changeset 478:f55844a06cc2

meth-lazy: misc. SPARC fixes
author twisti
date Thu, 12 Jul 2012 18:47:17 -0700
parents 71016edd5799
children f128e52774bf
files meth-lazy-7023639.patch
diffstat 1 files changed, 223 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/meth-lazy-7023639.patch	Thu Jul 12 00:50:46 2012 -0700
+++ b/meth-lazy-7023639.patch	Thu Jul 12 18:47:17 2012 -0700
@@ -45,16 +45,57 @@
    bind(StackOk);
  #endif // ASSERT
    assert( last_java_sp != G4_scratch, "bad register usage in set_last_Java_frame");
-@@ -2020,7 +2022,7 @@
+@@ -1650,23 +1652,28 @@
+ 
+ 
+ void RegistersForDebugging::print(outputStream* s) {
++  FlagSetting fs(Debugging, true);
+   int j;
+-  for ( j = 0;  j < 8;  ++j )
+-    if ( j != 6 ) s->print_cr("i%d = 0x%.16lx", j, i[j]);
+-    else          s->print_cr( "fp = 0x%.16lx",    i[j]);
++  for (j = 0; j < 8; ++j) {
++    if (j != 6) { s->print("i%d = ", j); os::print_location(s, i[j]); }
++    else        { s->print( "fp = "   ); os::print_location(s, i[j]); }
++  }
+   s->cr();
+ 
+-  for ( j = 0;  j < 8;  ++j )
+-    s->print_cr("l%d = 0x%.16lx", j, l[j]);
++  for (j = 0;  j < 8;  ++j) {
++    s->print("l%d = ", j); os::print_location(s, l[j]);
++  }
+   s->cr();
+ 
+-  for ( j = 0;  j < 8;  ++j )
+-    if ( j != 6 ) s->print_cr("o%d = 0x%.16lx", j, o[j]);
+-    else          s->print_cr( "sp = 0x%.16lx",    o[j]);
++  for (j = 0; j < 8; ++j) {
++    if (j != 6) { s->print("o%d = ", j); os::print_location(s, o[j]); }
++    else        { s->print( "sp = "   ); os::print_location(s, o[j]); }
++  }
+   s->cr();
+ 
+-  for ( j = 0;  j < 8;  ++j )
+-    s->print_cr("g%d = 0x%.16lx", j, g[j]);
++  for (j = 0; j < 8; ++j) {
++    s->print("g%d = ", j); os::print_location(s, g[j]);
++  }
+   s->cr();
+ 
+   // print out floats with compression
+@@ -2020,8 +2027,8 @@
    char* b = new char[1024];
    sprintf(b, "untested: %s", what);
  
 -  if ( ShowMessageBoxOnError )   stop(b);
-+  if ( ShowMessageBoxOnError )   STOP(b);
-   else                           warn(b);
- }
- 
-@@ -2998,26 +3000,60 @@
+-  else                           warn(b);
++  if (ShowMessageBoxOnError) { STOP(b); }
++  else                       { warn(b); }
+ }
+ 
+ 
+@@ -2998,26 +3005,60 @@
  }
  
  
@@ -108,7 +149,7 @@
 +  check_klass_subtype_fast_path(sub_klass, super_klass,
 +                                temp_reg, temp2_reg,
 +                                (did_save ? &L_pop_to_success : &L_success),
-+                                &L_failure, NULL);
++                                (did_save ? &L_pop_to_failure : &L_failure), NULL);
 +
 +  if (!did_save)
 +    save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2);
@@ -121,7 +162,7 @@
    restore();
    ba_short(L_success);
  
-@@ -3234,54 +3270,6 @@
+@@ -3234,54 +3275,6 @@
  }
  
  
@@ -176,7 +217,7 @@
  RegisterOrConstant MacroAssembler::argument_offset(RegisterOrConstant arg_slot,
                                                     Register temp_reg,
                                                     int extra_slot_offset) {
-@@ -3914,7 +3902,7 @@
+@@ -3914,7 +3907,7 @@
      ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t2);
      or3(t1, t2, t3);
      cmp_and_br_short(t1, t2, Assembler::greaterEqual, Assembler::pn, next);
@@ -185,7 +226,7 @@
      should_not_reach_here();
  
      bind(next);
