hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
changeset 13391 30245956af37
parent 11439 7af64224c70b
child 13728 882756847a04
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Mon Jul 23 13:04:59 2012 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Tue Jul 24 10:51:00 2012 -0700
@@ -378,7 +378,7 @@
   Register Rcache = G3_scratch;
   Register Rscratch = G4_scratch;
 
-  resolve_cache_and_index(f1_oop, Otos_i, Rcache, Rscratch, wide ? sizeof(u2) : sizeof(u1));
+  resolve_cache_and_index(f12_oop, Otos_i, Rcache, Rscratch, wide ? sizeof(u2) : sizeof(u1));
 
   __ verify_oop(Otos_i);
 
@@ -2093,10 +2093,12 @@
   // Depends on cpCacheOop layout!
   Label resolved;
 
-  if (byte_no == f1_oop) {
-    // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
-    // This kind of CP cache entry does not need to match the flags byte, because
+  if (byte_no == f12_oop) {
+    // We are resolved if the f1 field contains a non-null object (CallSite, MethodType, etc.)
+    // This kind of CP cache entry does not need to match bytecode_1 or bytecode_2, because
     // there is a 1-1 relation between bytecode type and CP entry type.
+    // The caller will also load a methodOop from f2.
+    assert(result != noreg, "");
     assert_different_registers(result, Rcache);
     __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
     __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() +
@@ -2123,10 +2125,13 @@
     case Bytecodes::_invokespecial  : // fall through
     case Bytecodes::_invokestatic   : // fall through
     case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);  break;
+    case Bytecodes::_invokehandle   : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle);  break;
     case Bytecodes::_invokedynamic  : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);  break;
     case Bytecodes::_fast_aldc      : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);     break;
     case Bytecodes::_fast_aldc_w    : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);     break;
-    default                         : ShouldNotReachHere();                                 break;
+    default:
+      fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
+      break;
   }
   // first time invocation - must resolve first
   __ call_VM(noreg, entry, O1);
@@ -2139,48 +2144,54 @@
 }
 
 void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
