changeset 91:60c425aa6014

indy-amd64: Initial interpreter support.
author twisti
date Tue, 08 Sep 2009 21:07:43 +0200
parents 515c6ecdf54d
children 992cf4a18b98
files indy-amd64.patch series
diffstat 2 files changed, 161 insertions(+), 139 deletions(-) [+]
line wrap: on
line diff
--- a/indy-amd64.patch	Tue Sep 08 18:58:44 2009 +0200
+++ b/indy-amd64.patch	Tue Sep 08 21:07:43 2009 +0200
@@ -2,6 +2,18 @@
 Summary: changes for method handles and invokedynamic
 Reviewed-by: ?, ?
 
+diff --git a/src/cpu/x86/vm/assembler_x86.cpp b/src/cpu/x86/vm/assembler_x86.cpp
+--- a/src/cpu/x86/vm/assembler_x86.cpp
++++ b/src/cpu/x86/vm/assembler_x86.cpp
+@@ -7644,7 +7644,7 @@
+ 
+ #ifdef ASSERT
+   Label L;
+-  testl(tmp, tmp);
++  testptr(tmp, tmp);
+   jccb(Assembler::notZero, L);
+   hlt();
+   bind(L);
 diff --git a/src/cpu/x86/vm/interp_masm_x86_64.cpp b/src/cpu/x86/vm/interp_masm_x86_64.cpp
 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp
 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp
@@ -134,6 +146,18 @@
  }
  
  
+diff --git a/src/cpu/x86/vm/methodHandles_x86.cpp b/src/cpu/x86/vm/methodHandles_x86.cpp
+--- a/src/cpu/x86/vm/methodHandles_x86.cpp
++++ b/src/cpu/x86/vm/methodHandles_x86.cpp
+@@ -448,7 +448,7 @@
+                                 rbx_index, Address::times_ptr,
+                                 base + vtableEntry::method_offset_in_bytes());
+       Register rbx_method = rbx_temp;
+-      __ movl(rbx_method, vtable_entry_addr);
++      __ movptr(rbx_method, vtable_entry_addr);
+ 
+       __ verify_oop(rbx_method);
+       __ jmp(rbx_method_fie);
 diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp
 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -189,29 +213,11 @@
               // pass required type, failing object (or NULL)
               c_rarg1, c_rarg2);
    return entry;
-@@ -167,7 +172,15 @@
- 
- address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
-                                                                 int step, bool unbox) {
--  assert(!unbox, "NYI");//6815692//
-+  TosState incoming_state = state;
-+  if (EnableInvokeDynamic) {
-+    if (unbox) {
-+      incoming_state = atos;
-+    }
-+    Unimplemented();
-+  } else {
-+    assert(!unbox, "old behavior");
-+  }
- 
-   // amd64 doesn't need to do anything special about compiled returns
-   // to the interpreter so the code that exists on x86 to place a sentinel
-@@ -183,7 +196,14 @@
+@@ -182,15 +187,29 @@
    __ restore_bcp();
    __ restore_locals();
  
 -  __ get_cache_and_index_at_bcp(rbx, rcx, 1);
-+
 +  Label L_got_cache, L_giant_index;
 +  if (EnableInvokeDynamic) {
 +    __ cmpb(Address(r13, 0), Bytecodes::_invokedynamic);
@@ -220,14 +226,18 @@
 +  __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
 +  __ bind(L_got_cache);
    __ movl(rbx, Address(rbx, rcx,
-                        Address::times_8,
+-                       Address::times_8,
++                       Address::times_ptr,
                         in_bytes(constantPoolCacheOopDesc::base_offset()) +
-@@ -192,6 +212,12 @@
+                        3 * wordSize));
+   __ andl(rbx, 0xFF);
    if (TaggedStackInterpreter) __ shll(rbx, 1); // 2 slots per parameter.
    __ lea(rsp, Address(rsp, rbx, Address::times_8));
    __ dispatch_next(state, step);
 +
++  // out of the main line of code...
 +  if (EnableInvokeDynamic) {
++    __ bind(L_giant_index);
 +    __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
 +    __ jmp(L_got_cache);
 +  }
@@ -235,11 +245,29 @@
    return entry;
  }
  
+diff --git a/src/cpu/x86/vm/templateTable_x86_32.cpp b/src/cpu/x86/vm/templateTable_x86_32.cpp
+--- a/src/cpu/x86/vm/templateTable_x86_32.cpp
++++ b/src/cpu/x86/vm/templateTable_x86_32.cpp
+@@ -3146,7 +3146,6 @@
+     __ profile_call(rsi);
+   }
+ 
+-  Label handle_unlinked_site;
+   __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx)));
+   __ null_check(rcx);
+   __ prepare_to_jump_from_interpreted();
 diff --git a/src/cpu/x86/vm/templateTable_x86_64.cpp b/src/cpu/x86/vm/templateTable_x86_64.cpp
 --- a/src/cpu/x86/vm/templateTable_x86_64.cpp
 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp
-@@ -209,12 +209,12 @@
-                scratch, r13, bc);
+@@ -203,18 +203,15 @@
+     __ jcc(Assembler::notEqual, fast_patch);
+     __ get_method(scratch);
+     // Let breakpoint table handling rewrite to quicker bytecode
+-    __ call_VM(noreg,
+-               CAST_FROM_FN_PTR(address,
+-                                InterpreterRuntime::set_original_bytecode_at),
+-               scratch, r13, bc);
++    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, r13, bc);
  #ifndef ASSERT
      __ jmpb(patch_done);
 +#else
@@ -255,18 +283,23 @@
    Label okay;
    __ load_unsigned_byte(scratch, at_bcp(0));
    __ cmpl(scratch, (int) Bytecodes::java_code(bytecode));
-@@ -2058,6 +2058,7 @@
-                                             Register Rcache,
-                                             Register index) {
+@@ -2054,26 +2051,28 @@
+   }
+ }
+ 
+-void TemplateTable::resolve_cache_and_index(int byte_no,
+-                                            Register Rcache,
+-                                            Register index) {
++void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) {
    assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
 +  bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
  
    const Register temp = rbx;
    assert_different_registers(Rcache, index, temp);
-@@ -2065,15 +2066,24 @@
+ 
    const int shift_count = (1 + byte_no) * BitsPerByte;
    Label resolved;
-   __ get_cache_and_index_at_bcp(Rcache, index, 1);
+-  __ get_cache_and_index_at_bcp(Rcache, index, 1);
 -  __ movl(temp, Address(Rcache,
 -                        index, Address::times_8,
 -                        constantPoolCacheOopDesc::base_offset() +
@@ -276,18 +309,13 @@
 -  __ andl(temp, 0xFF);
 -  __ cmpl(temp, (int) bytecode());
 -  __ jcc(Assembler::equal, resolved);
++  __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
 +  if (is_invokedynamic) {
 +    // we are resolved if the f1 field contains a non-null CallSite object
-+    __ cmpptr(Address(Rcache,
-+                      index, Address::times_ptr,
-+                      constantPoolCacheOopDesc::base_offset() +
-+                      ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
++    __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
 +    __ jcc(Assembler::notEqual, resolved);
 +  } else {
-+    __ movl(temp, Address(Rcache,
-+                          index, Address::times_ptr,
-+                          constantPoolCacheOopDesc::base_offset() +
-+                          ConstantPoolCacheEntry::indices_offset()));
++    __ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
 +    __ shrl(temp, shift_count);
 +    // have we resolved this bytecode?
 +    __ andl(temp, 0xFF);
@@ -297,7 +325,7 @@
  
    // resolve first time through
    address entry;
-@@ -2090,6 +2100,9 @@
+@@ -2090,6 +2089,9 @@
    case Bytecodes::_invokeinterface:
      entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
      break;
@@ -307,7 +335,7 @@
    default:
      ShouldNotReachHere();
      break;
-@@ -2098,7 +2111,7 @@
+@@ -2098,7 +2100,7 @@
    __ call_VM(noreg, entry, temp);
  
    // Update registers with resolved info
@@ -316,42 +344,34 @@
    __ bind(resolved);
  }
  
-@@ -2834,10 +2847,14 @@
+@@ -2832,15 +2834,14 @@
+   ShouldNotReachHere();
+ }
  
- void TemplateTable::prepare_invoke(Register method,
-                                    Register index,
+-void TemplateTable::prepare_invoke(Register method,
+-                                   Register index,
 -                                   int byte_no,
 -                                   Bytecodes::Code code) {
-+                                   int byte_no) {
-+  bool neg_byte_no = (byte_no < 0);
-+  if (neg_byte_no)  byte_no = -byte_no;
-+
++void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) {
    // determine flags
 +  Bytecodes::Code code = bytecode();
    const bool is_invokeinterface  = code == Bytecodes::_invokeinterface;
 +  const bool is_invokedynamic    = code == Bytecodes::_invokedynamic;
    const bool is_invokevirtual    = code == Bytecodes::_invokevirtual;
    const bool is_invokespecial    = code == Bytecodes::_invokespecial;
-   const bool load_receiver       = code != Bytecodes::_invokestatic;
-@@ -2848,6 +2865,9 @@
-   const Register flags  = rdx;
-   assert_different_registers(method, index, recv, flags);
- 
-+  assert(!neg_byte_no || is_invokedynamic, "byte_no<0 hack only for invdyn");
-+  const bool is_invdyn_bootstrap = neg_byte_no;
-+
-   // save 'interpreter return address'
-   __ save_bcp();
- 
-@@ -2858,9 +2878,14 @@
+-  const bool load_receiver       = code != Bytecodes::_invokestatic;
++  const bool load_receiver      = (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic);
+   const bool receiver_null_check = is_invokespecial;
+   const bool save_flags = is_invokeinterface || is_invokevirtual;
+   // setup registers & access constant pool cache
+@@ -2858,9 +2859,13 @@
      __ movl(recv, flags);
      __ andl(recv, 0xFF);
      if (TaggedStackInterpreter) __ shll(recv, 1);  // index*2
 -    __ movptr(recv, Address(rsp, recv, Address::times_8,
 -                                 -Interpreter::expr_offset_in_bytes(1)));
 -    __ verify_oop(recv);
-+    Address recv_addr(rsp, recv, Address::times_8,
-+                           -Interpreter::expr_offset_in_bytes(1));
++    Address recv_addr(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1));
 +    if (is_invokedynamic) {
 +      __ lea(recv, recv_addr);
 +    } else {
@@ -361,7 +381,7 @@
    }
  
    // do null check if needed
-@@ -2878,10 +2903,15 @@
+@@ -2878,10 +2883,14 @@
    ConstantPoolCacheEntry::verify_tosBits();
    // load return address
    {
@@ -369,19 +389,18 @@
 -    ExternalAddress return_3((address)Interpreter::return_3_addrs_by_index_table());
 -    __ lea(rscratch1, (is_invokeinterface ? return_5 : return_3));
 -    __ movptr(flags, Address(rscratch1, flags, Address::times_8));
-+    address table_addr =
-+      (is_invdyn_bootstrap)
-+      ? (address)Interpreter::return_5_unbox_addrs_by_index_table()
-+      : (is_invokeinterface || is_invokedynamic)
-+      ? (address)Interpreter::return_5_addrs_by_index_table()
-+      : (address)Interpreter::return_3_addrs_by_index_table();
++    address table_addr;
++    if (is_invokeinterface || is_invokedynamic)
++      table_addr = (address)Interpreter::return_5_addrs_by_index_table();
++    else
++      table_addr = (address)Interpreter::return_3_addrs_by_index_table();
 +    ExternalAddress table(table_addr);
 +    __ lea(rscratch1, table);
 +    __ movptr(flags, Address(rscratch1, flags, Address::times_ptr));
    }
  
    // push return address
-@@ -2947,7 +2977,7 @@
+@@ -2947,7 +2956,7 @@
  
  void TemplateTable::invokevirtual(int byte_no) {
    transition(vtos, vtos);
@@ -390,7 +409,7 @@
  
    // rbx: index
    // rcx: receiver
-@@ -2959,7 +2989,7 @@
+@@ -2959,7 +2968,7 @@
  
  void TemplateTable::invokespecial(int byte_no) {
    transition(vtos, vtos);
@@ -399,7 +418,7 @@
    // do the call
    __ verify_oop(rbx);
    __ profile_call(rax);
-@@ -2969,7 +2999,7 @@
+@@ -2969,7 +2978,7 @@
  
  void TemplateTable::invokestatic(int byte_no) {
    transition(vtos, vtos);
@@ -408,7 +427,7 @@
    // do the call
    __ verify_oop(rbx);
    __ profile_call(rax);
-@@ -2983,7 +3013,7 @@
+@@ -2983,7 +2992,7 @@
  
  void TemplateTable::invokeinterface(int byte_no) {
    transition(vtos, vtos);
@@ -417,24 +436,11 @@
  
    // rax: Interface
    // rbx: index
-@@ -3075,6 +3105,83 @@
-   __ stop("invokedynamic NYI");//6815692//
- }
+@@ -3072,7 +3081,24 @@
+     return;
+   }
  
-+void TemplateTable::invokedynamic(int byte_no) {
-+  transition(vtos, vtos);
-+
-+  if (!EnableInvokeDynamic) {
-+    // We should not encounter this bytecode if !EnableInvokeDynamic.
-+    // The verifier will stop it.  However, if we get past the verifier,
-+    // this will stop the thread in a reasonable way, without crashing the JVM.
-+    __ call_VM(noreg, CAST_FROM_FN_PTR(address,
-+                     InterpreterRuntime::throw_IncompatibleClassChangeError));
-+    // the call_VM checks for exception, so we should never return here.
-+    __ should_not_reach_here();
-+    return;
-+  }
-+
+-  __ stop("invokedynamic NYI");//6815692//
 +  prepare_invoke(rax, rbx, byte_no);
 +
 +  // rax: CallSite object (f1)
@@ -444,63 +450,18 @@
 +
 +  if (ProfileInterpreter) {
 +    Label L;
-+    __ movl(rdx, Address(rcx, 0));
-+    __ testl(rdx, rdx);
-+    __ jcc(Assembler::zero, L);
-+
-+    // Get receiver klass into rdx
-+    __ movl(rdx, Address(rdx, oopDesc::klass_offset_in_bytes()));
-+    __ verify_oop(rdx);
-+    __ bind(L);
-+
++    // %%% should make a type profile for any invokedynamic that takes a ref argument
 +    // profile this call
-+    __ profile_virtual_call(rdx, r13, r14, true);
++    __ profile_call(r13);
 +  }
 +
-+  Label handle_unlinked_site;
-+  __ movptr(rcx, Address(rax, __ delayed_value(sun_dyn_CallSiteImpl::target_offset_in_bytes, rcx)));
-+  __ testptr(rcx, rcx);
-+  __ jcc(Assembler::zero, handle_unlinked_site);
-+
++  __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_CallSite::target_offset_in_bytes, rcx)));
++  __ null_check(rcx);
 +  __ prepare_to_jump_from_interpreted();
 +  __ jump_to_method_handle_entry(rcx, rdx);
-+
-+  // Initial calls come here...
-+  __ bind(handle_unlinked_site);
-+  __ pop(rcx);                 // remove return address pushed by prepare_invoke
-+
-+  address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic);
-+  // squish stacked arguments together on stack, preceded by call site
-+  // return bootstrap method as a handle in rcx
-+  __ restore_bcp();      // rsi must be correct for call_VM
-+  __ call_VM(rax, entry, rax);
-+  __ movl(rdi, rax);            // protect MH from prepare_invoke
-+
-+  // recompute return address
-+  __ restore_bcp();      // rsi must be correct for prepare_invoke
-+  prepare_invoke(rax, rbx, -byte_no);
-+  // rax: CallSite object (f1)
-+  // rbx: unused (f2)
-+  // rcx: receiver address (now holds arglist)
-+  // rdx: flags
-+
-+  // save SP now, before we add the bootstrap call to the stack 
-+  __ prepare_to_jump_from_interpreted();
-+
-+  // let's play adapter
-+  __ pop(rbx);                  // return value
-+  __ push(rdi);                 // boot MH
-+  __ push(rax);                 // call site
-+  __ movptr(rcx, Address(rcx, 0));
-+  __ push(rcx);                 // arglist
-+  __ push(rbx);                 // return value
-+  __ mov(rcx, rdi);
-+  __ jump_to_method_handle_entry(rcx, rdx);
-+}
-+
+ }
  
- //-----------------------------------------------------------------------------
- // Allocation
+ 
 diff --git a/src/cpu/x86/vm/templateTable_x86_64.hpp b/src/cpu/x86/vm/templateTable_x86_64.hpp
 --- a/src/cpu/x86/vm/templateTable_x86_64.hpp
 +++ b/src/cpu/x86/vm/templateTable_x86_64.hpp
@@ -514,3 +475,64 @@
    static void invokevirtual_helper(Register index, Register recv,
                                     Register flags);
    static void volatile_barrier(Assembler::Membar_mask_bits order_constraint);
+diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp
+--- a/src/share/vm/classfile/classFileParser.cpp
++++ b/src/share/vm/classfile/classFileParser.cpp
+@@ -2514,23 +2514,23 @@
+       fac_ptr->nonstatic_byte_count -= 1;
+       (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset,
+                                    word_sig_index);
+-      if (wordSize == jintSize) {
++//       if (wordSize == jintSize) {
+         fac_ptr->nonstatic_word_count += 1;
+-      } else {
+-        fac_ptr->nonstatic_double_count += 1;
+-      }
+-
+-      FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i+4);
++//       } else {
++//         fac_ptr->nonstatic_double_count += 1;
++//       }
++
++      FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i + instanceKlass::low_offset);
+       assert(atype == NONSTATIC_BYTE, "");
+       FieldAllocationType new_atype = NONSTATIC_WORD;
+-      if (wordSize > jintSize) {
+-        if (Universe::field_type_should_be_aligned(T_LONG)) {
+-          atype = NONSTATIC_ALIGNED_DOUBLE;
+-        } else {
+-          atype = NONSTATIC_DOUBLE;
+-        }
+-      }
+-      (*fields_ptr)->ushort_at_put(i+4, new_atype);
++//       if (wordSize > jintSize) {
++//         if (Universe::field_type_should_be_aligned(T_LONG)) {
++//           atype = NONSTATIC_ALIGNED_DOUBLE;
++//         } else {
++//           atype = NONSTATIC_DOUBLE;
++//         }
++//       }
++      (*fields_ptr)->ushort_at_put(i + instanceKlass::low_offset, new_atype);
+ 
+       found_vmentry = true;
+       break;
+@@ -3078,7 +3078,7 @@
+     int len = fields->length();
+     for (int i = 0; i < len; i += instanceKlass::next_offset) {
+       int real_offset;
+-      FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i+4);
++      FieldAllocationType atype = (FieldAllocationType) fields->ushort_at(i + instanceKlass::low_offset);
+       switch (atype) {
+         case STATIC_OOP:
+           real_offset = next_static_oop_offset;
+@@ -3164,8 +3164,8 @@
+         default:
+           ShouldNotReachHere();
+       }
+-      fields->short_at_put(i+4, extract_low_short_from_int(real_offset) );
+-      fields->short_at_put(i+5, extract_high_short_from_int(real_offset) );
++      fields->short_at_put(i + instanceKlass::low_offset,  extract_low_short_from_int(real_offset));
++      fields->short_at_put(i + instanceKlass::high_offset, extract_high_short_from_int(real_offset));
+     }
+ 
+     // Size of instances
--- a/series	Tue Sep 08 18:58:44 2009 +0200
+++ b/series	Tue Sep 08 21:07:43 2009 +0200
@@ -5,10 +5,10 @@
 nonperm-6863023.patch           #-/meth #+12ea00a010fb
 meth-6815692.patch              #-/meth #+12ea00a010fb
 indy-6858164.patch              #-/indy #+12ea00a010fb
+indy-amd64.patch                #-/indy #+12ea00a010fb
 meth.walker.patch               #-/meth #+12ea00a010fb
 indy.compiler.patch             #-/indy #+12ea00a010fb
 indy.compiler.inline.patch      #-/indy #+12ea00a010fb #-testable
-indy-amd64.patch                #-/indy #+12ea00a010fb #-buildable
 indy-sparc.patch                #-/indy #+12ea00a010fb #-buildable
 
 meth.proj.patch                 #-/meth #+projects