-@@ -3922,13 +3910,13 @@
+@@ -3922,13 +3915,13 @@
      ld_ptr(G2_thread, in_bytes(JavaThread::tlab_end_offset()), t2);
      or3(t3, t2, t3);
      cmp_and_br_short(t1, t2, Assembler::lessEqual, Assembler::pn, next2);
@@ -201,7 +242,7 @@
      should_not_reach_here();
  
      bind(ok);
-@@ -3976,7 +3964,7 @@
+@@ -3976,7 +3969,7 @@
        btst(MinObjAlignmentInBytesMask, obj);
        br(Assembler::zero, false, Assembler::pt, L);
        delayed()->nop();
@@ -210,7 +251,7 @@
        bind(L);
      }
  #endif // ASSERT
-@@ -4013,7 +4001,7 @@
+@@ -4013,7 +4006,7 @@
        btst(MinObjAlignmentInBytesMask, top_addr);
        br(Assembler::zero, false, Assembler::pt, L);
        delayed()->nop();
@@ -219,7 +260,7 @@
        bind(L);
      }
  #endif // ASSERT
-@@ -4066,7 +4054,7 @@
+@@ -4066,7 +4059,7 @@
      btst(MinObjAlignmentInBytesMask, free);
      br(Assembler::zero, false, Assembler::pt, L);
      delayed()->nop();
@@ -228,7 +269,7 @@
      bind(L);
    }
  #endif // ASSERT
-@@ -4164,7 +4152,7 @@
+@@ -4164,7 +4157,7 @@
      ld_ptr(G2_thread, in_bytes(JavaThread::tlab_size_offset()), t2);
      sll_ptr(t2, LogHeapWordSize, t2);
      cmp_and_br_short(t1, t2, Assembler::equal, Assembler::pt, ok);
@@ -899,16 +940,15 @@
    Label L_ok, L_bad;
    BLOCK_COMMENT("verify_klass {");
    __ verify_oop(obj_reg);
-@@ -498,538 +91,421 @@
-   __ set(ExternalAddress(klass_addr), temp2_reg);
+@@ -499,537 +92,416 @@
    __ ld_ptr(Address(temp2_reg, 0), temp2_reg);
    __ cmp_and_brx_short(temp_reg, temp2_reg, Assembler::equal, Assembler::pt, L_ok);
-+  if (did_save)  __ restore();
    __ BIND(L_bad);
 -  __ stop(error_message);
++  if (did_save)  __ restore();
 +  __ STOP(error_message);
+   __ BIND(L_ok);
 +  if (did_save)  __ restore();
-   __ BIND(L_ok);
    BLOCK_COMMENT("} verify_klass");
  }
 +