-                                               Register Rmethod,
-                                               Register Ritable_index,
-                                               Register Rflags,
+                                               Register method,
+                                               Register itable_index,
+                                               Register flags,
                                                bool is_invokevirtual,
                                                bool is_invokevfinal,
                                                bool is_invokedynamic) {
   // Uses both G3_scratch and G4_scratch
-  Register Rcache = G3_scratch;
-  Register Rscratch = G4_scratch;
-  assert_different_registers(Rcache, Rmethod, Ritable_index);
-
-  ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset();
+  Register cache = G3_scratch;
+  Register index = G4_scratch;
+  assert_different_registers(cache, method, itable_index);
 
   // determine constant pool cache field offsets
+  assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant");
   const int method_offset = in_bytes(
-    cp_base_offset +
-      (is_invokevirtual
+      constantPoolCacheOopDesc::base_offset() +
+      ((byte_no == f2_byte)
        ? ConstantPoolCacheEntry::f2_offset()
        : ConstantPoolCacheEntry::f1_offset()
       )
     );
-  const int flags_offset = in_bytes(cp_base_offset +
+  const int flags_offset = in_bytes(constantPoolCacheOopDesc::base_offset() +
                                     ConstantPoolCacheEntry::flags_offset());
   // access constant pool cache fields
-  const int index_offset = in_bytes(cp_base_offset +
+  const int index_offset = in_bytes(constantPoolCacheOopDesc::base_offset() +
                                     ConstantPoolCacheEntry::f2_offset());
 
   if (is_invokevfinal) {
-    __ get_cache_and_index_at_bcp(Rcache, Rscratch, 1);
-    __ ld_ptr(Rcache, method_offset, Rmethod);
-  } else if (byte_no == f1_oop) {
-    // Resolved f1_oop goes directly into 'method' register.
-    resolve_cache_and_index(byte_no, Rmethod, Rcache, Rscratch, sizeof(u4));
+    __ get_cache_and_index_at_bcp(cache, index, 1);
+    __ ld_ptr(Address(cache, method_offset), method);
+  } else if (byte_no == f12_oop) {
+    // Resolved f1_oop (CallSite, MethodType, etc.) goes into 'itable_index'.
+    // Resolved f2_oop (methodOop invoker) will go into 'method' (at index_offset).
+    // See ConstantPoolCacheEntry::set_dynamic_call and set_method_handle.
+    size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
+    resolve_cache_and_index(byte_no, itable_index, cache, index, index_size);
+    __ ld_ptr(Address(cache, index_offset), method);
+    itable_index = noreg;  // hack to disable load below
   } else {
-    resolve_cache_and_index(byte_no, noreg, Rcache, Rscratch, sizeof(u2));
-    __ ld_ptr(Rcache, method_offset, Rmethod);
+    resolve_cache_and_index(byte_no, noreg, cache, index, sizeof(u2));
+    __ ld_ptr(Address(cache, method_offset), method);
   }
 
-  if (Ritable_index != noreg) {
-    __ ld_ptr(Rcache, index_offset, Ritable_index);
+  if (itable_index != noreg) {
+    // pick up itable index from f2 also:
+    assert(byte_no == f1_byte, "already picked up f1");
+    __ ld_ptr(Address(cache, index_offset), itable_index);
   }
-  __ ld_ptr(Rcache, flags_offset, Rflags);
+  __ ld_ptr(Address(cache, flags_offset), flags);
 }
 
 // The Rcache register must be set before call
@@ -2272,7 +2283,7 @@
 
   if (__ membar_has_effect(membar_bits)) {
     // Get volatile flag
-    __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch);
+    __ set((1 << ConstantPoolCacheEntry::is_volatile_shift), Lscratch);
     __ and3(Rflags, Lscratch, Lscratch);
   }
 
@@ -2280,9 +2291,9 @@
 
   // compute field type
   Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj;
-  __ srl(Rflags, ConstantPoolCacheEntry::tosBits, Rflags);
-  // Make sure we don't need to mask Rflags for tosBits after the above shift
-  ConstantPoolCacheEntry::verify_tosBits();
+  __ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags);
+  // Make sure we don't need to mask Rflags after the above shift
+  ConstantPoolCacheEntry::verify_tos_state_shift();
 
   // Check atos before itos for getstatic, more likely (in Queens at least)
   __ cmp(Rflags, atos);
@@ -2445,7 +2456,7 @@
   if (__ membar_has_effect(membar_bits)) {
     // Get volatile flag
     __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Rflags);
-    __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch);
+    __ set((1 << ConstantPoolCacheEntry::is_volatile_shift), Lscratch);
   }
 
   switch (bytecode()) {
@@ -2569,9 +2580,9 @@
       Label two_word, valsizeknown;
       __ ld_ptr(G1_scratch, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), Rflags);
       __ mov(Lesp, G4_scratch);
-      __ srl(Rflags, ConstantPoolCacheEntry::tosBits, Rflags);
-      // Make sure we don't need to mask Rflags for tosBits after the above shift
-      ConstantPoolCacheEntry::verify_tosBits();
+      __ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags);
+      // Make sure we don't need to mask Rflags after the above shift
+      ConstantPoolCacheEntry::verify_tos_state_shift();
       __ cmp(Rflags, ltos);
       __ br(Assembler::equal, false, Assembler::pt, two_word);
       __ delayed()->cmp(Rflags, dtos);
@@ -2625,7 +2636,7 @@
 
   Label notVolatile, checkVolatile, exit;
   if (__ membar_has_effect(read_bits) || __ membar_has_effect(write_bits)) {
-    __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch);
+    __ set((1 << ConstantPoolCacheEntry::is_volatile_shift), Lscratch);
     __ and3(Rflags, Lscratch, Lscratch);
 
     if (__ membar_has_effect(read_bits)) {
@@ -2635,9 +2646,9 @@
     }
   }
 
