src/cpu/sparc/vm/methodHandles_sparc.cpp

Sat, 30 Oct 2010 13:08:23 -0700

author
jrose
date
Sat, 30 Oct 2010 13:08:23 -0700
changeset 2268
3b2dea75431e
parent 2266
fff777a71346
child 2271
e62345fd6a46
permissions
-rw-r--r--

6984311: JSR 292 needs optional bootstrap method parameters
Summary: Allow CONSTANT_InvokeDynamic nodes to have any number of extra operands.
Reviewed-by: twisti

     1 /*
     2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "incls/_precompiled.incl"
    26 #include "incls/_methodHandles_sparc.cpp.incl"
    28 #define __ _masm->
    30 #ifdef PRODUCT
    31 #define BLOCK_COMMENT(str) /* nothing */
    32 #else
    33 #define BLOCK_COMMENT(str) __ block_comment(str)
    34 #endif
    36 #define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
    38 address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm,
    39                                                 address interpreted_entry) {
    40   // Just before the actual machine code entry point, allocate space
    41   // for a MethodHandleEntry::Data record, so that we can manage everything
    42   // from one base pointer.
    43   __ align(wordSize);
    44   address target = __ pc() + sizeof(Data);
    45   while (__ pc() < target) {
    46     __ nop();
    47     __ align(wordSize);
    48   }
    50   MethodHandleEntry* me = (MethodHandleEntry*) __ pc();
    51   me->set_end_address(__ pc());         // set a temporary end_address
    52   me->set_from_interpreted_entry(interpreted_entry);
    53   me->set_type_checking_entry(NULL);
    55   return (address) me;
    56 }
    58 MethodHandleEntry* MethodHandleEntry::finish_compiled_entry(MacroAssembler* _masm,
    59                                                 address start_addr) {
    60   MethodHandleEntry* me = (MethodHandleEntry*) start_addr;
    61   assert(me->end_address() == start_addr, "valid ME");
    63   // Fill in the real end_address:
    64   __ align(wordSize);
    65   me->set_end_address(__ pc());
    67   return me;
    68 }
    71 // Code generation
    72 address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm) {
    73   // I5_savedSP: sender SP (must preserve)
    74   // G4 (Gargs): incoming argument list (must preserve)
    75   // G5_method:  invoke methodOop; becomes method type.
    76   // G3_method_handle: receiver method handle (must load from sp[MethodTypeForm.vmslots])
    77   // O0, O1: garbage temps, blown away
    78   Register O0_argslot = O0;
    79   Register O1_scratch = O1;
    80   Register O2_scratch = O2;
    81   Register O3_scratch = O3;
    82   Register O4_argbase = O4;
    83   Register O5_mtype   = O5;
    85   // emit WrongMethodType path first, to enable back-branch from main path
    86   Label wrong_method_type;
    87   __ bind(wrong_method_type);
    88   Label invoke_generic_slow_path;
    89   assert(methodOopDesc::intrinsic_id_size_in_bytes() == sizeof(u1), "");;
    90   __ ldub(Address(G5_method, methodOopDesc::intrinsic_id_offset_in_bytes()), O1_scratch);
    91   __ cmp(O1_scratch, (int) vmIntrinsics::_invokeExact);
    92   __ brx(Assembler::notEqual, false, Assembler::pt, invoke_generic_slow_path);
    93   __ delayed()->nop();
    94   __ mov(O5_mtype, G5_method_type);  // required by throw_WrongMethodType
    95   // mov(G3_method_handle, G3_method_handle);  // already in this register
    96   __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch);
    97   __ delayed()->nop();
    99   // here's where control starts out:
   100   __ align(CodeEntryAlignment);
   101   address entry_point = __ pc();
   103   // fetch the MethodType from the method handle
   104   {
   105     Register tem = G5_method;
   106     for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) {
   107       __ ld_ptr(Address(tem, *pchase), O5_mtype);
   108       tem = O5_mtype;          // in case there is another indirection
   109     }
   110   }
   112   // given the MethodType, find out where the MH argument is buried
   113   __ load_heap_oop(Address(O5_mtype,   __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)),        O0_argslot);
   114   __ ldsw(  Address(O0_argslot, __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, O1_scratch)), O0_argslot);
   115   __ add(Gargs, __ argument_offset(O0_argslot, 1), O4_argbase);
   116   // Note: argument_address uses its input as a scratch register!
   117   __ ld_ptr(Address(O4_argbase, -Interpreter::stackElementSize), G3_method_handle);
   119   trace_method_handle(_masm, "invokeExact");
   121   __ check_method_handle_type(O5_mtype, G3_method_handle, O1_scratch, wrong_method_type);
   122   __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   124   // for invokeGeneric (only), apply argument and result conversions on the fly
   125   __ bind(invoke_generic_slow_path);
   126 #ifdef ASSERT
   127   { Label L;
   128     __ ldub(Address(G5_method, methodOopDesc::intrinsic_id_offset_in_bytes()), O1_scratch);
   129     __ cmp(O1_scratch, (int) vmIntrinsics::_invokeGeneric);
   130     __ brx(Assembler::equal, false, Assembler::pt, L);
   131     __ delayed()->nop();
   132     __ stop("bad methodOop::intrinsic_id");
   133     __ bind(L);
   134   }
   135 #endif //ASSERT
   137   // make room on the stack for another pointer:
   138   insert_arg_slots(_masm, 2 * stack_move_unit(), _INSERT_REF_MASK,
   139                    O4_argbase, O1_scratch, O2_scratch, O3_scratch);
   140   // load up an adapter from the calling type (Java weaves this)
   141   Register O2_form    = O2_scratch;
   142   Register O3_adapter = O3_scratch;
   143   __ load_heap_oop(Address(O5_mtype, __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, O1_scratch)), O2_form);
   144   // load_heap_oop(Address(O2_form,  __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter);
   145   // deal with old JDK versions:
   146   __ add(   Address(O2_form,  __ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter);
   147   __ cmp(O3_adapter, O2_form);
   148   Label sorry_no_invoke_generic;
   149   __ brx(Assembler::lessUnsigned, false, Assembler::pn, sorry_no_invoke_generic);
   150   __ delayed()->nop();
   152   __ load_heap_oop(Address(O3_adapter, 0), O3_adapter);
   153   __ tst(O3_adapter);
   154   __ brx(Assembler::zero, false, Assembler::pn, sorry_no_invoke_generic);
   155   __ delayed()->nop();
   156   __ st_ptr(O3_adapter, Address(O4_argbase, 1 * Interpreter::stackElementSize));
   157   // As a trusted first argument, pass the type being called, so the adapter knows
   158   // the actual types of the arguments and return values.
   159   // (Generic invokers are shared among form-families of method-type.)
   160   __ st_ptr(O5_mtype,   Address(O4_argbase, 0 * Interpreter::stackElementSize));
   161   // FIXME: assert that O3_adapter is of the right method-type.
   162   __ mov(O3_adapter, G3_method_handle);
   163   trace_method_handle(_masm, "invokeGeneric");
   164   __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   166   __ bind(sorry_no_invoke_generic); // no invokeGeneric implementation available!
   167   __ mov(O5_mtype, G5_method_type);  // required by throw_WrongMethodType
   168   // mov(G3_method_handle, G3_method_handle);  // already in this register
   169   __ jump_to(AddressLiteral(Interpreter::throw_WrongMethodType_entry()), O1_scratch);
   170   __ delayed()->nop();
   172   return entry_point;
   173 }
   176 #ifdef ASSERT
   177 static void verify_argslot(MacroAssembler* _masm, Register argslot_reg, Register temp_reg, const char* error_message) {
   178   // Verify that argslot lies within (Gargs, FP].
   179   Label L_ok, L_bad;
   180   BLOCK_COMMENT("{ verify_argslot");
   181 #ifdef _LP64
   182   __ add(FP, STACK_BIAS, temp_reg);
   183   __ cmp(argslot_reg, temp_reg);
   184 #else
   185   __ cmp(argslot_reg, FP);
   186 #endif
   187   __ brx(Assembler::greaterUnsigned, false, Assembler::pn, L_bad);
   188   __ delayed()->nop();
   189   __ cmp(Gargs, argslot_reg);
   190   __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, L_ok);
   191   __ delayed()->nop();
   192   __ bind(L_bad);
   193   __ stop(error_message);
   194   __ bind(L_ok);
   195   BLOCK_COMMENT("} verify_argslot");
   196 }
   197 #endif
   200 // Helper to insert argument slots into the stack.
   201 // arg_slots must be a multiple of stack_move_unit() and <= 0
   202 void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
   203                                      RegisterOrConstant arg_slots,
   204                                      int arg_mask,
   205                                      Register argslot_reg,
   206                                      Register temp_reg, Register temp2_reg, Register temp3_reg) {
   207   assert(temp3_reg != noreg, "temp3 required");
   208   assert_different_registers(argslot_reg, temp_reg, temp2_reg, temp3_reg,
   209                              (!arg_slots.is_register() ? Gargs : arg_slots.as_register()));
   211 #ifdef ASSERT
   212   verify_argslot(_masm, argslot_reg, temp_reg, "insertion point must fall within current frame");
   213   if (arg_slots.is_register()) {
   214     Label L_ok, L_bad;
   215     __ cmp(arg_slots.as_register(), (int32_t) NULL_WORD);
   216     __ br(Assembler::greater, false, Assembler::pn, L_bad);
   217     __ delayed()->nop();
   218     __ btst(-stack_move_unit() - 1, arg_slots.as_register());
   219     __ br(Assembler::zero, false, Assembler::pt, L_ok);
   220     __ delayed()->nop();
   221     __ bind(L_bad);
   222     __ stop("assert arg_slots <= 0 and clear low bits");
   223     __ bind(L_ok);
   224   } else {
   225     assert(arg_slots.as_constant() <= 0, "");
   226     assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
   227   }
   228 #endif // ASSERT
   230 #ifdef _LP64
   231   if (arg_slots.is_register()) {
   232     // Was arg_slots register loaded as signed int?
   233     Label L_ok;
   234     __ sll(arg_slots.as_register(), BitsPerInt, temp_reg);
   235     __ sra(temp_reg, BitsPerInt, temp_reg);
   236     __ cmp(arg_slots.as_register(), temp_reg);
   237     __ br(Assembler::equal, false, Assembler::pt, L_ok);
   238     __ delayed()->nop();
   239     __ stop("arg_slots register not loaded as signed int");
   240     __ bind(L_ok);
   241   }
   242 #endif
   244   // Make space on the stack for the inserted argument(s).
   245   // Then pull down everything shallower than argslot_reg.
   246   // The stacked return address gets pulled down with everything else.
   247   // That is, copy [sp, argslot) downward by -size words.  In pseudo-code:
   248   //   sp -= size;
   249   //   for (temp = sp + size; temp < argslot; temp++)
   250   //     temp[-size] = temp[0]
   251   //   argslot -= size;
   252   BLOCK_COMMENT("insert_arg_slots {");
   253   RegisterOrConstant offset = __ regcon_sll_ptr(arg_slots, LogBytesPerWord, temp3_reg);
   255   // Keep the stack pointer 2*wordSize aligned.
   256   const int TwoWordAlignmentMask = right_n_bits(LogBytesPerWord + 1);
   257   RegisterOrConstant masked_offset = __ regcon_andn_ptr(offset, TwoWordAlignmentMask, temp_reg);
   258   __ add(SP, masked_offset, SP);
   260   __ mov(Gargs, temp_reg);  // source pointer for copy
   261   __ add(Gargs, offset, Gargs);
   263   {
   264     Label loop;
   265     __ BIND(loop);
   266     // pull one word down each time through the loop
   267     __ ld_ptr(Address(temp_reg, 0), temp2_reg);
   268     __ st_ptr(temp2_reg, Address(temp_reg, offset));
   269     __ add(temp_reg, wordSize, temp_reg);
   270     __ cmp(temp_reg, argslot_reg);
   271     __ brx(Assembler::less, false, Assembler::pt, loop);
   272     __ delayed()->nop();  // FILLME
   273   }
   275   // Now move the argslot down, to point to the opened-up space.
   276   __ add(argslot_reg, offset, argslot_reg);
   277   BLOCK_COMMENT("} insert_arg_slots");
   278 }
   281 // Helper to remove argument slots from the stack.
   282 // arg_slots must be a multiple of stack_move_unit() and >= 0
   283 void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
   284                                      RegisterOrConstant arg_slots,
   285                                      Register argslot_reg,
   286                                      Register temp_reg, Register temp2_reg, Register temp3_reg) {
   287   assert(temp3_reg != noreg, "temp3 required");
   288   assert_different_registers(argslot_reg, temp_reg, temp2_reg, temp3_reg,
   289                              (!arg_slots.is_register() ? Gargs : arg_slots.as_register()));
   291   RegisterOrConstant offset = __ regcon_sll_ptr(arg_slots, LogBytesPerWord, temp3_reg);
   293 #ifdef ASSERT
   294   // Verify that [argslot..argslot+size) lies within (Gargs, FP).
   295   __ add(argslot_reg, offset, temp2_reg);
   296   verify_argslot(_masm, temp2_reg, temp_reg, "deleted argument(s) must fall within current frame");
   297   if (arg_slots.is_register()) {
   298     Label L_ok, L_bad;
   299     __ cmp(arg_slots.as_register(), (int32_t) NULL_WORD);
   300     __ br(Assembler::less, false, Assembler::pn, L_bad);
   301     __ delayed()->nop();
   302     __ btst(-stack_move_unit() - 1, arg_slots.as_register());
   303     __ br(Assembler::zero, false, Assembler::pt, L_ok);
   304     __ delayed()->nop();
   305     __ bind(L_bad);
   306     __ stop("assert arg_slots >= 0 and clear low bits");
   307     __ bind(L_ok);
   308   } else {
   309     assert(arg_slots.as_constant() >= 0, "");
   310     assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
   311   }
   312 #endif // ASSERT
   314   BLOCK_COMMENT("remove_arg_slots {");
   315   // Pull up everything shallower than argslot.
   316   // Then remove the excess space on the stack.
   317   // The stacked return address gets pulled up with everything else.
   318   // That is, copy [sp, argslot) upward by size words.  In pseudo-code:
   319   //   for (temp = argslot-1; temp >= sp; --temp)
   320   //     temp[size] = temp[0]
   321   //   argslot += size;
   322   //   sp += size;
   323   __ sub(argslot_reg, wordSize, temp_reg);  // source pointer for copy
   324   {
   325     Label loop;
   326     __ BIND(loop);
   327     // pull one word up each time through the loop
   328     __ ld_ptr(Address(temp_reg, 0), temp2_reg);
   329     __ st_ptr(temp2_reg, Address(temp_reg, offset));
   330     __ sub(temp_reg, wordSize, temp_reg);
   331     __ cmp(temp_reg, Gargs);
   332     __ brx(Assembler::greaterEqual, false, Assembler::pt, loop);
   333     __ delayed()->nop();  // FILLME
   334   }
   336   // Now move the argslot up, to point to the just-copied block.
   337   __ add(Gargs, offset, Gargs);
   338   // And adjust the argslot address to point at the deletion point.
   339   __ add(argslot_reg, offset, argslot_reg);
   341   // Keep the stack pointer 2*wordSize aligned.
   342   const int TwoWordAlignmentMask = right_n_bits(LogBytesPerWord + 1);
   343   RegisterOrConstant masked_offset = __ regcon_andn_ptr(offset, TwoWordAlignmentMask, temp_reg);
   344   __ add(SP, masked_offset, SP);
   345   BLOCK_COMMENT("} remove_arg_slots");
   346 }
   349 #ifndef PRODUCT
   350 extern "C" void print_method_handle(oop mh);
   351 void trace_method_handle_stub(const char* adaptername,
   352                               oopDesc* mh) {
   353   printf("MH %s mh="INTPTR_FORMAT"\n", adaptername, (intptr_t) mh);
   354   print_method_handle(mh);
   355 }
   356 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
   357   if (!TraceMethodHandles)  return;
   358   BLOCK_COMMENT("trace_method_handle {");
   359   // save: Gargs, O5_savedSP
   360   __ save_frame(16);
   361   __ set((intptr_t) adaptername, O0);
   362   __ mov(G3_method_handle, O1);
   363   __ mov(G3_method_handle, L3);
   364   __ mov(Gargs, L4);
   365   __ mov(G5_method_type, L5);
   366   __ call_VM_leaf(L7, CAST_FROM_FN_PTR(address, trace_method_handle_stub));
   368   __ mov(L3, G3_method_handle);
   369   __ mov(L4, Gargs);
   370   __ mov(L5, G5_method_type);
   371   __ restore();
   372   BLOCK_COMMENT("} trace_method_handle");
   373 }
   374 #endif // PRODUCT
   376 // which conversion op types are implemented here?
   377 int MethodHandles::adapter_conversion_ops_supported_mask() {
   378   return ((1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY)
   379          |(1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW)
   380          |(1<<sun_dyn_AdapterMethodHandle::OP_CHECK_CAST)
   381          |(1<<sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM)
   382          |(1<<sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM)
   383          |(1<<sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS)
   384          |(1<<sun_dyn_AdapterMethodHandle::OP_ROT_ARGS)
   385          |(1<<sun_dyn_AdapterMethodHandle::OP_DUP_ARGS)
   386          |(1<<sun_dyn_AdapterMethodHandle::OP_DROP_ARGS)
   387          //|(1<<sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG!
   388          );
   389   // FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
   390 }
   392 //------------------------------------------------------------------------------
   393 // MethodHandles::generate_method_handle_stub
   394 //
   395 // Generate an "entry" field for a method handle.
   396 // This determines how the method handle will respond to calls.
   397 void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
   398   // Here is the register state during an interpreted call,
   399   // as set up by generate_method_handle_interpreter_entry():
   400   // - G5: garbage temp (was MethodHandle.invoke methodOop, unused)
   401   // - G3: receiver method handle
   402   // - O5_savedSP: sender SP (must preserve)
   404   Register O0_argslot = O0;
   405   Register O1_scratch = O1;
   406   Register O2_scratch = O2;
   407   Register O3_scratch = O3;
   408   Register G5_index   = G5;
   410   guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
   412   // Some handy addresses:
   413   Address G5_method_fie(    G5_method,        in_bytes(methodOopDesc::from_interpreted_offset()));
   415   Address G3_mh_vmtarget(   G3_method_handle, java_dyn_MethodHandle::vmtarget_offset_in_bytes());
   417   Address G3_dmh_vmindex(   G3_method_handle, sun_dyn_DirectMethodHandle::vmindex_offset_in_bytes());
   419   Address G3_bmh_vmargslot( G3_method_handle, sun_dyn_BoundMethodHandle::vmargslot_offset_in_bytes());
   420   Address G3_bmh_argument(  G3_method_handle, sun_dyn_BoundMethodHandle::argument_offset_in_bytes());
   422   Address G3_amh_vmargslot( G3_method_handle, sun_dyn_AdapterMethodHandle::vmargslot_offset_in_bytes());
   423   Address G3_amh_argument ( G3_method_handle, sun_dyn_AdapterMethodHandle::argument_offset_in_bytes());
   424   Address G3_amh_conversion(G3_method_handle, sun_dyn_AdapterMethodHandle::conversion_offset_in_bytes());
   426   const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes();
   428   if (have_entry(ek)) {
   429     __ nop();  // empty stubs make SG sick
   430     return;
   431   }
   433   address interp_entry = __ pc();
   435   trace_method_handle(_masm, entry_name(ek));
   437   switch ((int) ek) {
   438   case _raise_exception:
   439     {
   440       // Not a real MH entry, but rather shared code for raising an
   441       // exception.  Extra local arguments are passed in scratch
   442       // registers, as required type in O3, failing object (or NULL)
   443       // in O2, failing bytecode type in O1.
   445       __ mov(O5_savedSP, SP);  // Cut the stack back to where the caller started.
   447       // Push arguments as if coming from the interpreter.
   448       Register O0_scratch = O0_argslot;
   449       int stackElementSize = Interpreter::stackElementSize;
   451       // Make space on the stack for the arguments and set Gargs
   452       // correctly.
   453       __ sub(SP, 4*stackElementSize, SP);  // Keep stack aligned.
   454       __ add(SP, (frame::varargs_offset)*wordSize - 1*Interpreter::stackElementSize + STACK_BIAS + BytesPerWord, Gargs);
   456       // void raiseException(int code, Object actual, Object required)
   457       __ st(    O1_scratch, Address(Gargs, 2*stackElementSize));  // code
   458       __ st_ptr(O2_scratch, Address(Gargs, 1*stackElementSize));  // actual
   459       __ st_ptr(O3_scratch, Address(Gargs, 0*stackElementSize));  // required
   461       Label no_method;
   462       // FIXME: fill in _raise_exception_method with a suitable sun.dyn method
   463       __ set(AddressLiteral((address) &_raise_exception_method), G5_method);
   464       __ ld_ptr(Address(G5_method, 0), G5_method);
   465       __ tst(G5_method);
   466       __ brx(Assembler::zero, false, Assembler::pn, no_method);
   467       __ delayed()->nop();
   469       int jobject_oop_offset = 0;
   470       __ ld_ptr(Address(G5_method, jobject_oop_offset), G5_method);
   471       __ tst(G5_method);
   472       __ brx(Assembler::zero, false, Assembler::pn, no_method);
   473       __ delayed()->nop();
   475       __ verify_oop(G5_method);
   476       __ jump_indirect_to(G5_method_fie, O1_scratch);
   477       __ delayed()->nop();
   479       // If we get here, the Java runtime did not do its job of creating the exception.
   480       // Do something that is at least causes a valid throw from the interpreter.
   481       __ bind(no_method);
   482       __ unimplemented("_raise_exception no method");
   483     }
   484     break;
   486   case _invokestatic_mh:
   487   case _invokespecial_mh:
   488     {
   489       __ load_heap_oop(G3_mh_vmtarget, G5_method);  // target is a methodOop
   490       __ verify_oop(G5_method);
   491       // Same as TemplateTable::invokestatic or invokespecial,
   492       // minus the CP setup and profiling:
   493       if (ek == _invokespecial_mh) {
   494         // Must load & check the first argument before entering the target method.
   495         __ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch);
   496         __ ld_ptr(__ argument_address(O0_argslot), G3_method_handle);
   497         __ null_check(G3_method_handle);
   498         __ verify_oop(G3_method_handle);
   499       }
   500       __ jump_indirect_to(G5_method_fie, O1_scratch);
   501       __ delayed()->nop();
   502     }
   503     break;
   505   case _invokevirtual_mh:
   506     {
   507       // Same as TemplateTable::invokevirtual,
   508       // minus the CP setup and profiling:
   510       // Pick out the vtable index and receiver offset from the MH,
   511       // and then we can discard it:
   512       __ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch);
   513       __ ldsw(G3_dmh_vmindex, G5_index);
   514       // Note:  The verifier allows us to ignore G3_mh_vmtarget.
   515       __ ld_ptr(__ argument_address(O0_argslot, -1), G3_method_handle);
   516       __ null_check(G3_method_handle, oopDesc::klass_offset_in_bytes());
   518       // Get receiver klass:
   519       Register O0_klass = O0_argslot;
   520       __ load_klass(G3_method_handle, O0_klass);
   521       __ verify_oop(O0_klass);
   523       // Get target methodOop & entry point:
   524       const int base = instanceKlass::vtable_start_offset() * wordSize;
   525       assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
   527       __ sll_ptr(G5_index, LogBytesPerWord, G5_index);
   528       __ add(O0_klass, G5_index, O0_klass);
   529       Address vtable_entry_addr(O0_klass, base + vtableEntry::method_offset_in_bytes());
   530       __ ld_ptr(vtable_entry_addr, G5_method);
   532       __ verify_oop(G5_method);
   533       __ jump_indirect_to(G5_method_fie, O1_scratch);
   534       __ delayed()->nop();
   535     }
   536     break;
   538   case _invokeinterface_mh:
   539     {
   540       // Same as TemplateTable::invokeinterface,
   541       // minus the CP setup and profiling:
   542       __ load_method_handle_vmslots(O0_argslot, G3_method_handle, O1_scratch);
   543       Register O1_intf  = O1_scratch;
   544       __ load_heap_oop(G3_mh_vmtarget, O1_intf);
   545       __ ldsw(G3_dmh_vmindex, G5_index);
   546       __ ld_ptr(__ argument_address(O0_argslot, -1), G3_method_handle);
   547       __ null_check(G3_method_handle, oopDesc::klass_offset_in_bytes());
   549       // Get receiver klass:
   550       Register O0_klass = O0_argslot;
   551       __ load_klass(G3_method_handle, O0_klass);
   552       __ verify_oop(O0_klass);
   554       // Get interface:
   555       Label no_such_interface;
   556       __ verify_oop(O1_intf);
   557       __ lookup_interface_method(O0_klass, O1_intf,
   558                                  // Note: next two args must be the same:
   559                                  G5_index, G5_method,
   560                                  O2_scratch,
   561                                  O3_scratch,
   562                                  no_such_interface);
   564       __ verify_oop(G5_method);
   565       __ jump_indirect_to(G5_method_fie, O1_scratch);
   566       __ delayed()->nop();
   568       __ bind(no_such_interface);
   569       // Throw an exception.
   570       // For historical reasons, it will be IncompatibleClassChangeError.
   571       __ unimplemented("not tested yet");
   572       __ ld_ptr(Address(O1_intf, java_mirror_offset), O3_scratch);  // required interface
   573       __ mov(O0_klass, O2_scratch);  // bad receiver
   574       __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot);
   575       __ delayed()->mov(Bytecodes::_invokeinterface, O1_scratch);  // who is complaining?
   576     }
   577     break;
   579   case _bound_ref_mh:
   580   case _bound_int_mh:
   581   case _bound_long_mh:
   582   case _bound_ref_direct_mh:
   583   case _bound_int_direct_mh:
   584   case _bound_long_direct_mh:
   585     {
   586       const bool direct_to_method = (ek >= _bound_ref_direct_mh);
   587       BasicType arg_type  = T_ILLEGAL;
   588       int       arg_mask  = _INSERT_NO_MASK;
   589       int       arg_slots = -1;
   590       get_ek_bound_mh_info(ek, arg_type, arg_mask, arg_slots);
   592       // Make room for the new argument:
   593       __ ldsw(G3_bmh_vmargslot, O0_argslot);
   594       __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
   596       insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask, O0_argslot, O1_scratch, O2_scratch, G5_index);
   598       // Store bound argument into the new stack slot:
   599       __ load_heap_oop(G3_bmh_argument, O1_scratch);
   600       if (arg_type == T_OBJECT) {
   601         __ st_ptr(O1_scratch, Address(O0_argslot, 0));
   602       } else {
   603         Address prim_value_addr(O1_scratch, java_lang_boxing_object::value_offset_in_bytes(arg_type));
   604         __ load_sized_value(prim_value_addr, O2_scratch, type2aelembytes(arg_type), is_signed_subword_type(arg_type));
   605         if (arg_slots == 2) {
   606           __ unimplemented("not yet tested");
   607 #ifndef _LP64
   608           __ signx(O2_scratch, O3_scratch);  // Sign extend
   609 #endif
   610           __ st_long(O2_scratch, Address(O0_argslot, 0));  // Uses O2/O3 on !_LP64
   611         } else {
   612           __ st_ptr( O2_scratch, Address(O0_argslot, 0));
   613         }
   614       }
   616       if (direct_to_method) {
   617         __ load_heap_oop(G3_mh_vmtarget, G5_method);  // target is a methodOop
   618         __ verify_oop(G5_method);
   619         __ jump_indirect_to(G5_method_fie, O1_scratch);
   620         __ delayed()->nop();
   621       } else {
   622         __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);  // target is a methodOop
   623         __ verify_oop(G3_method_handle);
   624         __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   625       }
   626     }
   627     break;
   629   case _adapter_retype_only:
   630   case _adapter_retype_raw:
   631     // Immediately jump to the next MH layer:
   632     __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
   633     __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   634     // This is OK when all parameter types widen.
   635     // It is also OK when a return type narrows.
   636     break;
   638   case _adapter_check_cast:
   639     {
   640       // Temps:
   641       Register G5_klass = G5_index;  // Interesting AMH data.
   643       // Check a reference argument before jumping to the next layer of MH:
   644       __ ldsw(G3_amh_vmargslot, O0_argslot);
   645       Address vmarg = __ argument_address(O0_argslot);
   647       // What class are we casting to?
   648       __ load_heap_oop(G3_amh_argument, G5_klass);  // This is a Class object!
   649       __ load_heap_oop(Address(G5_klass, java_lang_Class::klass_offset_in_bytes()), G5_klass);
   651       Label done;
   652       __ ld_ptr(vmarg, O1_scratch);
   653       __ tst(O1_scratch);
   654       __ brx(Assembler::zero, false, Assembler::pn, done);  // No cast if null.
   655       __ delayed()->nop();
   656       __ load_klass(O1_scratch, O1_scratch);
   658       // Live at this point:
   659       // - G5_klass        :  klass required by the target method
   660       // - O1_scratch      :  argument klass to test
   661       // - G3_method_handle:  adapter method handle
   662       __ check_klass_subtype(O1_scratch, G5_klass, O0_argslot, O2_scratch, done);
   664       // If we get here, the type check failed!
   665       __ ldsw(G3_amh_vmargslot, O0_argslot);  // reload argslot field
   666       __ load_heap_oop(G3_amh_argument, O3_scratch);  // required class
   667       __ ld_ptr(vmarg, O2_scratch);  // bad object
   668       __ jump_to(AddressLiteral(from_interpreted_entry(_raise_exception)), O0_argslot);
   669       __ delayed()->mov(Bytecodes::_checkcast, O1_scratch);  // who is complaining?
   671       __ bind(done);
   672       // Get the new MH:
   673       __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
   674       __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   675     }
   676     break;
   678   case _adapter_prim_to_prim:
   679   case _adapter_ref_to_prim:
   680     // Handled completely by optimized cases.
   681     __ stop("init_AdapterMethodHandle should not issue this");
   682     break;
   684   case _adapter_opt_i2i:        // optimized subcase of adapt_prim_to_prim
   685 //case _adapter_opt_f2i:        // optimized subcase of adapt_prim_to_prim
   686   case _adapter_opt_l2i:        // optimized subcase of adapt_prim_to_prim
   687   case _adapter_opt_unboxi:     // optimized subcase of adapt_ref_to_prim
   688     {
   689       // Perform an in-place conversion to int or an int subword.
   690       __ ldsw(G3_amh_vmargslot, O0_argslot);
   691       Address vmarg = __ argument_address(O0_argslot);
   692       Address value;
   693       bool value_left_justified = false;
   695       switch (ek) {
   696       case _adapter_opt_i2i:
   697         value = vmarg;
   698         break;
   699       case _adapter_opt_l2i:
   700         {
   701           // just delete the extra slot
   702           __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
   703           remove_arg_slots(_masm, -stack_move_unit(), O0_argslot, O1_scratch, O2_scratch, O3_scratch);
   704           value = vmarg = Address(O0_argslot, 0);
   705         }
   706         break;
   707       case _adapter_opt_unboxi:
   708         {
   709           // Load the value up from the heap.
   710           __ ld_ptr(vmarg, O1_scratch);
   711           int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_INT);
   712 #ifdef ASSERT
   713           for (int bt = T_BOOLEAN; bt < T_INT; bt++) {
   714             if (is_subword_type(BasicType(bt)))
   715               assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(BasicType(bt)), "");
   716           }
   717 #endif
   718           __ null_check(O1_scratch, value_offset);
   719           value = Address(O1_scratch, value_offset);
   720 #ifdef _BIG_ENDIAN
   721           // Values stored in objects are packed.
   722           value_left_justified = true;
   723 #endif
   724         }
   725         break;
   726       default:
   727         ShouldNotReachHere();
   728       }
   730       // This check is required on _BIG_ENDIAN
   731       Register G5_vminfo = G5_index;
   732       __ ldsw(G3_amh_conversion, G5_vminfo);
   733       assert(CONV_VMINFO_SHIFT == 0, "preshifted");
   735       // Original 32-bit vmdata word must be of this form:
   736       // | MBZ:6 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
   737       __ lduw(value, O1_scratch);
   738       if (!value_left_justified)
   739         __ sll(O1_scratch, G5_vminfo, O1_scratch);
   740       Label zero_extend, done;
   741       __ btst(CONV_VMINFO_SIGN_FLAG, G5_vminfo);
   742       __ br(Assembler::zero, false, Assembler::pn, zero_extend);
   743       __ delayed()->nop();
   745       // this path is taken for int->byte, int->short
   746       __ sra(O1_scratch, G5_vminfo, O1_scratch);
   747       __ ba(false, done);
   748       __ delayed()->nop();
   750       __ bind(zero_extend);
   751       // this is taken for int->char
   752       __ srl(O1_scratch, G5_vminfo, O1_scratch);
   754       __ bind(done);
   755       __ st(O1_scratch, vmarg);
   757       // Get the new MH:
   758       __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
   759       __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   760     }
   761     break;
   763   case _adapter_opt_i2l:        // optimized subcase of adapt_prim_to_prim
   764   case _adapter_opt_unboxl:     // optimized subcase of adapt_ref_to_prim
   765     {
   766       // Perform an in-place int-to-long or ref-to-long conversion.
   767       __ ldsw(G3_amh_vmargslot, O0_argslot);
   769       // On big-endian machine we duplicate the slot and store the MSW
   770       // in the first slot.
   771       __ add(Gargs, __ argument_offset(O0_argslot, 1), O0_argslot);
   773       insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK, O0_argslot, O1_scratch, O2_scratch, G5_index);
   775       Address arg_lsw(O0_argslot, 0);
   776       Address arg_msw(O0_argslot, -Interpreter::stackElementSize);
   778       switch (ek) {
   779       case _adapter_opt_i2l:
   780         {
   781           __ ldsw(arg_lsw, O2_scratch);      // Load LSW
   782 #ifndef _LP64
   783           __ signx(O2_scratch, O3_scratch);  // Sign extend
   784 #endif
   785           __ st_long(O2_scratch, arg_msw);   // Uses O2/O3 on !_LP64
   786         }
   787         break;
   788       case _adapter_opt_unboxl:
   789         {
   790           // Load the value up from the heap.
   791           __ ld_ptr(arg_lsw, O1_scratch);
   792           int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG);
   793           assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), "");
   794           __ null_check(O1_scratch, value_offset);
   795           __ ld_long(Address(O1_scratch, value_offset), O2_scratch);  // Uses O2/O3 on !_LP64
   796           __ st_long(O2_scratch, arg_msw);
   797         }
   798         break;
   799       default:
   800         ShouldNotReachHere();
   801       }
   803       __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
   804       __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   805     }
   806     break;
   808   case _adapter_opt_f2d:        // optimized subcase of adapt_prim_to_prim
   809   case _adapter_opt_d2f:        // optimized subcase of adapt_prim_to_prim
   810     {
   811       // perform an in-place floating primitive conversion
   812       __ unimplemented(entry_name(ek));
   813     }
   814     break;
   816   case _adapter_prim_to_ref:
   817     __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
   818     break;
   820   case _adapter_swap_args:
   821   case _adapter_rot_args:
   822     // handled completely by optimized cases
   823     __ stop("init_AdapterMethodHandle should not issue this");
   824     break;
   826   case _adapter_opt_swap_1:
   827   case _adapter_opt_swap_2:
   828   case _adapter_opt_rot_1_up:
   829   case _adapter_opt_rot_1_down:
   830   case _adapter_opt_rot_2_up:
   831   case _adapter_opt_rot_2_down:
   832     {
   833       int swap_bytes = 0, rotate = 0;
   834       get_ek_adapter_opt_swap_rot_info(ek, swap_bytes, rotate);
   836       // 'argslot' is the position of the first argument to swap.
   837       __ ldsw(G3_amh_vmargslot, O0_argslot);
   838       __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
   840       // 'vminfo' is the second.
   841       Register O1_destslot = O1_scratch;
   842       __ ldsw(G3_amh_conversion, O1_destslot);
   843       assert(CONV_VMINFO_SHIFT == 0, "preshifted");
   844       __ and3(O1_destslot, CONV_VMINFO_MASK, O1_destslot);
   845       __ add(Gargs, __ argument_offset(O1_destslot), O1_destslot);
   847       if (!rotate) {
   848         for (int i = 0; i < swap_bytes; i += wordSize) {
   849           __ ld_ptr(Address(O0_argslot,  i), O2_scratch);
   850           __ ld_ptr(Address(O1_destslot, i), O3_scratch);
   851           __ st_ptr(O3_scratch, Address(O0_argslot,  i));
   852           __ st_ptr(O2_scratch, Address(O1_destslot, i));
   853         }
   854       } else {
   855         // Save the first chunk, which is going to get overwritten.
   856         switch (swap_bytes) {
   857         case 4 : __ lduw(Address(O0_argslot, 0), O2_scratch); break;
   858         case 16: __ ldx( Address(O0_argslot, 8), O3_scratch); //fall-thru
   859         case 8 : __ ldx( Address(O0_argslot, 0), O2_scratch); break;
   860         default: ShouldNotReachHere();
   861         }
   863         if (rotate > 0) {
   864           // Rorate upward.
   865           __ sub(O0_argslot, swap_bytes, O0_argslot);
   866 #if ASSERT
   867           {
   868             // Verify that argslot > destslot, by at least swap_bytes.
   869             Label L_ok;
   870             __ cmp(O0_argslot, O1_destslot);
   871             __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, L_ok);
   872             __ delayed()->nop();
   873             __ stop("source must be above destination (upward rotation)");
   874             __ bind(L_ok);
   875           }
   876 #endif
   877           // Work argslot down to destslot, copying contiguous data upwards.
   878           // Pseudo-code:
   879           //   argslot  = src_addr - swap_bytes
   880           //   destslot = dest_addr
   881           //   while (argslot >= destslot) {
   882           //     *(argslot + swap_bytes) = *(argslot + 0);
   883           //     argslot--;
   884           //   }
   885           Label loop;
   886           __ bind(loop);
   887           __ ld_ptr(Address(O0_argslot, 0), G5_index);
   888           __ st_ptr(G5_index, Address(O0_argslot, swap_bytes));
   889           __ sub(O0_argslot, wordSize, O0_argslot);
   890           __ cmp(O0_argslot, O1_destslot);
   891           __ brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, loop);
   892           __ delayed()->nop();  // FILLME
   893         } else {
   894           __ add(O0_argslot, swap_bytes, O0_argslot);
   895 #if ASSERT
   896           {
   897             // Verify that argslot < destslot, by at least swap_bytes.
   898             Label L_ok;
   899             __ cmp(O0_argslot, O1_destslot);
   900             __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, L_ok);
   901             __ delayed()->nop();
   902             __ stop("source must be above destination (upward rotation)");
   903             __ bind(L_ok);
   904           }
   905 #endif
   906           // Work argslot up to destslot, copying contiguous data downwards.
   907           // Pseudo-code:
   908           //   argslot  = src_addr + swap_bytes
   909           //   destslot = dest_addr
   910           //   while (argslot >= destslot) {
   911           //     *(argslot - swap_bytes) = *(argslot + 0);
   912           //     argslot++;
   913           //   }
   914           Label loop;
   915           __ bind(loop);
   916           __ ld_ptr(Address(O0_argslot, 0), G5_index);
   917           __ st_ptr(G5_index, Address(O0_argslot, -swap_bytes));
   918           __ add(O0_argslot, wordSize, O0_argslot);
   919           __ cmp(O0_argslot, O1_destslot);
   920           __ brx(Assembler::lessEqualUnsigned, false, Assembler::pt, loop);
   921           __ delayed()->nop();  // FILLME
   922         }
   924         // Store the original first chunk into the destination slot, now free.
   925         switch (swap_bytes) {
   926         case 4 : __ stw(O2_scratch, Address(O1_destslot, 0)); break;
   927         case 16: __ stx(O3_scratch, Address(O1_destslot, 8)); // fall-thru
   928         case 8 : __ stx(O2_scratch, Address(O1_destslot, 0)); break;
   929         default: ShouldNotReachHere();
   930         }
   931       }
   933       __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
   934       __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   935     }
   936     break;
   938   case _adapter_dup_args:
   939     {
   940       // 'argslot' is the position of the first argument to duplicate.
   941       __ ldsw(G3_amh_vmargslot, O0_argslot);
   942       __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
   944       // 'stack_move' is negative number of words to duplicate.
   945       Register G5_stack_move = G5_index;
   946       __ ldsw(G3_amh_conversion, G5_stack_move);
   947       __ sra(G5_stack_move, CONV_STACK_MOVE_SHIFT, G5_stack_move);
   949       // Remember the old Gargs (argslot[0]).
   950       Register O1_oldarg = O1_scratch;
   951       __ mov(Gargs, O1_oldarg);
   953       // Move Gargs down to make room for dups.
   954       __ sll_ptr(G5_stack_move, LogBytesPerWord, G5_stack_move);
   955       __ add(Gargs, G5_stack_move, Gargs);
   957       // Compute the new Gargs (argslot[0]).
   958       Register O2_newarg = O2_scratch;
   959       __ mov(Gargs, O2_newarg);
   961       // Copy from oldarg[0...] down to newarg[0...]
   962       // Pseude-code:
   963       //   O1_oldarg  = old-Gargs
   964       //   O2_newarg  = new-Gargs
   965       //   O0_argslot = argslot
   966       //   while (O2_newarg < O1_oldarg) *O2_newarg = *O0_argslot++
   967       Label loop;
   968       __ bind(loop);
   969       __ ld_ptr(Address(O0_argslot, 0), O3_scratch);
   970       __ st_ptr(O3_scratch, Address(O2_newarg, 0));
   971       __ add(O0_argslot, wordSize, O0_argslot);
   972       __ add(O2_newarg,  wordSize, O2_newarg);
   973       __ cmp(O2_newarg, O1_oldarg);
   974       __ brx(Assembler::less, false, Assembler::pt, loop);
   975       __ delayed()->nop();  // FILLME
   977       __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
   978       __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   979     }
   980     break;
   982   case _adapter_drop_args:
   983     {
   984       // 'argslot' is the position of the first argument to nuke.
   985       __ ldsw(G3_amh_vmargslot, O0_argslot);
   986       __ add(Gargs, __ argument_offset(O0_argslot), O0_argslot);
   988       // 'stack_move' is number of words to drop.
   989       Register G5_stack_move = G5_index;
   990       __ ldsw(G3_amh_conversion, G5_stack_move);
   991       __ sra(G5_stack_move, CONV_STACK_MOVE_SHIFT, G5_stack_move);
   993       remove_arg_slots(_masm, G5_stack_move, O0_argslot, O1_scratch, O2_scratch, O3_scratch);
   995       __ load_heap_oop(G3_mh_vmtarget, G3_method_handle);
   996       __ jump_to_method_handle_entry(G3_method_handle, O1_scratch);
   997     }
   998     break;
  1000   case _adapter_collect_args:
  1001     __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
  1002     break;
  1004   case _adapter_spread_args:
  1005     // Handled completely by optimized cases.
  1006     __ stop("init_AdapterMethodHandle should not issue this");
  1007     break;
  1009   case _adapter_opt_spread_0:
  1010   case _adapter_opt_spread_1:
  1011   case _adapter_opt_spread_more:
  1013       // spread an array out into a group of arguments
  1014       __ unimplemented(entry_name(ek));
  1016     break;
  1018   case _adapter_flyby:
  1019   case _adapter_ricochet:
  1020     __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
  1021     break;
  1023   default:
  1024     ShouldNotReachHere();
  1027   address me_cookie = MethodHandleEntry::start_compiled_entry(_masm, interp_entry);
  1028   __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
  1030   init_entry(ek, MethodHandleEntry::finish_compiled_entry(_masm, me_cookie));

mercurial