@@ -1209,11 +1249,6 @@
 +                                                    Register member_reg,
 +                                                    bool for_compiler_entry) {
 +  assert(is_signature_polymorphic(iid), "expected invoke iid");
-+  assert(member_reg == G5_method, "only valid assignment");
- 
--static void load_vmargslot(MacroAssembler* _masm, Address vmargslot_addr, Register result) {
--  __ ldsw(vmargslot_addr, result);
--}
 +  // temps used in this code are not used in *either* compiled or interpreted calling sequences
 +  Register temp1 = (for_compiler_entry ? G1_scratch : O1);
 +  Register temp2 = (for_compiler_entry ? G4_scratch : O4);
@@ -1221,16 +1256,21 @@
 +  Register temp4 = (for_compiler_entry ? noreg      : O2);
 +  if (for_compiler_entry) {
 +    assert(receiver_reg == (iid == vmIntrinsics::_linkToStatic ? noreg : O0), "only valid assignment");
-+    assert_different_registers(member_reg, O0, O1, O2, O3, O4, O5);
 +    assert_different_registers(temp1,      O0, O1, O2, O3, O4, O5);
 +    assert_different_registers(temp2,      O0, O1, O2, O3, O4, O5);
 +    assert_different_registers(temp3,      O0, O1, O2, O3, O4, O5);
 +    assert_different_registers(temp4,      O0, O1, O2, O3, O4, O5);
 +  }
-+  assert_different_registers(temp1, temp2, temp3, temp4, receiver_reg);
-+  assert_different_registers(temp1, temp2, temp3, temp4, member_reg);
-+  if (!for_compiler_entry)
-+    assert_different_registers(temp1, temp2, temp3, temp4, O5_savedSP);  // don't trash lastSP
++  if (receiver_reg != noreg)  assert_different_registers(temp1, temp2, temp3, temp4, receiver_reg);
++  if (member_reg   != noreg)  assert_different_registers(temp1, temp2, temp3, temp4, member_reg);
++  if (!for_compiler_entry)    assert_different_registers(temp1, temp2, temp3, temp4, O5_savedSP);  // don't trash lastSP
+ 
+-static void load_vmargslot(MacroAssembler* _masm, Address vmargslot_addr, Register result) {
+-  __ ldsw(vmargslot_addr, result);
+-}
++  if (iid == vmIntrinsics::_invokeBasic) {
++    // indirect through MH.form.vmentry.vmtarget
++    jump_to_lambda_form(_masm, receiver_reg, G5_method, temp2, temp3, for_compiler_entry);
  
 -static RegisterOrConstant adjust_SP_and_Gargs_down_by_slots(MacroAssembler* _masm,
 -                                                            RegisterOrConstant arg_slots,
@@ -1245,10 +1285,6 @@
 -    __ sub(Gargs,        offset, Gargs);
 -    __ sub(SP,    masked_offset, SP   );
 -    return offset;
-+  if (iid == vmIntrinsics::_invokeBasic) {
-+    // indirect through MH.form.vmentry.vmtarget
-+    jump_to_lambda_form(_masm, receiver_reg, G5_method, temp2, temp3, for_compiler_entry);
-+
    } else {
 -#ifdef ASSERT
 +    // The method is a member invoker used by direct method handles.
@@ -1378,7 +1414,7 @@
 +      load_klass_from_Class(_masm, temp3_intf, temp2, temp4);
 +      __ verify_oop(temp3_intf);
 +
-+      Register G5_index = member_reg;
++      Register G5_index = G5_method;
 +      __ ld_ptr(member_vmindex, G5_index);
 +      if (VerifyMethodHandles) {
 +        Label L;
@@ -1796,7 +1832,7 @@
  
    if (Verbose) {
      // dumping last frame with frame::describe
-@@ -1090,6 +566,7 @@
+@@ -1090,6 +562,7 @@
  
      // mark saved_sp, if seems valid (may not be valid for some adapters)
      intptr_t *unbiased_sp = (intptr_t *)(STACK_BIAS+(uintptr_t)saved_sp);
@@ -1804,7 +1840,7 @@
      if ((unbiased_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (unbiased_sp < dump_fp)) {
        values.describe(-1, unbiased_sp, "*saved_sp+STACK_BIAS");
      }
-@@ -1097,10 +574,13 @@
+@@ -1097,10 +570,13 @@
      // Note: the unextended_sp may not be correct
      tty->print_cr("  stack layout:");
      values.print(p);
@@ -1822,7 +1858,7 @@
    }
  }
  
-@@ -1143,1260 +623,3 @@
+@@ -1143,1260 +619,3 @@
    BLOCK_COMMENT("} trace_method_handle");
  }
  #endif // PRODUCT
@@ -3875,7 +3911,19 @@
    __ call_from_interpreter(Rcall, Gargs, Rret);
  }
  
-@@ -2974,7 +3040,7 @@
+@@ -2965,16 +3031,16 @@
+   assert(byte_no == f2_byte, "use this argument");
+ 
+   Register Rscratch = G3_scratch;
+-  Register Rtemp = G4_scratch;
+-  Register Rret = Lscratch;
+-  Register Rrecv = G5_method;
++  Register Rtemp    = G4_scratch;
++  Register Rret     = Lscratch;
++  Register O0_recv  = O0;
+   Label notFinal;
+ 
+   load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, true, false, false);
    __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
  
    // Check for vfinal
@@ -3884,7 +3932,17 @@
    __ btst(Rret, G4_scratch);
    __ br(Assembler::zero, false, Assembler::pt, notFinal);
    __ delayed()->and3(Rret, 0xFF, G4_scratch);      // gets number of parameters
-@@ -2993,9 +3059,9 @@
+@@ -2986,27 +3052,27 @@
+   __ bind(notFinal);
+ 
+   __ mov(G5_method, Rscratch);  // better scratch register
+-  __ load_receiver(G4_scratch, O0);  // gets receiverOop
+-  // receiver is in O0
+-  __ verify_oop(O0);
++  __ load_receiver(G4_scratch, O0_recv);  // gets receiverOop
++  // receiver is in O0_recv
++  __ verify_oop(O0_recv);
+ 
    // get return address
    AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
    __ set(table, Rtemp);
@@ -3897,6 +3955,24 @@
    __ sll(Rret,  LogBytesPerWord, Rret);
    __ ld_ptr(Rtemp, Rret, Rret);         // get return address
  
+   // get receiver klass
+-  __ null_check(O0, oopDesc::klass_offset_in_bytes());
+-  __ load_klass(O0, Rrecv);
+-  __ verify_oop(Rrecv);
+-
+-  __ profile_virtual_call(Rrecv, O4);
+-
+-  generate_vtable_call(Rrecv, Rscratch, Rret);
++  __ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
++  __ load_klass(O0_recv, O0_recv);
++  __ verify_oop(O0_recv);
++
++  __ profile_virtual_call(O0_recv, O4);
++
++  generate_vtable_call(O0_recv, Rscratch, Rret);
+ }
+ 
+ void TemplateTable::fast_invokevfinal(int byte_no) {
 @@ -3036,9 +3102,9 @@
    // get return address
    AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
@@ -4001,7 +4077,7 @@
    __ btst(Rflags, Rscratch);
    __ br(Assembler::zero, false, Assembler::pt, notFinal);
    __ delayed()->nop();
-@@ -3144,36 +3182,20 @@
+@@ -3144,53 +3182,37 @@
    transition(vtos, vtos);
    assert(byte_no == f1_byte, "use this argument");
  
@@ -4011,13 +4087,13 @@
 -  Register Rinterface = G1_scratch;
 -  Register RklassOop = G5_method;
 -  Register Rflags = O1;
-+  const Register Rinterface = G1_scratch;
-+  const Register Rret       = G3_scratch;
-+  const Register Rindex     = Lscratch;
-+  const Register O0_recv    = O0;
-+  const Register Rflags     = O1;
-+  const Register RklassOop  = G5_method;
-+  const Register Rscratch   = G4_scratch;
++  const Register Rinterface  = G1_scratch;
++  const Register Rret        = G3_scratch;
++  const Register Rindex      = Lscratch;
++  const Register O0_recv     = O0;
++  const Register O1_flags    = O1;
++  const Register O2_klassOop = O2;
++  const Register Rscratch    = G4_scratch;
    assert_different_registers(Rscratch, G5_method);
  
 -  load_invoke_cp_cache_entry(byte_no, Rinterface, Rindex, Rflags, /*virtual*/ false, false, false);
@@ -4038,25 +4114,69 @@
 -  ConstantPoolCacheEntry::verify_tosBits();
 -  __ sll(Rret,  LogBytesPerWord, Rret);
 -  __ ld_ptr(Rscratch, Rret, Rret);      // get return address
-+  prepare_invoke(byte_no, Rinterface, Rret, Rindex, O0_recv, Rflags);
++  prepare_invoke(byte_no, Rinterface, Rret, Rindex, O0_recv, O1_flags);
  
    // get receiver klass
 -  __ null_check(O0, oopDesc::klass_offset_in_bytes());
 -  __ load_klass(O0, RklassOop);
+-  __ verify_oop(RklassOop);
 +  __ null_check(O0_recv, oopDesc::klass_offset_in_bytes());
-+  __ load_klass(O0_recv, RklassOop);
-   __ verify_oop(RklassOop);
++  __ load_klass(O0_recv, O2_klassOop);
++  __ verify_oop(O2_klassOop);
  
    // Special case of invokeinterface called for virtual method of
-@@ -3181,7 +3203,7 @@
+   // java.lang.Object.  See cpCacheOop.cpp for details.
    // This code isn't produced by javac, but could be produced by
    // another compliant java compiler.
    Label notMethod;
 -  __ set((1 << ConstantPoolCacheEntry::methodInterface), Rscratch);
+-  __ btst(Rflags, Rscratch);
 +  __ set((1 << ConstantPoolCacheEntry::is_forced_virtual_shift), Rscratch);
-   __ btst(Rflags, Rscratch);
++  __ btst(O1_flags, Rscratch);
    __ br(Assembler::zero, false, Assembler::pt, notMethod);
    __ delayed()->nop();
+ 
+-  invokeinterface_object_method(RklassOop, Rinterface, Rret, Rflags);
++  invokeinterface_object_method(O2_klassOop, Rinterface, Rret, O1_flags);
+ 
+   __ bind(notMethod);
+ 
+-  __ profile_virtual_call(RklassOop, O4);
++  __ profile_virtual_call(O2_klassOop, O4);
+ 
+   //
+   // find entry point to call
+@@ -3199,9 +3221,9 @@
+   // compute start of first itableOffsetEntry (which is at end of vtable)
+   const int base = instanceKlass::vtable_start_offset() * wordSize;
+   Label search;
+-  Register Rtemp = Rflags;
+-
+-  __ ld(RklassOop, instanceKlass::vtable_length_offset() * wordSize, Rtemp);
++  Register Rtemp = O1_flags;
++
++  __ ld(O2_klassOop, instanceKlass::vtable_length_offset() * wordSize, Rtemp);
+   if (align_object_offset(1) > 1) {
+     __ round_to(Rtemp, align_object_offset(1));
+   }
+@@ -3212,7 +3234,7 @@
+     __ set(base, Rscratch);
+     __ add(Rscratch, Rtemp, Rtemp);
+   }
+-  __ add(RklassOop, Rtemp, Rscratch);
++  __ add(O2_klassOop, Rtemp, Rscratch);
+ 
+   __ bind(search);
+ 
+@@ -3244,7 +3266,7 @@
+   assert(itableMethodEntry::method_offset_in_bytes() == 0, "adjust instruction below");
+   __ sll(Rindex, exact_log2(itableMethodEntry::size() * wordSize), Rindex);       // Rindex *= 8;
+   __ add(Rscratch, Rindex, Rscratch);
+-  __ ld_ptr(RklassOop, Rscratch, G5_method);
++  __ ld_ptr(O2_klassOop, Rscratch, G5_method);
+ 
+   // Check for abstract method error.
+   {
 @@ -3260,13 +3282,42 @@
  
    __ verify_oop(G5_method);
@@ -10315,9 +10435,12 @@
    assert(!callee->is_native(), "callee must not be native");
    if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) {
      INLINE_BAILOUT("inlining prohibited by policy");
-@@ -3508,8 +3600,8 @@
+@@ -3508,10 +3600,10 @@
+   if (callee->force_inline() || callee->should_inline()) {
+     // ignore heuristic controls on inlining
      if (callee->force_inline())
-       CompileTask::print_inlining(callee, scope()->level(), bci(), "force inline by annotation");
+-      CompileTask::print_inlining(callee, scope()->level(), bci(), "force inline by annotation");
++      print_inlining(callee, "force inline by annotation");
    } else {
 -    if (inline_level() > MaxInlineLevel                         ) INLINE_BAILOUT("too-deep inlining");
 -    if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining");
@@ -10326,7 +10449,7 @@
      if (callee->code_size_for_inlining() > max_inline_size()    ) INLINE_BAILOUT("callee is too large");
  
      // don't inline throwable methods unless the inlining tree is rooted in a throwable class
-@@ -3528,28 +3621,25 @@
+@@ -3530,28 +3622,25 @@
      if (compilation()->env()->num_inlined_bytecodes() > DesiredMethodLimit) {
        INLINE_BAILOUT("total inlining greater than DesiredMethodLimit");
      }
@@ -10361,7 +10484,7 @@
      // note: null check must happen even if first instruction of callee does
      //       an implicit null check since the callee is in a different scope
      //       and we must make sure exception handling does the right thing
-@@ -3565,7 +3655,7 @@
+@@ -3567,7 +3656,7 @@
      compilation()->set_would_profile(true);
  
      if (profile_calls()) {
@@ -10370,7 +10493,7 @@
      }
    }
  
-@@ -3574,7 +3664,7 @@
+@@ -3576,7 +3665,7 @@
    // fall-through of control flow, all return instructions of the
    // callee will need to be replaced by Goto's pointing to this
    // continuation point.
@@ -10379,7 +10502,7 @@
    bool continuation_existed = true;
    if (cont == NULL) {
      cont = new BlockBegin(next_bci());
-@@ -3607,17 +3697,10 @@
+@@ -3609,17 +3698,10 @@
    // note: this will also ensure that all arguments are computed before being passed
    ValueStack* callee_state = state();
    ValueStack* caller_state = state()->caller_state();
@@ -10401,7 +10524,7 @@
    }
  
    // Remove args from stack.
-@@ -3693,29 +3776,27 @@
+@@ -3695,29 +3777,27 @@
    // block merging. This allows load elimination and CSE to take place
    // across multiple callee scopes if they are relatively simple, and
    // is currently essential to making inlining profitable.
@@ -10450,7 +10573,7 @@
      }
    }
  