-  __ srl(Rflags, ConstantPoolCacheEntry::tosBits, Rflags);
-  // Make sure we don't need to mask Rflags for tosBits after the above shift
-  ConstantPoolCacheEntry::verify_tosBits();
+  __ srl(Rflags, ConstantPoolCacheEntry::tos_state_shift, Rflags);
+  // Make sure we don't need to mask Rflags after the above shift
+  ConstantPoolCacheEntry::verify_tos_state_shift();
 
   // compute field type
   Label notInt, notShort, notChar, notObj, notByte, notLong, notFloat;
@@ -2833,7 +2844,7 @@
   Label notVolatile, checkVolatile, exit;
   if (__ membar_has_effect(read_bits) || __ membar_has_effect(write_bits)) {
     __ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), Rflags);
-    __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch);
+    __ set((1 << ConstantPoolCacheEntry::is_volatile_shift), Lscratch);
     __ and3(Rflags, Lscratch, Lscratch);
     if (__ membar_has_effect(read_bits)) {
       __ cmp_and_br_short(Lscratch, 0, Assembler::equal, Assembler::pt, notVolatile);
@@ -2916,7 +2927,7 @@
 
     // Test volatile
     Label notVolatile;
-    __ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch);
+    __ set((1 << ConstantPoolCacheEntry::is_volatile_shift), Lscratch);
     __ btst(Rflags, Lscratch);
     __ br(Assembler::zero, false, Assembler::pt, notVolatile);
     __ delayed()->nop();
@@ -2936,27 +2947,82 @@
   ShouldNotReachHere();
 }
 
+
+void TemplateTable::prepare_invoke(int byte_no,
+                                   Register method,  // linked method (or i-klass)
+                                   Register ra,      // return address
+                                   Register index,   // itable index, MethodType, etc.
+                                   Register recv,    // if caller wants to see it
+                                   Register flags    // if caller wants to test it
+                                   ) {
+  // determine flags
+  const Bytecodes::Code code = bytecode();
+  const bool is_invokeinterface  = code == Bytecodes::_invokeinterface;
+  const bool is_invokedynamic    = code == Bytecodes::_invokedynamic;
+  const bool is_invokehandle     = code == Bytecodes::_invokehandle;
+  const bool is_invokevirtual    = code == Bytecodes::_invokevirtual;
+  const bool is_invokespecial    = code == Bytecodes::_invokespecial;
+  const bool load_receiver       = (recv != noreg);
+  assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), "");
+  assert(recv  == noreg || recv  == O0, "");
+  assert(flags == noreg || flags == O1, "");
+
+  // setup registers & access constant pool cache
+  if (recv  == noreg)  recv  = O0;
+  if (flags == noreg)  flags = O1;
+  const Register temp = O2;
+  assert_different_registers(method, ra, index, recv, flags, temp);
+
+  load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
+
+  __ mov(SP, O5_savedSP);  // record SP that we wanted the callee to restore
+
+  // maybe push appendix to arguments
+  if (is_invokedynamic || is_invokehandle) {
+    Label L_no_push;
+    __ verify_oop(index);
+    __ set((1 << ConstantPoolCacheEntry::has_appendix_shift), temp);
+    __ btst(flags, temp);
+    __ br(Assembler::zero, false, Assembler::pt, L_no_push);
+    __ delayed()->nop();
+    // Push the appendix as a trailing parameter.
+    // This must be done before we get the receiver,
+    // since the parameter_size includes it.
+    __ push_ptr(index);  // push appendix (MethodType, CallSite, etc.)
+    __ bind(L_no_push);
+  }
+
+  // load receiver if needed (after appendix is pushed so parameter size is correct)
+  if (load_receiver) {
+    __ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, temp);  // get parameter size
+    __ load_receiver(temp, recv);  //  __ argument_address uses Gargs but we need Lesp
+    __ verify_oop(recv);
+  }
+
+  // compute return type
+  __ srl(flags, ConstantPoolCacheEntry::tos_state_shift, ra);
+  // Make sure we don't need to mask flags after the above shift
+  ConstantPoolCacheEntry::verify_tos_state_shift();
+  // load return address
+  {
+    const address table_addr = (is_invokeinterface || is_invokedynamic) ?
+        (address)Interpreter::return_5_addrs_by_index_table() :
+        (address)Interpreter::return_3_addrs_by_index_table();
+    AddressLiteral table(table_addr);
+    __ set(table, temp);
+    __ sll(ra, LogBytesPerWord, ra);
+    __ ld_ptr(Address(temp, ra), ra);
+  }
+}
+
+
 void TemplateTable::generate_vtable_call(Register Rrecv, Register Rindex, Register Rret) {
   Register Rtemp = G4_scratch;
   Register Rcall = Rindex;
   assert_different_registers(Rcall, G5_method, Gargs, Rret);
 
   // get target methodOop & entry point
-  const int base = instanceKlass::vtable_start_offset() * wordSize;
-  if (vtableEntry::size() % 3 == 0) {
-    // scale the vtable index by 12:
-    int one_third = vtableEntry::size() / 3;
-    __ sll(Rindex, exact_log2(one_third * 1 * wordSize), Rtemp);
-    __ sll(Rindex, exact_log2(one_third * 2 * wordSize), Rindex);
-    __ add(Rindex, Rtemp, Rindex);
-  } else {
-    // scale the vtable index by 8:
-    __ sll(Rindex, exact_log2(vtableEntry::size() * wordSize), Rindex);
-  }
-
-  __ add(Rrecv, Rindex, Rrecv);
-  __ ld_ptr(Rrecv, base + vtableEntry::method_offset_in_bytes(), G5_method);
-
+  __ lookup_virtual_method(Rrecv, Rindex, G5_method);
   __ call_from_interpreter(Rcall, Gargs, Rret);
 }
 
