indy-amd64: Initial interpreter support.
authortwisti
Tue Sep 08 21:07:43 2009 +0200 (3 years ago)
changeset 9160c425aa6014
parent 90515c6ecdf54d
child 92992cf4a18b98
indy-amd64: Initial interpreter support.
indy-amd64.patch
series
--- 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
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/interpreter_
}
+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 @@ diff --git a/src/cpu/x86/vm/templateInte
// 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 @@ diff --git a/src/cpu/x86/vm/templateInte
+ __ 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 @@ diff --git a/src/cpu/x86/vm/templateInte
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 @@ diff --git a/src/cpu/x86/vm/templateTabl
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 @@ diff --git a/src/cpu/x86/vm/templateTabl
- __ 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 @@ diff --git a/src/cpu/x86/vm/templateTabl
// 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 @@ diff --git a/src/cpu/x86/vm/templateTabl
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 @@ diff --git a/src/cpu/x86/vm/templateTabl
__ bind(resolved);
}
-@@ -2834,10 +2847,14 @@
-
- void TemplateTable::prepare_invoke(Register method,
- Register index,
+@@ -2832,15 +2834,14 @@
+ ShouldNotReachHere();
+ }
+
+-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 @@ diff --git a/src/cpu/x86/vm/templateTabl
}
// do null check if needed
-@@ -2878,10 +2903,15 @@
+@@ -2878,10 +2883,14 @@
ConstantPoolCacheEntry::verify_tosBits();
// load return address
{
@@ -369,19 +389,18 @@ diff --git a/src/cpu/x86/vm/templateTabl
- 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 @@ diff --git a/src/cpu/x86/vm/templateTabl
// 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 @@ diff --git a/src/cpu/x86/vm/templateTabl
// 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 @@ diff --git a/src/cpu/x86/vm/templateTabl
// 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 @@ diff --git a/src/cpu/x86/vm/templateTabl
// rax: Interface
// rbx: index
-@@ -3075,6 +3105,83 @@
- __ stop("invokedynamic NYI");//6815692//
- }
-
-+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;
-+ }
-+
+@@ -3072,7 +3081,24 @@
+ return;
+ }
+
+- __ stop("invokedynamic NYI");//6815692//
+ prepare_invoke(rax, rbx, byte_no);
+
+ // rax: CallSite object (f1)
@@ -444,63 +450,18 @@ diff --git a/src/cpu/x86/vm/templateTabl
+
+ 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 @@ diff --git a/src/cpu/x86/vm/templateTabl
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
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