-@@ -3733,114 +3814,88 @@
+@@ -3735,114 +3815,88 @@
  
  
  bool GraphBuilder::for_method_handle_inline(ciMethod* callee) {
@@ -10642,7 +10765,7 @@
    return false;
  }
  
-@@ -4032,22 +4087,24 @@
+@@ -4034,22 +4088,24 @@
  }
  
  
@@ -12064,7 +12187,7 @@
 diff --git a/src/share/vm/classfile/classFileParser.hpp b/src/share/vm/classfile/classFileParser.hpp
 --- a/src/share/vm/classfile/classFileParser.hpp
 +++ b/src/share/vm/classfile/classFileParser.hpp
-@@ -68,6 +68,9 @@
+@@ -86,6 +86,9 @@
      enum ID {
        _unknown = 0,
        _method_ForceInline,
@@ -25551,15 +25674,20 @@
      }
    }
  #endif
-@@ -1187,6 +1160,7 @@
+@@ -1186,8 +1159,10 @@
+                                      call_info, CHECK_(methodHandle()));
    methodHandle callee_method = call_info.selected_method();
  
-   assert((!is_virtual && invoke_code == Bytecodes::_invokestatic) ||
-+         (!is_virtual && invoke_code == Bytecodes::_invokehandle) ||
-          ( is_virtual && invoke_code != Bytecodes::_invokestatic), "inconsistent bytecode");
+-  assert((!is_virtual && invoke_code == Bytecodes::_invokestatic) ||
+-         ( is_virtual && invoke_code != Bytecodes::_invokestatic), "inconsistent bytecode");
++  assert((!is_virtual && invoke_code == Bytecodes::_invokestatic ) ||
++         (!is_virtual && invoke_code == Bytecodes::_invokehandle ) ||
++         (!is_virtual && invoke_code == Bytecodes::_invokedynamic) ||
++         ( is_virtual && invoke_code != Bytecodes::_invokestatic ), "inconsistent bytecode");
  
  #ifndef PRODUCT