@@ -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
-  __ set((1 << ConstantPoolCacheEntry::vfinalMethod), G4_scratch);
+  __ set((1 << ConstantPoolCacheEntry::is_vfinal_shift), G4_scratch);
   __ btst(Rret, G4_scratch);
   __ br(Assembler::zero, false, Assembler::pt, notFinal);
   __ delayed()->and3(Rret, 0xFF, G4_scratch);      // gets number of parameters
@@ -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);
-  __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret);          // get return type
-  // Make sure we don't need to mask Rret for tosBits after the above shift
-  ConstantPoolCacheEntry::verify_tosBits();
+  __ srl(Rret, ConstantPoolCacheEntry::tos_state_shift, Rret);          // get return type
+  // Make sure we don't need to mask Rret after the above shift
+  ConstantPoolCacheEntry::verify_tos_state_shift();
   __ 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());
   __ set(table, Rtemp);
-  __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret);          // get return type
-  // Make sure we don't need to mask Rret for tosBits after the above shift
-  ConstantPoolCacheEntry::verify_tosBits();
+  __ srl(Rret, ConstantPoolCacheEntry::tos_state_shift, Rret);          // get return type
+  // Make sure we don't need to mask Rret after the above shift
+  ConstantPoolCacheEntry::verify_tos_state_shift();
   __ sll(Rret,  LogBytesPerWord, Rret);
   __ ld_ptr(Rtemp, Rret, Rret);         // get return address
 
@@ -3047,65 +3113,37 @@
   __ call_from_interpreter(Rscratch, Gargs, Rret);
 }
 