-@@ -1202,16 +1176,17 @@
+   // tracing/debugging/statistics
+@@ -1202,16 +1177,17 @@
        (is_optimized) ? "optimized " : "", (is_virtual) ? "virtual" : "static",
        Bytecodes::name(invoke_code));
      callee_method->print_short_name(tty);
@@ -25583,7 +25711,7 @@
  
    // Compute entry points. This might require generation of C2I converter
    // frames, so we cannot be holding any locks here. Furthermore, the
-@@ -1284,7 +1259,6 @@
+@@ -1284,7 +1260,6 @@
    assert(stub_frame.is_runtime_frame(), "sanity check");
    frame caller_frame = stub_frame.sender(&reg_map);
    assert(!caller_frame.is_interpreted_frame() && !caller_frame.is_entry_frame(), "unexpected frame");
@@ -25591,7 +25719,7 @@
  #endif /* ASSERT */
  
    methodHandle callee_method;
-@@ -1320,21 +1294,9 @@
+@@ -1320,21 +1295,9 @@
    address   sender_pc = caller_frame.pc();
    CodeBlob* sender_cb = caller_frame.cb();
    nmethod*  sender_nm = sender_cb->as_nmethod_or_null();
@@ -25614,7 +25742,7 @@
      methodOop callee = thread->callee_target();
      guarantee(callee != NULL && callee->is_method(), "bad handshake");
      thread->set_vm_result(callee);
-@@ -1677,12 +1639,6 @@
+@@ -1677,12 +1640,6 @@
    // Get the return PC for the passed caller PC.
    address return_pc = caller_pc + frame::pc_return_offset;
  
@@ -25627,7 +25755,7 @@
    // There is a benign race here. We could be attempting to patch to a compiled
    // entry point at the same time the callee is being deoptimized. If that is
    // the case then entry_point may in fact point to a c2i and we'd patch the
-@@ -1788,97 +1744,6 @@
+@@ -1788,97 +1745,6 @@
    return generate_class_cast_message(objName, targetKlass->external_name());
  }
  
@@ -25725,7 +25853,7 @@
  char* SharedRuntime::generate_class_cast_message(
      const char* objName, const char* targetKlassName, const char* desc) {
    size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1;
-@@ -2119,8 +1984,17 @@
+@@ -2119,8 +1985,17 @@
  // that allows sharing of adapters for the same calling convention.
  class AdapterFingerPrint : public CHeapObj {
   private:
@@ -25744,7 +25872,7 @@
      int* _fingerprint;
    } _value;
    int _length; // A negative length indicates the fingerprint is in the compact form,
-@@ -2129,8 +2003,7 @@
+@@ -2129,8 +2004,7 @@
    // Remap BasicTypes that are handled equivalently by the adapters.
    // These are correct for the current system but someday it might be
    // necessary to make this mapping platform dependent.
@@ -25754,7 +25882,7 @@
      switch(in) {
        case T_BOOLEAN:
        case T_BYTE:
-@@ -2141,6 +2014,8 @@
+@@ -2141,6 +2015,8 @@
  
        case T_OBJECT:
        case T_ARRAY:
@@ -25763,7 +25891,7 @@
  #ifdef _LP64
          return T_LONG;
  #else
-@@ -2165,8 +2040,9 @@
+@@ -2165,8 +2041,9 @@
      // The fingerprint is based on the BasicType signature encoded
      // into an array of ints with eight entries per int.
      int* ptr;
@@ -25775,7 +25903,7 @@
        _value._compact[0] = _value._compact[1] = _value._compact[2] = 0;
        // Storing the signature encoded as signed chars hits about 98%
        // of the time.
-@@ -2182,10 +2058,12 @@
+@@ -2182,10 +2059,12 @@
      int sig_index = 0;
      for (int index = 0; index < len; index++) {
        int value = 0;
@@ -25792,7 +25920,7 @@
        }
        ptr[index] = value;
      }
-@@ -2235,6 +2113,7 @@
+@@ -2235,6 +2114,7 @@
        return false;
      }
      if (_length < 0) {
@@ -25800,7 +25928,7 @@
        return _value._compact[0] == other->_value._compact[0] &&
               _value._compact[1] == other->_value._compact[1] &&
               _value._compact[2] == other->_value._compact[2];
-@@ -2531,13 +2410,17 @@
+@@ -2531,13 +2411,17 @@
      entry->relocate(B->content_begin());
  #ifndef PRODUCT
      // debugging suppport
@@ -25823,7 +25951,7 @@
      }
  #endif
  