+
 void TemplateTable::invokespecial(int byte_no) {
   transition(vtos, vtos);
   assert(byte_no == f1_byte, "use this argument");
 
-  Register Rscratch = G3_scratch;
-  Register Rtemp = G4_scratch;
-  Register Rret = Lscratch;
-
-  load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, /*virtual*/ false, false, false);
-  __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
-
-  __ verify_oop(G5_method);
-
-  __ lduh(G5_method, in_bytes(methodOopDesc::size_of_parameters_offset()), G4_scratch);
-  __ load_receiver(G4_scratch, O0);
-
-  // receiver NULL check
-  __ null_check(O0);
-
-  __ profile_call(O4);
-
-  // get return address
-  AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
-  __ set(table, Rtemp);
-  __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret);          // get return type
-  // Make sure we don't need to mask Rret for tosBits after the above shift
-  ConstantPoolCacheEntry::verify_tosBits();
-  __ sll(Rret,  LogBytesPerWord, Rret);
-  __ ld_ptr(Rtemp, Rret, Rret);         // get return address
+  const Register Rret     = Lscratch;
+  const Register O0_recv  = O0;
+  const Register Rscratch = G3_scratch;
+
+  prepare_invoke(byte_no, G5_method, Rret, noreg, O0_recv);  // get receiver also for null check
+  __ null_check(O0_recv);
 
   // do the call
+  __ verify_oop(G5_method);
+  __ profile_call(O4);
   __ call_from_interpreter(Rscratch, Gargs, Rret);
 }
 
+
 void TemplateTable::invokestatic(int byte_no) {
   transition(vtos, vtos);
   assert(byte_no == f1_byte, "use this argument");
 
-  Register Rscratch = G3_scratch;
-  Register Rtemp = G4_scratch;
-  Register Rret = Lscratch;
-
-  load_invoke_cp_cache_entry(byte_no, G5_method, noreg, Rret, /*virtual*/ false, false, false);
-  __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
-
-  __ verify_oop(G5_method);
-
-  __ profile_call(O4);
-
-  // get return address
-  AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
-  __ set(table, Rtemp);
-  __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret);          // get return type
-  // Make sure we don't need to mask Rret for tosBits after the above shift
-  ConstantPoolCacheEntry::verify_tosBits();
-  __ sll(Rret,  LogBytesPerWord, Rret);
-  __ ld_ptr(Rtemp, Rret, Rret);         // get return address
+  const Register Rret     = Lscratch;
+  const Register Rscratch = G3_scratch;
+
+  prepare_invoke(byte_no, G5_method, Rret);  // get f1 methodOop
 
   // do the call
+  __ verify_oop(G5_method);
+  __ profile_call(O4);
   __ call_from_interpreter(Rscratch, Gargs, Rret);
 }
 
@@ -3122,7 +3160,7 @@
   Label notFinal;
 
   // Check for vfinal
-  __ set((1 << ConstantPoolCacheEntry::vfinalMethod), Rscratch);
+  __ set((1 << ConstantPoolCacheEntry::is_vfinal_shift), Rscratch);
   __ btst(Rflags, Rscratch);
   __ br(Assembler::zero, false, Assembler::pt, notFinal);
   __ delayed()->nop();
@@ -3144,53 +3182,37 @@
   transition(vtos, vtos);
   assert(byte_no == f1_byte, "use this argument");
 
-  Register Rscratch = G4_scratch;
-  Register Rret = G3_scratch;
-  Register Rindex = Lscratch;
-  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 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);
-  __ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
-
-  // get receiver
-  __ and3(Rflags, 0xFF, Rscratch);       // gets number of parameters
-  __ load_receiver(Rscratch, O0);
-  __ verify_oop(O0);
-
-  __ mov(Rflags, Rret);
-
-  // get return address
-  AddressLiteral table(Interpreter::return_5_addrs_by_index_table());
-  __ set(table, Rscratch);
-  __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret);          // get return type
-  // Make sure we don't need to mask Rret for tosBits after the above shift
-  ConstantPoolCacheEntry::verify_tosBits();
-  __ sll(Rret,  LogBytesPerWord, Rret);
-  __ ld_ptr(Rscratch, Rret, Rret);      // get return address
+  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, O2_klassOop);
+  __ verify_oop(O2_klassOop);
 
   // Special case of invokeinterface called for virtual method of
   // 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(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);
   __ call_from_interpreter(Rcall, Gargs, Rret);