-@@ -2561,11 +2444,25 @@
+@@ -2561,11 +2445,25 @@
    return entry;
  }
  
@@ -25850,7 +25978,7 @@
  }
  
  
-@@ -2614,7 +2511,9 @@
+@@ -2614,7 +2512,9 @@
    ResourceMark rm;
    nmethod* nm = NULL;
  
@@ -25861,7 +25989,22 @@
  
    {
      // perform the work while holding the lock, but perform any printing outside the lock
-@@ -2939,18 +2838,22 @@
+@@ -2651,9 +2551,11 @@
+       assert( i==total_args_passed, "" );
+       BasicType ret_type = ss.type();
+ 
+-      // Now get the compiled-Java layout as input arguments
+-      int comp_args_on_stack;
+-      comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, false);
++      // Now get the compiled-Java layout as input (or output) arguments.
++      // NOTE: Stubs for compiled entry points of method handle intrinsics
++      // are just trampolines so the argument registers must be outgoing ones.
++      const bool is_outgoing = method->is_method_handle_intrinsic();
++      int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed, is_outgoing);
+ 
+       // Generate the compiled-to-native wrapper code
+       nm = SharedRuntime::generate_native_wrapper(&_masm,
+@@ -2939,18 +2841,22 @@
    AdapterHandlerTableIterator iter(_adapters);
    while (iter.has_next()) {
      AdapterHandlerEntry* a = iter.next();