-
+}
+
+
+void TemplateTable::invokehandle(int byte_no) {
+  transition(vtos, vtos);
+  assert(byte_no == f12_oop, "use this argument");
+
+  if (!EnableInvokeDynamic) {
+    // rewriter does not generate this bytecode
+    __ should_not_reach_here();
+    return;
+  }
+
+  const Register Rret       = Lscratch;
+  const Register G4_mtype   = G4_scratch;  // f1
+  const Register O0_recv    = O0;
+  const Register Rscratch   = G3_scratch;
+
+  prepare_invoke(byte_no, G5_method, Rret, G4_mtype, O0_recv);
+  __ null_check(O0_recv);
+
+  // G4: MethodType object (from f1)
+  // G5: MH.linkToCallSite method (from f2)
+
+  // Note:  G4_mtype is already pushed (if necessary) by prepare_invoke
+
+  // do the call
+  __ verify_oop(G5_method);
+  __ profile_final_call(O4);  // FIXME: profile the LambdaForm also
+  __ call_from_interpreter(Rscratch, Gargs, Rret);
 }
 
 
 void TemplateTable::invokedynamic(int byte_no) {
   transition(vtos, vtos);
-  assert(byte_no == f1_oop, "use this argument");
+  assert(byte_no == f12_oop, "use this argument");
 
   if (!EnableInvokeDynamic) {
     // We should not encounter this bytecode if !EnableInvokeDynamic.
@@ -3279,42 +3330,24 @@
     return;
   }
 
-  // G5: CallSite object (f1)
-  // XX: unused (f2)
-  // XX: flags (unused)
-
-  Register G5_callsite = G5_method;
-  Register Rscratch    = G3_scratch;
-  Register Rtemp       = G1_scratch;
-  Register Rret        = Lscratch;
-
-  load_invoke_cp_cache_entry(byte_no, G5_callsite, noreg, Rret,
-                             /*virtual*/ false, /*vfinal*/ false, /*indy*/ true);
-  __ mov(SP, O5_savedSP);  // record SP that we wanted the callee to restore
-
+  const Register Rret        = Lscratch;
+  const Register G4_callsite = G4_scratch;
+  const Register Rscratch    = G3_scratch;
+
+  prepare_invoke(byte_no, G5_method, Rret, G4_callsite);
+
+  // G4: CallSite object (from f1)
+  // G5: MH.linkToCallSite method (from f2)
+
+  // Note:  G4_callsite is already pushed by prepare_invoke
+
+  // %%% should make a type profile for any invokedynamic that takes a ref argument
   // profile this call
   __ profile_call(O4);
 
-  // get return address
-  AddressLiteral table(Interpreter::return_5_addrs_by_index_table());
-  __ set(table, Rtemp);
-  __ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret);  // get return type
-  // Make sure we don't need to mask Rret for tosBits after the above shift
-  ConstantPoolCacheEntry::verify_tosBits();
-  __ sll(Rret, LogBytesPerWord, Rret);
-  __ ld_ptr(Rtemp, Rret, Rret);  // get return address
-
-  __ verify_oop(G5_callsite);
-  __ load_heap_oop(G5_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle);
-  __ null_check(G3_method_handle);
-  __ verify_oop(G3_method_handle);
-
-  // Adjust Rret first so Llast_SP can be same as Rret
-  __ add(Rret, -frame::pc_return_offset, O7);
-  __ add(Lesp, BytesPerWord, Gargs);  // setup parameter pointer
-  __ jump_to_method_handle_entry(G3_method_handle, Rtemp, /* emit_delayed_nop */ false);
-  // Record SP so we can remove any stack space allocated by adapter transition
-  __ delayed()->mov(SP, Llast_SP);
+  // do the call
+  __ verify_oop(G5_method);
+  __ call_from_interpreter(Rscratch, Gargs, Rret);
 }