indy: rebase to meth series and to bsd-port, redo opcode to be receiverless
authorjrose
Fri Apr 03 00:24:23 2009 -0700 (7 months ago)
changeset 3884689b088293
parent 37590fe9969f83
child 39ef70a7045609
indy: rebase to meth series and to bsd-port, redo opcode to be receiverless
indy.patch
series
--- a/indy.patch Sat Mar 21 23:57:50 2009 -0700
+++ b/indy.patch Fri Apr 03 00:24:23 2009 -0700
@@ -12,7 +12,7 @@ diff --git a/src/cpu/sparc/vm/interp_mas
+ if (!giant_index) {
+ get_2_byte_integer_at_bcp(bcp_offset, Rtmp, Rdst, Unsigned);
+ } else {
-+ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
++ assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
+ get_4_byte_integer_at_bcp(bcp_offset, Rtmp, Rdst);
+ assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
+ xor3(Rdst, -1, Rdst); // convert to plain index
@@ -43,7 +43,7 @@ diff --git a/src/cpu/sparc/vm/interp_mas
get_2_byte_integer_at_bcp(bcp_offset, cache, tmp, Unsigned);
// convert from field index to ConstantPoolCacheEntry index
// and from word index to byte offset
-@@ -1739,7 +1757,8 @@
+@@ -1692,7 +1710,8 @@
// Count a virtual call in the bytecodes.
void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
@@ -80,14 +80,14 @@ diff --git a/src/cpu/sparc/vm/templateIn
diff --git a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
+++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp
-@@ -160,7 +160,16 @@
+@@ -150,7 +150,16 @@
}
-address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) {
+address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) {
+ TosState incoming_state = state;
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ if (unbox) {
+ incoming_state = atos;
+ }
@@ -98,7 +98,7 @@ diff --git a/src/cpu/sparc/vm/templateIn
address compiled_entry = __ pc();
Label cont;
-@@ -175,7 +184,7 @@
+@@ -165,7 +174,7 @@
// do this here. Unfortunately if we did a rethrow we'd see an machepilog node
// first which would move g1 -> O0/O1 and destroy the exception we were throwing.
@@ -107,7 +107,7 @@ diff --git a/src/cpu/sparc/vm/templateIn
__ srl (G1, 0,O1);
__ srlx(G1,32,O0);
}
-@@ -192,16 +201,42 @@
+@@ -182,10 +191,27 @@
__ mov(Llast_SP, SP); // Remove any adapter added stack space.
@@ -119,7 +119,7 @@ diff --git a/src/cpu/sparc/vm/templateIn
const Register cache = G3_scratch;
const Register size = G1_scratch;
+ Label L_got_cache, L_giant_index;
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ __ ldub(Lbcp, 0, size);
+ __ cmp(size, Bytecodes::_invokedynamic);
+ __ br(Assembler::equal, false, Assembler::pn, L_giant_index);
@@ -135,35 +135,40 @@ diff --git a/src/cpu/sparc/vm/templateIn
__ ld_ptr(Address(cache, 0, in_bytes(constantPoolCacheOopDesc::base_offset()) +
in_bytes(ConstantPoolCacheEntry::flags_offset())), size);
__ and3(size, 0xFF, size); // argument size in words
- __ sll(size, Interpreter::logStackElementSize(), size); // each argument size in bytes
+@@ -193,6 +219,15 @@
__ add(Lesp, size, Lesp); // pop arguments
__ dispatch_next(state, step);
-+
+
+ // out of the main line of code...
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ __ bind(L_giant_index);
+ __ unimplemented();
+ ////__ get_cache_and_index_at_bcp(cache, G1_scratch, 1, true);
+ __ ba(false, L_got_cache);
+ __ delayed()->nop();
+ }
-
++
return entry;
}
+
diff --git a/src/cpu/sparc/vm/templateTable_sparc.cpp b/src/cpu/sparc/vm/templateTable_sparc.cpp
--- a/src/cpu/sparc/vm/templateTable_sparc.cpp
+++ b/src/cpu/sparc/vm/templateTable_sparc.cpp
-@@ -3125,6 +3125,20 @@
+@@ -3125,6 +3125,24 @@
}
+void TemplateTable::invokedynamic(int byte_no) {
+ transition(vtos, vtos);
+
-+ if (!InvokeDynamic) {
-+ // We do not encounter this bytecode if !InvokeDynamic.
-+ // See Rewriter::rewrite_invokedynamic.
-+ __ stop("invokedynamic not enabled");
++ 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;
+ }
+
@@ -185,9 +190,9 @@ diff --git a/src/cpu/x86/vm/interp_masm_
+void InterpreterMacroAssembler::get_cache_index_at_bcp(Register reg, int bcp_offset, bool giant_index) {
assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
+ if (!giant_index) {
-+ load_unsigned_word(reg, Address(rsi, bcp_offset));
++ load_unsigned_short(reg, Address(rsi, bcp_offset));
+ } else {
-+ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
++ assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
+ movl(reg, Address(rsi, bcp_offset));
+ assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
+ notl(reg); // convert to plain index
@@ -198,7 +203,7 @@ diff --git a/src/cpu/x86/vm/interp_masm_
+void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index,
+ int bcp_offset, bool giant_index) {
assert(cache != index, "must use different registers");
-- load_unsigned_word(index, Address(rsi, bcp_offset));
+- load_unsigned_short(index, Address(rsi, bcp_offset));
+ get_cache_index_at_bcp(index, bcp_offset, giant_index);
movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
@@ -211,12 +216,12 @@ diff --git a/src/cpu/x86/vm/interp_masm_
+void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
+ int bcp_offset, bool giant_index) {
assert(cache != tmp, "must use different register");
-- load_unsigned_word(tmp, Address(rsi, bcp_offset));
+- load_unsigned_short(tmp, Address(rsi, bcp_offset));
+ get_cache_index_at_bcp(tmp, bcp_offset, giant_index);
assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
// convert from field index to ConstantPoolCacheEntry index
// and from word offset to byte offset
-@@ -1245,7 +1258,9 @@
+@@ -1214,7 +1227,9 @@
}
@@ -227,7 +232,7 @@ diff --git a/src/cpu/x86/vm/interp_masm_
if (ProfileInterpreter) {
Label profile_continue;
-@@ -1255,8 +1270,15 @@
+@@ -1224,8 +1239,15 @@
// We are making a call. Increment the count.
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
@@ -280,9 +285,9 @@ diff --git a/src/cpu/x86/vm/interp_masm_
+ bool giant_index) {
+ assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
+ if (!giant_index) {
-+ load_unsigned_word(index, Address(r13, bcp_offset));
++ load_unsigned_short(index, Address(r13, bcp_offset));
+ } else {
-+ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
++ assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
+ movl(index, Address(r13, bcp_offset));
+ assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
+ notl(index); // convert to plain index
@@ -297,7 +302,7 @@ diff --git a/src/cpu/x86/vm/interp_masm_
+ int bcp_offset,
+ bool giant_index) {
assert(cache != index, "must use different registers");
-- load_unsigned_word(index, Address(r13, bcp_offset));
+- load_unsigned_short(index, Address(r13, bcp_offset));
+ get_cache_index_at_bcp(index, bcp_offset, giant_index);
movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
@@ -311,12 +316,12 @@ diff --git a/src/cpu/x86/vm/interp_masm_
+ int bcp_offset,
+ bool giant_index) {
assert(cache != tmp, "must use different register");
-- load_unsigned_word(tmp, Address(r13, bcp_offset));
+- load_unsigned_short(tmp, Address(r13, bcp_offset));
+ get_cache_index_at_bcp(tmp, bcp_offset, giant_index);
assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
// convert from field index to ConstantPoolCacheEntry index
// and from word offset to byte offset
-@@ -1288,7 +1303,8 @@
+@@ -1236,7 +1251,8 @@
void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
Register mdp,
@@ -326,7 +331,7 @@ diff --git a/src/cpu/x86/vm/interp_masm_
if (ProfileInterpreter) {
Label profile_continue;
-@@ -1298,8 +1314,15 @@
+@@ -1246,8 +1262,15 @@
// We are making a call. Increment the count.
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
@@ -371,14 +376,14 @@ diff --git a/src/cpu/x86/vm/templateInte
diff --git a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
+++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp
-@@ -166,13 +166,22 @@
+@@ -156,13 +156,22 @@
}
-address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) {
+address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) {
+ TosState incoming_state = state;
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ if (unbox) {
+ incoming_state = atos;
+ }
@@ -396,7 +401,7 @@ diff --git a/src/cpu/x86/vm/templateInte
for (int i = 1; i < 8; i++) {
__ ffree(i);
}
-@@ -180,7 +189,7 @@
+@@ -170,7 +179,7 @@
__ empty_FPU_stack();
}
#endif
@@ -405,7 +410,7 @@ diff --git a/src/cpu/x86/vm/templateInte
__ MacroAssembler::verify_FPU(1, "generate_return_entry_for compiled");
} else {
__ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled");
-@@ -196,12 +205,12 @@
+@@ -186,12 +195,12 @@
// In SSE mode, interpreter returns FP results in xmm0 but they need
// to end up back on the FPU so it can operate on them.
@@ -420,7 +425,7 @@ diff --git a/src/cpu/x86/vm/templateInte
__ subptr(rsp, 2*wordSize);
__ movdbl(Address(rsp, 0), xmm0);
__ fld_d(Address(rsp, 0));
-@@ -217,13 +226,116 @@
+@@ -207,13 +216,115 @@
__ restore_bcp();
__ restore_locals();
@@ -432,7 +437,7 @@ diff --git a/src/cpu/x86/vm/templateInte
+ // cast and unbox
+ BasicType type = as_BasicType(state);
+ if (type == T_BYTE) type = T_BOOLEAN; // FIXME
-+ KlassHandle boxk = KlassHandles::box_klass(type);
++ KlassHandle boxk = SystemDictionaryHandles::box_klass(type);
+ __ mov32(rbx, ExternalAddress((address) boxk.raw_value()));
+ __ testl(rax, rax);
+ Label L_got_value, L_get_value;
@@ -452,15 +457,15 @@ diff --git a/src/cpu/x86/vm/templateInte
+ // Cf. TemplateTable::getfield_or_static
+ switch (type) {
+ case T_BYTE: // fall through:
-+ case T_BOOLEAN: __ load_signed_byte(rax, Address(rax, offset)); break;
-+ case T_CHAR: __ load_unsigned_word(rax, Address(rax, offset)); break;
-+ case T_SHORT: __ load_signed_word(rax, Address(rax, offset)); break;
-+ case T_INT: __ movl(rax, Address(rax, offset)); break;
-+ case T_FLOAT: __ fld_s(Address(rax, offset)); break;
-+ case T_DOUBLE: __ fld_d(Address(rax, offset)); break;
++ case T_BOOLEAN: __ load_signed_byte(rax, Address(rax, offset)); break;
++ case T_CHAR: __ load_unsigned_short(rax, Address(rax, offset)); break;
++ case T_SHORT: __ load_signed_short(rax, Address(rax, offset)); break;
++ case T_INT: __ movl(rax, Address(rax, offset)); break;
++ case T_FLOAT: __ fld_s(Address(rax, offset)); break;
++ case T_DOUBLE: __ fld_d(Address(rax, offset)); break;
+ // Access to java.lang.Double.value does not need to be atomic:
+ case T_LONG: { __ movl(rdx, Address(rax, offset + 4));
-+ __ movl(rax, Address(rax, offset + 0)); } break;
++ __ movl(rax, Address(rax, offset + 0)); } break;
+ default: ShouldNotReachHere();
+ }
+ __ bind(L_got_value);
@@ -480,7 +485,7 @@ diff --git a/src/cpu/x86/vm/templateInte
+ }
+
+ Label L_got_cache, L_giant_index;
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic);
+ __ jcc(Assembler::equal, L_giant_index);
+ }
@@ -492,23 +497,22 @@ diff --git a/src/cpu/x86/vm/templateInte
+ __ testl(rax, rax);
+ __ jcc(Assembler::zero, L_ok);
+ __ push(rax); // save the object to check
-+ __ movl(rax, Address(rax, oopDesc::klass_offset_in_bytes()));
+ __ push(rbx); // save CP cache reference
-+ __ push(rcx); // save CP cache reference
++ __ movl(rdx, Address(rax, oopDesc::klass_offset_in_bytes()));
+ __ movl(rbx, Address(rbx, rcx,
+ Address::times_4, constantPoolCacheOopDesc::base_offset() +
+ ConstantPoolCacheEntry::f1_offset()));
-+ __ movl(rbx, Address(rbx, __ delayed_value(java_dyn_impl_DynCallSite::type_offset_in_bytes, rcx)));
++ __ movl(rbx, Address(rbx, __ delayed_value(impl_java_dyn_CallSiteImpl::type_offset_in_bytes, rcx)));
+ __ movl(rbx, Address(rbx, __ delayed_value(java_dyn_MethodType::rtype_offset_in_bytes, rcx)));
-+ __ movl(rbx, Address(rbx, __ delayed_value(java_lang_Class::klass_offset_in_bytes, rcx)));
-+ __ check_klass_subtype(rax, rbx, rcx, L_ok_pops);
-+ __ addptr(rsp, 2*wordSize); // toss rcx, keep rbx as failed klass
-+ __ pop(rax);
++ __ movl(rax, Address(rbx, __ delayed_value(java_lang_Class::klass_offset_in_bytes, rcx)));
++ __ check_klass_subtype(rdx, rax, rbx, L_ok_pops);
++ __ pop(rcx); // pop and discard CP cache
++ __ mov(rbx, rax); // target supertype into rbx for L_fail
++ __ pop(rax); // failed object into rax for L_fail
+ __ jmp(L_fail);
+
+ __ bind(L_ok_pops);
+ // restore pushed temp regs:
-+ __ pop(rcx);
+ __ pop(rbx);
+ __ pop(rax);
+ __ bind(L_ok);
@@ -521,7 +525,7 @@ diff --git a/src/cpu/x86/vm/templateInte
__ dispatch_next(state, step);
+
+ // out of the main line of code...
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ __ bind(L_giant_index);
+ __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
+ __ jmp(L_got_cache);
@@ -541,7 +545,7 @@ diff --git a/src/cpu/x86/vm/templateInte
diff --git a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
+++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp
-@@ -176,7 +176,17 @@
+@@ -171,7 +171,17 @@
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
@@ -549,7 +553,7 @@ diff --git a/src/cpu/x86/vm/templateInte
+ int step,
+ bool unbox) {
+ TosState incoming_state = state;
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ if (unbox) {
+ incoming_state = atos;
+ }
@@ -560,14 +564,14 @@ diff --git a/src/cpu/x86/vm/templateInte
// 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
-@@ -191,7 +201,14 @@
-
+@@ -187,7 +197,14 @@
__ restore_bcp();
__ restore_locals();
+
- __ get_cache_and_index_at_bcp(rbx, rcx, 1);
+
+ Label L_got_cache, L_giant_index;
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ __ cmpb(Address(r13, 0), Bytecodes::_invokedynamic);
+ __ jcc(Assembler::equal, L_giant_index);
+ }
@@ -576,12 +580,12 @@ diff --git a/src/cpu/x86/vm/templateInte
__ movl(rbx, Address(rbx, rcx,
Address::times_8,
in_bytes(constantPoolCacheOopDesc::base_offset()) +
-@@ -200,6 +217,12 @@
+@@ -196,6 +213,12 @@
if (TaggedStackInterpreter) __ shll(rbx, 1); // 2 slots per parameter.
__ lea(rsp, Address(rsp, rbx, Address::times_8));
__ dispatch_next(state, step);
+
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
+ __ jmp(L_got_cache);
+ }
@@ -617,15 +621,18 @@ diff --git a/src/cpu/x86/vm/templateTabl
Register temp = rbx;
-@@ -2112,13 +2113,19 @@
+@@ -2112,16 +2113,19 @@
const int shift_count = (1 + byte_no)*BitsPerByte;
Label resolved;
- __ get_cache_and_index_at_bcp(Rcache, index, 1);
-- __ movl(temp, Address(Rcache, index, Address::times_4, 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);
+- __ andptr(temp, 0xFF);
- __ cmpl(temp, (int)bytecode());
- __ jcc(Assembler::equal, resolved);
+ __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
@@ -644,7 +651,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
// resolve first time through
address entry;
-@@ -2131,12 +2138,13 @@
+@@ -2134,12 +2138,13 @@
case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokestatic : // fall through
case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
@@ -659,7 +666,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
__ bind(resolved);
}
-@@ -2881,9 +2889,14 @@
+@@ -2884,9 +2889,14 @@
}
@@ -675,21 +682,21 @@ diff --git a/src/cpu/x86/vm/templateTabl
const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
const bool is_invokespecial = code == Bytecodes::_invokespecial;
const bool load_receiver = code != Bytecodes::_invokestatic;
-@@ -2893,6 +2906,9 @@
- const Register recv = rcx;
+@@ -2897,6 +2907,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();
-@@ -2904,8 +2920,13 @@
+
+@@ -2907,8 +2920,13 @@
__ movl(recv, flags);
__ andl(recv, 0xFF);
// recv count is 0 based?
-- __ movl(recv, Address(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)));
+- __ movptr(recv, Address(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)));
- __ verify_oop(recv);
+ Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1));
+ if (is_invokedynamic) {
@@ -701,16 +708,12 @@ diff --git a/src/cpu/x86/vm/templateTabl
}
// do null check if needed
-@@ -2922,11 +2943,15 @@
- // Make sure we don't need to mask flags for tosBits after the above shift
+@@ -2926,8 +2944,13 @@
ConstantPoolCacheEntry::verify_tosBits();
// load return address
-- { const int table =
-- is_invokeinterface
-- ? (int)Interpreter::return_5_addrs_by_index_table()
-- : (int)Interpreter::return_3_addrs_by_index_table();
-- __ movl(flags, Address(noreg, flags, Address::times_4, table));
-+ {
+ {
+- ExternalAddress table(is_invokeinterface ? (address)Interpreter::return_5_addrs_by_index_table() :
+- (address)Interpreter::return_3_addrs_by_index_table());
+ address table_addr =
+ (is_invdyn_bootstrap)
+ ? (address)Interpreter::return_5_unbox_addrs_by_index_table()
@@ -718,11 +721,10 @@ diff --git a/src/cpu/x86/vm/templateTabl
+ ? (address)Interpreter::return_5_addrs_by_index_table()
+ : (address)Interpreter::return_3_addrs_by_index_table();
+ ExternalAddress table(table_addr);
-+ __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr)));
- }
-
- // push return address
-@@ -2988,7 +3013,7 @@
+ __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr)));
+ }
+
+@@ -2990,7 +3013,7 @@
void TemplateTable::invokevirtual(int byte_no) {
transition(vtos, vtos);
@@ -731,7 +733,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
// rbx,: index
// rcx: receiver
-@@ -3000,7 +3025,7 @@
+@@ -3002,7 +3025,7 @@
void TemplateTable::invokespecial(int byte_no) {
transition(vtos, vtos);
@@ -740,7 +742,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
// do the call
__ verify_oop(rbx);
__ profile_call(rax);
-@@ -3010,7 +3035,7 @@
+@@ -3012,7 +3035,7 @@
void TemplateTable::invokestatic(int byte_no) {
transition(vtos, vtos);
@@ -749,7 +751,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
// do the call
__ verify_oop(rbx);
__ profile_call(rax);
-@@ -3026,7 +3051,7 @@
+@@ -3028,7 +3051,7 @@
void TemplateTable::invokeinterface(int byte_no) {
transition(vtos, vtos);
@@ -758,19 +760,21 @@ diff --git a/src/cpu/x86/vm/templateTabl
// rax,: Interface
// rbx,: index
-@@ -3176,6 +3201,79 @@
- // rcx: receiver
- // rbx,: methodOop
- __ jump_from_interpreted(rbx, rdx);
-+}
-+
+@@ -3102,6 +3125,83 @@
+ __ should_not_reach_here();
+ }
+
+void TemplateTable::invokedynamic(int byte_no) {
+ transition(vtos, vtos);
+
-+ if (!InvokeDynamic) {
-+ // We do not encounter this bytecode if !InvokeDynamic.
-+ // See Rewriter::rewrite_invokedynamic.
-+ __ stop("invokedynamic not enabled");
++ 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;
+ }
+
@@ -797,7 +801,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
+ }
+
+ Label handle_unlinked_site;
-+ __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_impl_DynCallSite::target_offset_in_bytes, rcx)));
++ __ movptr(rcx, Address(rax, __ delayed_value(impl_java_dyn_CallSiteImpl::target_offset_in_bytes, rcx)));
+ __ testptr(rcx, rcx);
+ __ jcc(Assembler::zero, handle_unlinked_site);
+
@@ -835,9 +839,11 @@ diff --git a/src/cpu/x86/vm/templateTabl
+ __ push(rbx); // return value
+ __ mov(rcx, rdi);
+ __ jump_to_method_handle_entry(rcx, rdx);
- }
-
++}
++
//----------------------------------------------------------------------------------------------------
+ // Allocation
+
diff --git a/src/cpu/x86/vm/templateTable_x86_32.hpp b/src/cpu/x86/vm/templateTable_x86_32.hpp
--- a/src/cpu/x86/vm/templateTable_x86_32.hpp
+++ b/src/cpu/x86/vm/templateTable_x86_32.hpp
@@ -949,21 +955,21 @@ diff --git a/src/cpu/x86/vm/templateTabl
const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
const bool is_invokespecial = code == Bytecodes::_invokespecial;
const bool load_receiver = code != Bytecodes::_invokestatic;
-@@ -2847,6 +2864,9 @@
- const Register recv = rcx;
+@@ -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 @@
__ movl(recv, flags);
__ andl(recv, 0xFF);
if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
-- __ movq(recv, Address(rsp, recv, Address::times_8,
+- __ 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,
@@ -984,7 +990,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
- ExternalAddress return_5((address)Interpreter::return_5_addrs_by_index_table());
- ExternalAddress return_3((address)Interpreter::return_3_addrs_by_index_table());
- __ lea(rscratch1, (is_invokeinterface ? return_5 : return_3));
-- __ movq(flags, Address(rscratch1, flags, Address::times_8));
+- __ movptr(flags, Address(rscratch1, flags, Address::times_8));
+ address table_addr =
+ (is_invdyn_bootstrap)
+ ? (address)Interpreter::return_5_unbox_addrs_by_index_table()
@@ -1033,19 +1039,21 @@ diff --git a/src/cpu/x86/vm/templateTabl
// rax: Interface
// rbx: index
-@@ -3150,6 +3180,79 @@
- // rcx: receiver
- // rbx: methodOop
- __ jump_from_interpreted(rbx, rdx);
-+}
-+
+@@ -3058,6 +3088,83 @@
+ return;
+ }
+
+void TemplateTable::invokedynamic(int byte_no) {
+ transition(vtos, vtos);
+
-+ if (!InvokeDynamic) {
-+ // We do not encounter this bytecode if !InvokeDynamic.
-+ // See Rewriter::rewrite_invokedynamic.
-+ __ stop("invokedynamic not enabled");
++ 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;
+ }
+
@@ -1072,7 +1080,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
+ }
+
+ Label handle_unlinked_site;
-+ __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_impl_DynCallSite::target_offset_in_bytes, rcx)));
++ __ movptr(rcx, Address(rax, __ delayed_value(impl_java_dyn_CallSiteImpl::target_offset_in_bytes, rcx)));
+ __ testptr(rcx, rcx);
+ __ jcc(Assembler::zero, handle_unlinked_site);
+
@@ -1110,9 +1118,11 @@ diff --git a/src/cpu/x86/vm/templateTabl
+ __ 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
@@ -1129,22 +1139,22 @@ diff --git a/src/share/vm/c1/c1_GraphBui
diff --git a/src/share/vm/c1/c1_GraphBuilder.cpp b/src/share/vm/c1/c1_GraphBuilder.cpp
--- a/src/share/vm/c1/c1_GraphBuilder.cpp
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp
-@@ -1541,6 +1541,14 @@
- if (target->is_loaded() && !target->is_abstract() &&
- target->can_be_statically_bound() && code == Bytecodes::_invokevirtual) {
+@@ -1524,6 +1524,14 @@
code = Bytecodes::_invokespecial;
-+ }
-+
-+ if (InvokeDynamic && target->is_method_handle_invoke()) {
+ }
+
++ if (EnableInvokeDynamic && target->is_method_handle_invoke()) {
+ if (target->holder()->name() == ciSymbol::java_dyn_Dynamic()) {
+ BAILOUT("invokedynamic NYI"); // FIXME
+ return;
+ }
+ // normal method handle invokes should work fine
- }
-
++ }
++
// NEEDS_CLEANUP
-@@ -2455,7 +2463,6 @@
+ // I've added the target-is_loaded() test below but I don't really understand
+ // how klass->is_loaded() can be true and yet target->is_loaded() is false.
+@@ -2432,7 +2440,6 @@
case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokestatic : // fall through
case Bytecodes::_invokeinterface: invoke(code); break;
@@ -1155,44 +1165,16 @@ diff --git a/src/share/vm/ci/bcEscapeAna
diff --git a/src/share/vm/ci/bcEscapeAnalyzer.cpp b/src/share/vm/ci/bcEscapeAnalyzer.cpp
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp
-@@ -847,9 +847,6 @@
- state.lpush();
+@@ -848,9 +848,6 @@
}
}
-- break;
+ break;
- case Bytecodes::_xxxunusedxxx:
- ShouldNotReachHere();
- break;
+- break;
case Bytecodes::_new:
state.apush(allocated_obj);
-diff --git a/src/share/vm/ci/ciMethod.cpp b/src/share/vm/ci/ciMethod.cpp
---- a/src/share/vm/ci/ciMethod.cpp
-+++ b/src/share/vm/ci/ciMethod.cpp
-@@ -697,6 +697,13 @@
- return CURRENT_THREAD_ENV->get_object(mtype)->as_instance();
- }
-
-+ciMethod* ciMethod::extended_invoke_method() {
-+ check_is_loaded();
-+ VM_ENTRY_MARK;
-+ methodOop extinv = get_methodOop()->extended_invoke_method();
-+ return CURRENT_THREAD_ENV->get_object(extinv)->as_method();
-+}
-+
-
- // ------------------------------------------------------------------
- // ciMethod::build_method_data
-diff --git a/src/share/vm/ci/ciMethod.hpp b/src/share/vm/ci/ciMethod.hpp
---- a/src/share/vm/ci/ciMethod.hpp
-+++ b/src/share/vm/ci/ciMethod.hpp
-@@ -209,6 +209,7 @@
- int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
- bool is_method_handle_invoke();
- ciInstance* method_handle_type();
-+ ciMethod* extended_invoke_method();
-
- // What kind of ciObject is this?
- bool is_method() { return true; }
+ break;
diff --git a/src/share/vm/ci/ciStreams.cpp b/src/share/vm/ci/ciStreams.cpp
--- a/src/share/vm/ci/ciStreams.cpp
+++ b/src/share/vm/ci/ciStreams.cpp
@@ -1223,7 +1205,7 @@ diff --git a/src/share/vm/ci/ciStreams.h
Bytecodes::Code next_bc() { return Bytecodes::java_code((Bytecodes::Code)* _pc); }
// Return current ByteCode and increment PC to next bytecode, skipping all
-@@ -121,33 +123,38 @@
+@@ -121,34 +123,39 @@
return check_java(_bc);
}
@@ -1269,12 +1251,13 @@ diff --git a/src/share/vm/ci/ciStreams.h
// Get dimensions byte (multinewarray)
int get_dimensions() const { return *(unsigned char*)(_pc-1); }
--
+
- // Get unsigned index fast
- int get_index_fast() const { return Bytes::get_native_u2(_pc-2); }
-
+-
// Sign-extended index byte/short, no widening
int get_byte() const { return (int8_t)(_pc[-1]); }
+ int get_short() const { return (int16_t)Bytes::get_Java_u2(_pc-2); }
@@ -225,6 +232,22 @@
ciKlass* get_declared_method_holder();
int get_method_holder_index();
@@ -1301,86 +1284,74 @@ diff --git a/src/share/vm/classfile/java
diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp
--- a/src/share/vm/classfile/javaClasses.cpp
+++ b/src/share/vm/classfile/javaClasses.cpp
-@@ -2200,6 +2200,52 @@
- }
-
-
-+// Support for java_dyn_impl_DynCallSite
-+
-+int java_dyn_impl_DynCallSite::_type_offset;
-+int java_dyn_impl_DynCallSite::_target_offset;
-+int java_dyn_impl_DynCallSite::_vmref_offset;
-+int java_dyn_impl_DynCallSite::_vmdata_offset;
-+
-+void java_dyn_impl_DynCallSite::compute_offsets() {
-+ if (!InvokeDynamic) return;
-+ klassOop k = SystemDictionary::dyn_impl_DynCallSite_klass();
+@@ -2430,6 +2430,41 @@
+ }
+
+
++// Support for impl_java_dyn_CallSiteImpl
++
++int impl_java_dyn_CallSiteImpl::_type_offset;
++int impl_java_dyn_CallSiteImpl::_target_offset;
++int impl_java_dyn_CallSiteImpl::_vmmethod_offset;
++
++void impl_java_dyn_CallSiteImpl::compute_offsets() {
++ if (!EnableInvokeDynamic) return;
++ klassOop k = SystemDictionary::CallSiteImpl_klass();
+ if (k != NULL) {
+ compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true);
+ compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature(), true);
-+ compute_offset(_vmref_offset, k, vmSymbols::vmref_name(), vmSymbols::object_signature(), true);
-+ compute_offset(_vmdata_offset, k, vmSymbols::vmdata_name(), vmSymbols::long_signature(), true);
-+ if (_vmdata_offset != 0) _vmdata_offset += oopDesc::address_padding_in_bytes();
++ compute_offset(_vmmethod_offset, k, vmSymbols::vmmethod_name(), vmSymbols::object_signature(), true);
+ }
+}
+
-+oop java_dyn_impl_DynCallSite::type(oop site) {
++oop impl_java_dyn_CallSiteImpl::type(oop site) {
+ return site->obj_field(_type_offset);
+}
+
-+oop java_dyn_impl_DynCallSite::target(oop site) {
++oop impl_java_dyn_CallSiteImpl::target(oop site) {
+ return site->obj_field(_target_offset);
+}
+
-+void java_dyn_impl_DynCallSite::set_target(oop site, oop target) {
++void impl_java_dyn_CallSiteImpl::set_target(oop site, oop target) {
+ site->obj_field_put(_target_offset, target);
+}
+
-+oop java_dyn_impl_DynCallSite::vmref(oop site) {
-+ return site->obj_field(_vmref_offset);
++oop impl_java_dyn_CallSiteImpl::vmmethod(oop site) {
++ return site->obj_field(_vmmethod_offset);
+}
+
-+void java_dyn_impl_DynCallSite::set_vmref(oop site, oop ref) {
-+ site->obj_field_put(_vmref_offset, ref);
++void impl_java_dyn_CallSiteImpl::set_vmmethod(oop site, oop ref) {
++ site->obj_field_put(_vmmethod_offset, ref);
+}
-+
-+address java_dyn_impl_DynCallSite::vmdata(oop site) {
-+ return site->address_field(_vmdata_offset);
-+}
-+
-+void java_dyn_impl_DynCallSite::set_vmdata(oop site, address data) {
-+ site->address_field_put(_vmdata_offset, data);
-+}
// Support for java_security_AccessControlContext
-@@ -2540,6 +2586,9 @@
- if (MethodHandles) {
- java_dyn_MethodHandle::compute_offsets();
+@@ -2775,6 +2810,9 @@
java_dyn_MethodType::compute_offsets();
-+ }
-+ if (InvokeDynamic) {
-+ java_dyn_impl_DynCallSite::compute_offsets();
- }
+ java_dyn_MethodTypeForm::compute_offsets();
+ }
++ if (EnableInvokeDynamic) {
++ impl_java_dyn_CallSiteImpl::compute_offsets();
++ }
java_security_AccessControlContext::compute_offsets();
// Initialize reflection classes. The layouts of these classes
+ // changed with the new reflection implementation in JDK 1.4, and
diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp
--- a/src/share/vm/classfile/javaClasses.hpp
+++ b/src/share/vm/classfile/javaClasses.hpp
-@@ -872,6 +872,40 @@
+@@ -1053,6 +1053,33 @@
};
-+// Interface to java.dyn.impl.DynCallSite objects
-+
-+class java_dyn_impl_DynCallSite: AllStatic {
++// Interface to java.dyn.impl.CallSiteImpl objects
++
++class impl_java_dyn_CallSiteImpl: AllStatic {
+ friend class JavaClasses;
+
+private:
+ static int _type_offset;
+ static int _target_offset;
-+ static int _vmref_offset;
-+ static int _vmdata_offset;
++ static int _vmmethod_offset;
+
+ static void compute_offsets();
+
@@ -1391,34 +1362,28 @@ diff --git a/src/share/vm/classfile/java
+ static oop target(oop site);
+ static void set_target(oop site, oop target);
+
-+ static oop vmref(oop site);
-+ static void set_vmref(oop site, oop ref);
-+
-+ static address vmdata(oop site);
-+ static void set_vmdata(oop site, address data);
++ static oop vmmethod(oop site);
++ static void set_vmmethod(oop site, oop ref);
+
+ // Accessors for code generation:
+ static int target_offset_in_bytes() { return _target_offset; }
+ static int type_offset_in_bytes() { return _type_offset; }
-+ static int vmref_offset_in_bytes() { return _vmref_offset; }
-+ static int vmdata_offset_in_bytes() { return _vmdata_offset; }
++ static int vmmethod_offset_in_bytes() { return _vmmethod_offset; }
+};
-+
-+
+
+
// Interface to java.security.AccessControlContext objects
-
- class java_security_AccessControlContext: AllStatic {
diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp
--- a/src/share/vm/classfile/systemDictionary.cpp
+++ b/src/share/vm/classfile/systemDictionary.cpp
-@@ -1909,6 +1909,16 @@
+@@ -1951,6 +1951,16 @@
// Skip the rest of the method handle classes, if MethodHandle is not loaded.
scan = WKID(meth_group_end+1);
}
-+ WKID indy_group_start = WK_KLASS_ENUM_NAME(java_dyn_Linkage_klass);
-+ WKID indy_group_end = WK_KLASS_ENUM_NAME(java_dyn_Dynamic_klass);
++ WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
++ WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass);
+ initialize_wk_klasses_until(indy_group_start, scan, CHECK);
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ initialize_wk_klasses_through(indy_group_start, scan, CHECK);
+ }
+ if (_well_known_klasses[indy_group_start] == NULL) {
@@ -1428,101 +1393,38 @@ diff --git a/src/share/vm/classfile/syst
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
-@@ -2324,6 +2334,138 @@
- return Handle(THREAD, (oop) result.get_jobject());
- }
-
-+static symbolHandle prepend_argument_type(symbolHandle prepend,
-+ symbolHandle signature,
-+ TRAPS) {
-+ ResourceMark rm;
-+ char fixed_buf[512 DEBUG_ONLY(* 0 + 20)];
-+ int buf_len = prepend->utf8_length() + signature->utf8_length() + 1;
-+ char* buf = (buf_len <= (int) sizeof(fixed_buf)
-+ ? fixed_buf
-+ : NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, buf_len));
-+ assert(prepend->byte_at(0) != '(', "argument sig");
-+ assert(signature->byte_at(0) == '(', "method sig");
-+ int fillp = buf_len, len;
-+ buf[--fillp] = 0;
-+ fillp -= (len = signature->utf8_length());
-+ memcpy(&buf[fillp], signature->bytes(), len);
-+ assert((int) strlen(&buf[fillp]) == len, "");
-+ assert(buf[fillp] == '(', "skip this");
-+ fillp++; // kill the paren
-+ fillp -= (len = prepend->utf8_length());
-+ memcpy(&buf[fillp], prepend->bytes(), len);
-+ buf[--fillp] = '(';
-+ assert(fillp == 0, "dead reckoning");
-+ assert((int) strlen(buf) == buf_len - 1, "");
-+ return oopFactory::new_symbol_handle(buf, THREAD);
-+}
-+
-+methodOop SystemDictionary::find_invokedynamic_invoke(symbolHandle signature,
-+ Handle class_loader,
-+ Handle protection_domain,
-+ TRAPS) {
-+ if (!InvokeDynamic) return NULL;
-+
-+ methodOop mhinvoke_oop = find_method_handle_invoke(signature,
-+ class_loader,
-+ protection_domain,
-+ CHECK_NULL);
-+
-+ methodOop idm_oop = mhinvoke_oop->invokedynamic_method();
-+
-+ if (idm_oop != NULL) return idm_oop;
-+
-+ // First time through, so compute it up.
-+ methodHandle mhinvoke(THREAD, mhinvoke_oop); DEBUG_ONLY(mhinvoke_oop = NULL);
-+ KlassHandle dyn_klass = KlassHandles::java_dyn_Dynamic_klass();
-+ Handle mt(THREAD, mhinvoke->method_handle_type());
-+ methodHandle idm = methodOopDesc::make_invoke_method(dyn_klass, signature,
-+ mt, CHECK_NULL);
-+
-+ // Now link in a third method, which is the target type of the invoke:
-+ // MH.invoke(abc)d --> Dyn.invoke(abc)d --> MH.invoke(Object;abc)d
-+ symbolHandle extsig = prepend_argument_type(vmSymbolHandles::object_signature(), signature, CHECK_NULL);
-+ {
-+ methodOop extm = find_method_handle_invoke(extsig,
-+ class_loader, protection_domain,
-+ CHECK_NULL);
-+ idm->set_extended_invoke_method(extm);
-+ }
-+
-+ {
-+ MutexLocker ml(SystemDictionary_lock, Thread::current());
-+ if (mhinvoke->invokedynamic_method() != NULL)
-+ // another thread got here first; go with the winner:
-+ return mhinvoke->invokedynamic_method();
-+
-+ mhinvoke->set_invokedynamic_method(idm());
-+ return idm();
-+ }
-+}
-+
-+
+@@ -2367,6 +2377,76 @@
+ }
+
+
+// Ask Java code to find or construct a java.dyn.CallSite for the given
+// name and signature, as interpreted relative to the given class loader.
+Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller,
++ int caller_method_idnum,
++ int caller_bci,
+ symbolHandle name,
+ methodHandle mh_invdyn,
-+ jlong vmdata,
+ TRAPS) {
+ Handle empty;
-+ // call java.dyn.impl.DynCallSite::makeSite(caller, name, mtype, vmdata)
++ // call java.dyn.impl.CallSiteImpl::makeSite(caller, name, mtype, cmid, cbci)
+ oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle!
+ JavaCallArguments args(Handle(THREAD, caller->java_mirror()));
+ args.push_oop(name_str_oop);
+ args.push_oop(mh_invdyn->method_handle_type());
-+ args.push_long(vmdata);
++ args.push_int(caller_method_idnum);
++ args.push_int(caller_bci);
+ JavaValue result(T_OBJECT);
+ JavaCalls::call_static(&result,
-+ SystemDictionary::dyn_impl_DynCallSite_klass(),
++ SystemDictionary::CallSiteImpl_klass(),
+ vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(),
+ &args, CHECK_(empty));
+ oop call_site_oop = (oop) result.get_jobject();
-+ java_dyn_impl_DynCallSite::set_vmref(call_site_oop, mh_invdyn());
++ impl_java_dyn_CallSiteImpl::set_vmmethod(call_site_oop, mh_invdyn());
++ if (TraceMethodHandles) {
++ tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop);
++ call_site_oop->print();
++ tty->cr();
++ }
+ return call_site_oop;
+}
+
@@ -1546,7 +1448,7 @@ diff --git a/src/share/vm/classfile/syst
+ args.push_oop(search_bootstrap_klass->java_mirror());
+ JavaValue result(T_OBJECT);
+ JavaCalls::call_static(&result,
-+ SystemDictionary::java_dyn_Linkage_klass(),
++ SystemDictionary::Linkage_klass(),
+ vmSymbols::findBootstrapMethod_name(),
+ vmSymbols::findBootstrapMethod_signature(),
+ &args, CHECK_(empty));
@@ -1564,39 +1466,36 @@ diff --git a/src/share/vm/classfile/syst
+
+ return Handle(THREAD, boot_method_oop);
+}
-
++
// Since the identity hash code for symbols changes when the symbols are
// moved from the regular perm gen (hash in the mark word) to the shared
+ // spaces (hash is the address), the classes loaded into the dictionary
diff --git a/src/share/vm/classfile/systemDictionary.hpp b/src/share/vm/classfile/systemDictionary.hpp
--- a/src/share/vm/classfile/systemDictionary.hpp
+++ b/src/share/vm/classfile/systemDictionary.hpp
-@@ -141,6 +141,12 @@
- template(java_dyn_MethodType_klass, java_dyn_MethodType, Opt) \
- template(java_dyn_MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \
- template(java_dyn_WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
-+ template(java_dyn_Linkage_klass, java_dyn_Linkage, Opt) \
-+ template(java_dyn_CallSite_klass, java_dyn_CallSite, Opt) \
-+ template(dyn_impl_DynCallSite_klass, java_dyn_impl_DynCallSite, Opt) \
-+ template(java_dyn_Dynamic_klass, java_dyn_Dynamic, Opt) \
+@@ -142,6 +142,12 @@
+ template(MethodType_klass, java_dyn_MethodType, Opt) \
+ template(MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \
+ template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
++ template(Linkage_klass, java_dyn_Linkage, Opt) \
++ template(CallSite_klass, java_dyn_CallSite, Opt) \
++ template(CallSiteImpl_klass, impl_java_dyn_CallSiteImpl, Opt) \
++ template(Dynamic_klass, java_dyn_Dynamic, Opt) \
+ /* Note: MethodHandle must be first, and Dynamic last in group */ \
+ \
template(vector_klass, java_util_Vector, Pre) \
template(hashtable_klass, java_util_Hashtable, Pre) \
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
-@@ -469,6 +475,25 @@
+@@ -466,6 +472,21 @@
Handle class_loader,
Handle protection_domain,
TRAPS);
-+ // find the MH::invoke method for an invokedynamic instruction
-+ static methodOop find_invokedynamic_invoke(symbolHandle signature,
-+ Handle class_loader,
-+ Handle protection_domain,
-+ TRAPS);
+ // ask Java to create a dynamic call site, while linking an invokedynamic op
+ static Handle make_dynamic_call_site(KlassHandle caller,
++ int caller_method_idnum,
++ int caller_bci,
+ symbolHandle name,
+ methodHandle mh_invoke,
-+ jlong vmdata,
+ TRAPS);
+
+ // coordinate with Java about bootstrap methods
@@ -1609,18 +1508,92 @@ diff --git a/src/share/vm/classfile/syst
// Utility for printing loader "name" as part of tracing constraints
static const char* loader_name(oop loader) {
return ((loader) == NULL ? "<bootloader>" :
+diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp
+--- a/src/share/vm/classfile/verifier.cpp
++++ b/src/share/vm/classfile/verifier.cpp
+@@ -1174,6 +1174,7 @@
+ &this_uninit, return_type, cp, CHECK_VERIFY(this));
+ no_control_flow = false; break;
+ case Bytecodes::_invokeinterface :
++ case Bytecodes::_invokedynamic :
+ verify_invoke_instructions(
+ &bcs, code_length, &current_frame,
+ &this_uninit, return_type, cp, CHECK_VERIFY(this));
+@@ -1895,12 +1896,23 @@
+ Bytecodes::Code opcode = bcs->code();
+ unsigned int types = (opcode == Bytecodes::_invokeinterface
+ ? 1 << JVM_CONSTANT_InterfaceMethodref
++ : opcode == Bytecodes::_invokedynamic
++ ? 1 << JVM_CONSTANT_NameAndType
+ : 1 << JVM_CONSTANT_Methodref);
+ verify_cp_type(index, cp, types, CHECK_VERIFY(this));
+
+ // Get method name and signature
+- symbolHandle method_name(THREAD, cp->name_ref_at(index));
+- symbolHandle method_sig(THREAD, cp->signature_ref_at(index));
++ symbolHandle method_name;
++ symbolHandle method_sig;
++ if (opcode == Bytecodes::_invokedynamic) {
++ int name_index = cp->name_ref_index_at(index);
++ int sig_index = cp->signature_ref_index_at(index);
++ method_name = symbolHandle(THREAD, cp->symbol_at(name_index));
++ method_sig = symbolHandle(THREAD, cp->symbol_at(sig_index));
++ } else {
++ method_name = symbolHandle(THREAD, cp->name_ref_at(index));
++ method_sig = symbolHandle(THREAD, cp->signature_ref_at(index));
++ }
+
+ if (!SignatureVerifier::is_valid_method_signature(method_sig)) {
+ class_format_error(
+@@ -1910,8 +1922,17 @@
+ }
+
+ // Get referenced class type
+- VerificationType ref_class_type = cp_ref_index_to_type(
+- index, cp, CHECK_VERIFY(this));
++ VerificationType ref_class_type;
++ if (opcode == Bytecodes::_invokedynamic) {
++ if (!EnableInvokeDynamic) {
++ class_format_error(
++ "invokedynamic instructions not enabled on this JVM",
++ _klass->external_name());
++ return;
++ }
++ } else {
++ ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this));
++ }
+
+ // For a small signature length, we just allocate 128 bytes instead
+ // of parsing the signature once to find its size.
+@@ -1970,6 +1991,14 @@
+ }
+ }
+
++ if (opcode == Bytecodes::_invokedynamic) {
++ address bcp = bcs->bcp();
++ if (*(bcp+3) != 0 || *(bcp+4) != 0) {
++ verify_error(bci, "Third and fourth operand bytes of invokedynamic must be zero");
++ return;
++ }
++ }
++
+ if (method_name->byte_at(0) == '<') {
+ // Make sure <init> can only be invoked by invokespecial
+ if (opcode != Bytecodes::_invokespecial ||
+@@ -1994,7 +2023,8 @@
+ current_frame->pop_stack(sig_types[i], CHECK_VERIFY(this));
+ }
+ // Check objectref on operand stack
+- if (opcode != Bytecodes::_invokestatic) {
++ if (opcode != Bytecodes::_invokestatic &&
++ opcode != Bytecodes::_invokedynamic) {
+ if (method_name() == vmSymbols::object_initializer_name()) { // <init> method
+ verify_invoke_init(bcs, ref_class_type, current_frame,
+ code_length, this_uninit, cp, CHECK_VERIFY(this));
diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp
--- a/src/share/vm/classfile/vmSymbols.hpp
+++ b/src/share/vm/classfile/vmSymbols.hpp
-@@ -123,6 +123,7 @@
- template(tag_runtime_invisible_parameter_annotations,"RuntimeInvisibleParameterAnnotations") \
- template(tag_annotation_default, "AnnotationDefault") \
- template(tag_enclosing_method, "EnclosingMethod") \
-+ template(tag_bootstrap_invoke_dynamic, "BootstrapInvokeDynamic") \
- \
- /* exception klasses: at least all exceptions thrown by the VM have entries here */ \
- template(java_lang_ArithmeticException, "java/lang/ArithmeticException") \
-@@ -215,6 +216,9 @@
+@@ -215,6 +215,9 @@
template(base_name, "base") \
\
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
@@ -1629,29 +1602,37 @@ diff --git a/src/share/vm/classfile/vmSy
+ template(java_dyn_CallSite, "java/dyn/CallSite") \
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
template(java_dyn_MethodType, "java/dyn/MethodType") \
- template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \
-@@ -224,12 +228,17 @@
- template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \
- /* internal classes known only to the JVM: */ \
- template(java_dyn_impl_MTForm, "java/dyn/impl/MTForm") \
-+ template(java_dyn_impl_DynCallSite, "java/dyn/impl/DynCallSite") \
- template(java_dyn_impl_MH, "java/dyn/impl/MH") \
- template(java_dyn_impl_AMH, "java/dyn/impl/AMH") \
- template(java_dyn_impl_BMH, "java/dyn/impl/BMH") \
- template(java_dyn_impl_DMH, "java/dyn/impl/DMH") \
+ template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") \
+@@ -228,8 +231,13 @@
+ template(impl_java_dyn_AdapterMethodHandle, "impl/java/dyn/AdapterMethodHandle") \
+ template(impl_java_dyn_BoundMethodHandle, "impl/java/dyn/BoundMethodHandle") \
+ template(impl_java_dyn_DirectMethodHandle, "impl/java/dyn/DirectMethodHandle") \
++ template(impl_java_dyn_CallSiteImpl, "impl/java/dyn/CallSiteImpl") \
template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \
template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \
-+ template(makeSite_name, "makeSite") /*DynCallSite::makeImpl*/ \
-+ template(makeSite_signature, "(Ljava/lang/Class;Ljava/lang/String;Ljava/dyn/MethodType;J)Ljava/dyn/impl/DynCallSite;") \
++ template(makeSite_name, "makeSite") /*CallSiteImpl::makeImpl*/ \
++ template(makeSite_signature, "(Ljava/lang/Class;Ljava/lang/String;Ljava/dyn/MethodType;II)Limpl/java/dyn/CallSiteImpl;") \
+ template(findBootstrapMethod_name, "findBootstrapMethod") \
+ template(findBootstrapMethod_signature, "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/dyn/MethodHandle;") \
+ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
+ LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
\
- /* common method and field names */ \
- template(object_initializer_name, "<init>") \
+@@ -303,9 +311,11 @@
+ template(value_name, "value") \
+ template(frontCacheEnabled_name, "frontCacheEnabled") \
+ template(stringCacheEnabled_name, "stringCacheEnabled") \
++ template(target_name, "target") \
+ template(toString_name, "toString") \
+ template(values_name, "values") \
+ template(receiver_name, "receiver") \
++ template(vmmethod_name, "vmmethod") \
+ template(vmtarget_name, "vmtarget") \
+ template(vmentry_name, "vmentry") \
+ template(vmslots_name, "vmslots") \
diff --git a/src/share/vm/includeDB_core b/src/share/vm/includeDB_core
--- a/src/share/vm/includeDB_core
+++ b/src/share/vm/includeDB_core
-@@ -4088,6 +4088,7 @@
+@@ -4095,6 +4095,7 @@
templateTable_<arch_model>.cpp interpreterRuntime.hpp
templateTable_<arch_model>.cpp interpreter.hpp
templateTable_<arch_model>.cpp methodDataOop.hpp
@@ -1662,19 +1643,19 @@ diff --git a/src/share/vm/includeDB_gc_p
diff --git a/src/share/vm/includeDB_gc_parallel b/src/share/vm/includeDB_gc_parallel
--- a/src/share/vm/includeDB_gc_parallel
+++ b/src/share/vm/includeDB_gc_parallel
-@@ -41,6 +41,12 @@
- constantPoolKlass.cpp psPromotionManager.inline.hpp
+@@ -42,6 +42,12 @@
constantPoolKlass.cpp psScavenge.inline.hpp
constantPoolKlass.cpp parOopClosures.inline.hpp
-+
+
+cpCacheKlass.cpp cardTableRS.hpp
+cpCacheKlass.cpp oop.pcgc.inline.hpp
+cpCacheKlass.cpp psPromotionManager.inline.hpp
+cpCacheKlass.cpp psScavenge.inline.hpp
+cpCacheKlass.cpp parOopClosures.inline.hpp
-
++
genCollectedHeap.cpp concurrentMarkSweepThread.hpp
genCollectedHeap.cpp vmCMSOperations.hpp
+
diff --git a/src/share/vm/includeDB_jvmti b/src/share/vm/includeDB_jvmti
--- a/src/share/vm/includeDB_jvmti
+++ b/src/share/vm/includeDB_jvmti
@@ -2126,7 +2107,7 @@ diff --git a/src/share/vm/interpreter/by
_invokestatic = 184, // 0xb8
_invokeinterface = 185, // 0xb9
- _xxxunusedxxx = 186, // 0xba
-+ _invokedynamic = 186, // 0xba // if InvokeDynamic
++ _invokedynamic = 186, // 0xba // if EnableInvokeDynamic
_new = 187, // 0xbb
_newarray = 188, // 0xbc
_anewarray = 189, // 0xbd
@@ -2147,17 +2128,16 @@ diff --git a/src/share/vm/interpreter/in
diff --git a/src/share/vm/interpreter/interpreterRuntime.cpp b/src/share/vm/interpreter/interpreterRuntime.cpp
--- a/src/share/vm/interpreter/interpreterRuntime.cpp
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp
-@@ -684,6 +684,131 @@
- info.vtable_index());
- }
+@@ -681,6 +681,131 @@
IRT_END
-+
-+
-+// First time execution: Resolve symbols, create a permanent DynCallSite object.
+
+
++// First time execution: Resolve symbols, create a permanent CallSiteImpl object.
+IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
+ ResourceMark rm(thread);
+
-+ assert(InvokeDynamic, "");
++ assert(EnableInvokeDynamic, "");
++
+ const Bytecodes::Code bytecode = Bytecodes::_invokedynamic;
+
+ methodHandle caller_method(thread, method(thread));
@@ -2167,9 +2147,12 @@ diff --git a/src/share/vm/interpreter/in
+ KlassHandle caller_klass(thread, caller_method->method_holder());
+ Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, KlassHandle(), CHECK);
+ if (bootm.is_null()) {
-+ // if there is no bootstrap method, the Dynamic call was really
-+ // an old-fashioned invokeinterface, so we must throw an ICCE
-+ THROW(vmSymbols::java_lang_IncompatibleClassChangeError());
++ // If there is no bootstrap method, throw IncompatibleClassChangeError.
++ // This is a valid generic error type for resolution (JLS 12.3.3).
++ char buf[200];
++ jio_snprintf(buf, sizeof(buf), "Class %s has not declared a bootstrap method for invokedynamic",
++ (Klass::cast(caller_klass()))->external_name());
++ THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
+ }
+ }
+
@@ -2182,8 +2165,8 @@ diff --git a/src/share/vm/interpreter/in
+ // there are two CPC entries that are of interest:
+ int site_index = constantPoolCacheOopDesc::decode_secondary_index(raw_index);
+ int main_index = pool->cache()->entry_at(site_index)->main_entry_index();
-+ // here is the CP index of the call site linkage info:
-+ int call_index = pool->cache()->entry_at(main_index)->constant_pool_index();
++ // and there is one CP entry, a NameAndType:
++ int nt_index = pool->map_instruction_operand_to_index(raw_index);
+
+ // first resolve the signature to a MH.invoke methodOop
+ if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) {
@@ -2191,36 +2174,32 @@ diff --git a/src/share/vm/interpreter/in
+ CallInfo info;
+ LinkResolver::resolve_invoke(info, Handle(), pool,
+ raw_index, bytecode, CHECK);
++ // The main entry corresponds to a JVM_CONSTANT_NameAndType, and serves
++ // as a common reference point for all invokedynamic call sites with
++ // that exact call descriptor. We will link it in the CP cache exactly
++ // as if it were an invokevirtual of MethodHandle.invoke.
+ pool->cache()->entry_at(main_index)->set_method(
+ bytecode,
+ info.resolved_method(),
+ info.vtable_index());
++ assert(pool->cache()->entry_at(main_index)->is_vfinal(), "f2 must be a methodOop");
+ }
+
+ // The method (f2 entry) of the main entry is the MH.invoke for the
-+ // invokedynamic target call signature. The extended invoke method
-+ // has the explicit signature plus a prepended Object argument
-+ // to represent the "Dynamic" receiver.
++ // invokedynamic target call signature.
+ intptr_t f2_value = pool->cache()->entry_at(main_index)->f2();
+ methodHandle mh_invdyn(THREAD, (methodOop) f2_value);
+ assert(mh_invdyn.not_null() && mh_invdyn->is_method() && mh_invdyn->is_method_handle_invoke(),
+ "correct result from LinkResolver::resolve_invokedynamic");
+
-+ // Find out more information about the call site.
-+ jlong vmdata = 0;
-+ {
-+ int method_idnum = caller_method->method_idnum();
-+ int bci = caller_method->bci_from(bcp(thread));
-+ vmdata = jlong_from(method_idnum, bci);
-+ }
-+
-+ methodHandle mh_extinv(THREAD, mh_invdyn->extended_invoke_method());
-+ assert(mh_extinv.not_null(), "");
-+
++ symbolHandle call_site_name(THREAD, pool->nt_name_ref_at(nt_index));
+ Handle call_site
+ = SystemDictionary::make_dynamic_call_site(caller_method->method_holder(),
-+ pool->uncached_name_ref_at(call_index),
-+ mh_extinv, vmdata, CHECK);
++ caller_method->method_idnum(),
++ caller_method->bci_from(bcp(thread)),
++ call_site_name,
++ mh_invdyn,
++ CHECK);
+ pool->cache()->entry_at(site_index)->set_dynamic_call(call_site(), 0);
+}
+IRT_END
@@ -2229,7 +2208,7 @@ diff --git a/src/share/vm/interpreter/in
+// Called on first time execution, and also whenever the CallSite.target is null.
+// FIXME: Do more of this in Java code.
+IRT_ENTRY(void, InterpreterRuntime::bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site)) {
-+ methodHandle mh_invdyn(thread, (methodOop) java_dyn_impl_DynCallSite::vmref(call_site));
++ methodHandle mh_invdyn(thread, (methodOop) impl_java_dyn_CallSiteImpl::vmmethod(call_site));
+ Handle mh_type(thread, mh_invdyn->method_handle_type());
+ objArrayHandle mh_ptypes(thread, java_dyn_MethodType::ptypes(mh_type()));
+
@@ -2276,9 +2255,11 @@ diff --git a/src/share/vm/interpreter/in
+}
+IRT_END
+
-
-
++
++
//------------------------------------------------------------------------------------------------------------------------
+ // Miscellaneous
+
diff --git a/src/share/vm/interpreter/interpreterRuntime.hpp b/src/share/vm/interpreter/interpreterRuntime.hpp
--- a/src/share/vm/interpreter/interpreterRuntime.hpp
+++ b/src/share/vm/interpreter/interpreterRuntime.hpp
@@ -2309,50 +2290,7 @@ diff --git a/src/share/vm/interpreter/li
diff --git a/src/share/vm/interpreter/linkResolver.cpp b/src/share/vm/interpreter/linkResolver.cpp
--- a/src/share/vm/interpreter/linkResolver.cpp
+++ b/src/share/vm/interpreter/linkResolver.cpp
-@@ -160,6 +160,19 @@
- CHECK);
- if (result_oop != NULL) {
- assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature(), "consistent");
-+ result = methodHandle(THREAD, result_oop);
-+ }
-+ }
-+ if (InvokeDynamic &&
-+ klass() == SystemDictionary::java_dyn_Dynamic_klass()) {
-+ // same as find_method_handle_invoke, except the receiver
-+ // is explicitly prepended as an Object argument
-+ methodOop result_oop = SystemDictionary::find_invokedynamic_invoke(signature,
-+ Handle(),
-+ Handle(),
-+ CHECK);
-+ if (result_oop != NULL) {
-+ assert(result_oop->is_method_handle_invoke(), "consistent");
- result = methodHandle(THREAD, result_oop);
- }
- }
-@@ -334,6 +347,11 @@
-
- // lookup method in this interface or its super, java.lang.Object
- lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK);
-+
-+ if (resolved_method.is_null()) {
-+ // JSR 292: see if this is an implicitly generated method Dynamic.*(*...)
-+ lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK);
-+ }
-
- if (resolved_method.is_null()) {
- // lookup method in all the super-interfaces
-@@ -765,6 +783,10 @@
- bool check_access, bool check_null_and_abstract, TRAPS) {
- methodHandle resolved_method;
- linktime_resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK);
-+ if (InvokeDynamic && resolved_method->is_method_handle_invoke()) {
-+ result.set_static(resolved_klass, resolved_method, CHECK);
-+ return; // do not perform runtime checks on implicit method
-+ }
- runtime_resolve_interface_method(result, resolved_method, resolved_klass, recv, recv_klass, check_null_and_abstract, CHECK);
- }
-
-@@ -947,6 +969,7 @@
+@@ -947,6 +947,7 @@
case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break;
case Bytecodes::_invokespecial : resolve_invokespecial (result, pool, index, CHECK); break;
case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break;
@@ -2360,20 +2298,32 @@ diff --git a/src/share/vm/interpreter/li
case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break;
}
return;
-@@ -1008,6 +1031,18 @@
+@@ -1008,6 +1009,30 @@
resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
}
+
-+void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
-+ assert(constantPoolCacheOopDesc::is_secondary_index(index), "must be secondary index");
-+ KlassHandle resolved_klass;
-+ symbolHandle method_name;
-+ symbolHandle method_signature;
-+ KlassHandle current_klass;
-+ resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK);
-+ assert(resolved_klass() == SystemDictionary::java_dyn_Dynamic_klass(), "else can't get here");
-+ resolve_interface_call(result, Handle(), KlassHandle(), resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
++void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int raw_index, TRAPS) {
++ assert(EnableInvokeDynamic, "");
++
++ // This guy is reached from InterpreterRuntime::resolve_invokedynamic.
++
++ assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "must be secondary index");
++ int nt_index = pool->map_instruction_operand_to_index(raw_index);
++
++ // At this point, we only need the signature, and can ignore the name.
++ symbolHandle method_signature(THREAD, pool->nt_signature_ref_at(nt_index));
++ symbolHandle method_name = vmSymbolHandles::invoke_name();
++ KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
++
++ // JSR 292: this must be an implicitly generated method MethodHandle.invoke(*...)
++ // The extra MH receiver will be inserted into the stack on every call.
++ methodHandle resolved_method;
++ lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK);
++ if (resolved_method.is_null()) {
++ THROW(vmSymbols::java_lang_InternalError());
++ }
++ result.set_virtual(resolved_klass, KlassHandle(), resolved_method, resolved_method, resolved_method->vtable_index(), CHECK);
+}
+
//------------------------------------------------------------------------------------------------------------------------
@@ -2393,7 +2343,7 @@ diff --git a/src/share/vm/interpreter/re
diff --git a/src/share/vm/interpreter/rewriter.cpp b/src/share/vm/interpreter/rewriter.cpp
--- a/src/share/vm/interpreter/rewriter.cpp
+++ b/src/share/vm/interpreter/rewriter.cpp
-@@ -25,34 +25,57 @@
+@@ -25,39 +25,50 @@
# include "incls/_precompiled.incl"
# include "incls/_rewriter.cpp.incl"
@@ -2417,17 +2367,6 @@ diff --git a/src/share/vm/interpreter/re
+ int tag = _pool->tag_at(i).value();
+ switch (tag) {
+ case JVM_CONSTANT_InterfaceMethodref:
-+ if (InvokeDynamic) {
-+ int k_index = _pool->klass_ref_index_at(i);
-+ symbolOop k_name = _pool->klass_name_at(k_index);
-+ if (k_name == vmSymbols::java_dyn_Dynamic()) {
-+ // all calls of the form Dynamic.*(...)
-+ add_cp_cache_entry(i, true);
-+ // more cpc entries added later, one per call site
-+ break;
-+ }
-+ }
-+ // else fall through...
case JVM_CONSTANT_Fieldref : // fall through
case JVM_CONSTANT_Methodref : // fall through
- case JVM_CONSTANT_InterfaceMethodref: {
@@ -2445,11 +2384,6 @@ diff --git a/src/share/vm/interpreter/re
-// Creates a constant pool cache given an inverse_index_map
--constantPoolCacheHandle Rewriter::new_constant_pool_cache(intArray& inverse_index_map, TRAPS) {
-- const int length = inverse_index_map.length();
-- constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, CHECK_(constantPoolCacheHandle()));
-- cache->initialize(inverse_index_map);
-- return constantPoolCacheHandle(THREAD, cache);
+int Rewriter::add_extra_cp_cache_entry(int main_entry) {
+ // Hack: We put it on the map as an encoded value.
+ // The only place that consumes this is ConstantPoolCacheEntry::set_initial_state
@@ -2461,16 +2395,27 @@ diff --git a/src/share/vm/interpreter/re
+
+
+// Creates a constant pool cache given a CPC map
+ // This creates the constant pool cache initially in a state
+ // that is unsafe for concurrent GC processing but sets it to
+ // a safe mode before the constant pool cache is returned.
+-constantPoolCacheHandle Rewriter::new_constant_pool_cache(intArray& inverse_index_map, TRAPS) {
+- const int length = inverse_index_map.length();
+- constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length,
+- methodOopDesc::IsUnsafeConc,
+- CHECK_(constantPoolCacheHandle()));
+- cache->initialize(inverse_index_map);
+- return constantPoolCacheHandle(THREAD, cache);
+void Rewriter::make_constant_pool_cache(TRAPS) {
+ const int length = _cp_cache_map.length();
-+ constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, CHECK);
++ constantPoolCacheOop cache =
++ oopFactory::new_constantPoolCache(length, methodOopDesc::IsUnsafeConc, CHECK);
+ cache->initialize(_cp_cache_map);
+ _pool->set_cache(cache);
+ cache->set_constant_pool(_pool());
}
-@@ -96,8 +119,40 @@
+@@ -101,8 +112,38 @@
}
@@ -2484,14 +2429,12 @@ diff --git a/src/share/vm/interpreter/re
+}
+
+
-+void Rewriter::rewrite_invokedynamic(address bcp, int offset, int cp_index) {
++void Rewriter::rewrite_invokedynamic(address bcp, int offset, int delete_me) {
+ address p = bcp + offset;
-+ assert(InvokeDynamic, "");
-+ assert(p[-1] == Bytecodes::_invokeinterface, "");
-+ p[-1] = Bytecodes::_invokedynamic;
-+ int cpc = cp_entry_to_cp_cache(cp_index);
++ assert(p[-1] == Bytecodes::_invokedynamic, "");
++ int cp_index = Bytes::get_Java_u2(p);
++ int cpc = maybe_add_cp_cache_entry(cp_index); // add lazily
+ int cpc2 = add_extra_cp_cache_entry(cpc);
-+ assert(Bytes::get_native_u2(p) == cpc, "already patched");
+
+ // Replace the trailing four bytes with a CPC index for the dynamic
+ // call site. Unlike other CPC entries, there is one per bytecode,
@@ -2512,7 +2455,7 @@ diff --git a/src/share/vm/interpreter/re
int nof_jsrs = 0;
bool has_monitor_bytecodes = false;
-@@ -114,8 +169,10 @@
+@@ -119,8 +160,10 @@
const int code_length = method->code_size();
int bc_length;
@@ -2523,7 +2466,7 @@ diff --git a/src/share/vm/interpreter/re
c = (Bytecodes::Code)(*bcp);
// Since we have the code, see if we can get the length
-@@ -130,6 +187,7 @@
+@@ -135,6 +178,7 @@
// by 'wide'. We don't currently examine any of the bytecodes
// modified by wide, but in case we do in the future...
if (c == Bytecodes::_wide) {
@@ -2531,34 +2474,26 @@ diff --git a/src/share/vm/interpreter/re
c = (Bytecodes::Code)bcp[1];
}
}
-@@ -152,14 +210,20 @@
- case Bytecodes::_putstatic : // fall through
- case Bytecodes::_getfield : // fall through
+@@ -159,12 +203,13 @@
case Bytecodes::_putfield : // fall through
-+ case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokevirtual : // fall through
-- case Bytecodes::_invokespecial : // fall through
+ case Bytecodes::_invokespecial : // fall through
- case Bytecodes::_invokestatic : // fall through
- case Bytecodes::_invokeinterface: {
- address p = bcp + 1;
- Bytes::put_native_u2(p, index_map[Bytes::get_Java_u2(p)]);
+ case Bytecodes::_invokestatic :
++ case Bytecodes::_invokeinterface:
+ rewrite_member_reference(bcp, prefix_length+1);
-+ // Note: cp_entry_is_extended() may be true for invokespecial.
-+ // The interpreter must watch for this corner case,
-+ // and support it as usual.
break;
- }
-+
-+ case Bytecodes::_invokeinterface:
-+ cp_index = rewrite_member_reference(bcp, prefix_length+1);
-+ if (cp_entry_is_extended(cp_index))
-+ rewrite_invokedynamic(bcp, prefix_length+1, cp_index);
++ case Bytecodes::_invokedynamic:
++ rewrite_invokedynamic(bcp, prefix_length+1, int(sizeof"@@@@DELETE ME"));
+ break;
case Bytecodes::_jsr : // fall through
case Bytecodes::_jsr_w : nof_jsrs++; break;
case Bytecodes::_monitorenter : // fall through
-@@ -177,53 +241,56 @@
+@@ -182,53 +227,56 @@
// have to be rewritten, so we run the oopMapGenerator on the method
if (nof_jsrs > 0) {
method->set_has_jsrs();
@@ -2648,7 +2583,7 @@ diff --git a/src/share/vm/interpreter/re
if (method->intrinsic_id() == vmIntrinsics::_Object_init) {
// rewrite the return bytecodes of Object.<init> to register the
// object for finalization if needed.
-@@ -234,13 +301,27 @@
+@@ -239,13 +287,27 @@
}
}
@@ -2708,14 +2643,14 @@ diff --git a/src/share/vm/interpreter/re
+ // calls to grow().
+ _cp_cache_map.initialize(length / 2);
+ }
-+ int cp_entry_to_cp_cache(int i) { return _cp_map[i] >> 1; }
-+ bool cp_entry_is_extended(int i) { return (_cp_map[i] & 1) != 0; }
-+ int add_cp_cache_entry(int cp_index, bool is_extended = false) {
++ int cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; }
++ bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; }
++ int maybe_add_cp_cache_entry(int i) { return has_cp_cache(i) ? _cp_map[i] : add_cp_cache_entry(i); }
++ int add_cp_cache_entry(int cp_index) {
+ assert(_cp_map[cp_index] == -1, "not twice on same cp_index");
+ int cache_index = _cp_cache_map.append(cp_index);
-+ _cp_map.at_put(cp_index, (cache_index << 1) | (is_extended ? 1 : 0));
++ _cp_map.at_put(cp_index, cache_index);
+ assert(cp_entry_to_cp_cache(cp_index) == cache_index, "");
-+ assert(cp_entry_is_extended(cp_index) == is_extended, "");
+ return cache_index;
+ }
+ int add_extra_cp_cache_entry(int main_entry);
@@ -2757,7 +2692,7 @@ diff --git a/src/share/vm/interpreter/te
}
}
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ CodeletMark cm(_masm, "unboxing return entry points");
+ Interpreter::_return_unbox_entry =
+ EntryPoint(
@@ -2785,20 +2720,17 @@ diff --git a/src/share/vm/interpreter/te
+ int index = Interpreter::TosState_as_index(states[j]);
+ Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3);
+ Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5);
-+ if (InvokeDynamic)
++ if (EnableInvokeDynamic)
+ Interpreter::_return_5_unbox_addrs_by_index[index] = Interpreter::return_unbox_entry(states[j], 5);
}
{ CodeletMark cm(_masm, "continuation entry points");
-@@ -523,6 +544,18 @@
- address TemplateInterpreter::return_entry(TosState state, int length) {
- guarantee(0 <= length && length < Interpreter::number_of_return_entries, "illegal length");
- return _return_entry[length].entry(state);
-+}
-+
-+
+@@ -526,6 +547,18 @@
+ }
+
+
+address TemplateInterpreter::return_unbox_entry(TosState state, int length) {
-+ assert(InvokeDynamic, "");
++ assert(EnableInvokeDynamic, "");
+ if (state == vtos) {
+ // no unboxing to do, actually
+ return return_entry(state, length);
@@ -2806,9 +2738,12 @@ diff --git a/src/share/vm/interpreter/te
+ assert(length == 5, "unboxing entries generated for invokedynamic only");
+ return _return_unbox_entry.entry(state);
+ }
- }
-
-
++}
++
++
+ address TemplateInterpreter::deopt_entry(TosState state, int length) {
+ guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length");
+ return _deopt_entry[length].entry(state);
diff --git a/src/share/vm/interpreter/templateInterpreter.hpp b/src/share/vm/interpreter/templateInterpreter.hpp
--- a/src/share/vm/interpreter/templateInterpreter.hpp
+++ b/src/share/vm/interpreter/templateInterpreter.hpp
@@ -2840,7 +2775,7 @@ diff --git a/src/share/vm/interpreter/te
static DispatchTable _active_table; // the active dispatch table (used by the interpreter for dispatch)
static DispatchTable _normal_table; // the normal dispatch table (used to set the active table in normal mode)
-@@ -156,10 +158,12 @@
+@@ -158,10 +160,12 @@
// Support for invokes
static address* return_3_addrs_by_index_table() { return _return_3_addrs_by_index; }
static address* return_5_addrs_by_index_table() { return _return_5_addrs_by_index; }
@@ -2894,7 +2829,7 @@ diff --git a/src/share/vm/oops/constantP
diff --git a/src/share/vm/oops/constantPoolKlass.cpp b/src/share/vm/oops/constantPoolKlass.cpp
--- a/src/share/vm/oops/constantPoolKlass.cpp
+++ b/src/share/vm/oops/constantPoolKlass.cpp
-@@ -304,6 +304,7 @@
+@@ -312,6 +312,7 @@
if (cp->flags() != 0) {
st->print(" - flags : 0x%x", cp->flags());
if (cp->has_pseudo_string()) st->print(" has_pseudo_string");
@@ -2905,29 +2840,114 @@ diff --git a/src/share/vm/oops/constantP
diff --git a/src/share/vm/oops/constantPoolOop.cpp b/src/share/vm/oops/constantPoolOop.cpp
--- a/src/share/vm/oops/constantPoolOop.cpp
+++ b/src/share/vm/oops/constantPoolOop.cpp
-@@ -272,6 +272,18 @@
- int constantPoolOopDesc::uncached_klass_ref_index_at(int which) {
- jint ref_index = field_or_method_at(which, true);
+@@ -249,32 +249,41 @@
+ }
+
+
+-symbolOop constantPoolOopDesc::uncached_name_ref_at(int which) {
+- jint ref_index = name_and_type_at(uncached_name_and_type_ref_index_at(which));
+- int name_index = extract_low_short_from_int(ref_index);
++symbolOop constantPoolOopDesc::impl_name_ref_at(int which, bool uncached) {
++ int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
+ return symbol_at(name_index);
+ }
+
+
+-symbolOop constantPoolOopDesc::uncached_signature_ref_at(int which) {
+- jint ref_index = name_and_type_at(uncached_name_and_type_ref_index_at(which));
+- int signature_index = extract_high_short_from_int(ref_index);
++symbolOop constantPoolOopDesc::impl_signature_ref_at(int which, bool uncached) {
++ int signature_index = signature_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
+ return symbol_at(signature_index);
+ }
+
+
+-int constantPoolOopDesc::uncached_name_and_type_ref_index_at(int which) {
+- jint ref_index = field_or_method_at(which, true);
++int constantPoolOopDesc::impl_name_and_type_ref_index_at(int which, bool uncached) {
++ jint ref_index = field_or_method_at(which, uncached);
+ return extract_high_short_from_int(ref_index);
+ }
+
+
+-int constantPoolOopDesc::uncached_klass_ref_index_at(int which) {
+- jint ref_index = field_or_method_at(which, true);
++int constantPoolOopDesc::impl_klass_ref_index_at(int which, bool uncached) {
++ jint ref_index = field_or_method_at(which, uncached);
return extract_low_short_from_int(ref_index);
-+}
-+
-+
+ }
+
+
+
+int constantPoolOopDesc::map_instruction_operand_to_index(int operand) {
+ if (constantPoolCacheOopDesc::is_secondary_index(operand)) {
-+ assert(InvokeDynamic, "rewriter only produces four-byte indexes for invokedynamic");
+ return cache()->main_entry_at(operand)->constant_pool_index();
+ }
+ assert((int)(u2)operand == operand, "clean u2");
+ int index = Bytes::swap_u2(operand);
+ return cache()->entry_at(index)->constant_pool_index();
- }
-
-
++}
++
++
+ void constantPoolOopDesc::verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle k, TRAPS) {
+ if (k->oop_is_instance() || k->oop_is_objArray()) {
+ instanceKlassHandle holder (THREAD, this_oop->pool_holder());
+@@ -290,26 +299,14 @@
+ }
+
+
+-int constantPoolOopDesc::klass_ref_index_at(int which) {
+- jint ref_index = field_or_method_at(which, false);
++int constantPoolOopDesc::name_ref_index_at(int which_nt) {
++ jint ref_index = name_and_type_at(which_nt);
+ return extract_low_short_from_int(ref_index);
+ }
+
+
+-int constantPoolOopDesc::name_and_type_ref_index_at(int which) {
+- jint ref_index = field_or_method_at(which, false);
+- return extract_high_short_from_int(ref_index);
+-}
+-
+-
+-int constantPoolOopDesc::name_ref_index_at(int which) {
+- jint ref_index = name_and_type_at(which);
+- return extract_low_short_from_int(ref_index);
+-}
+-
+-
+-int constantPoolOopDesc::signature_ref_index_at(int which) {
+- jint ref_index = name_and_type_at(which);
++int constantPoolOopDesc::signature_ref_index_at(int which_nt) {
++ jint ref_index = name_and_type_at(which_nt);
+ return extract_high_short_from_int(ref_index);
+ }
+
+@@ -353,20 +350,6 @@
+ }
+
+
+-symbolOop constantPoolOopDesc::name_ref_at(int which) {
+- jint ref_index = name_and_type_at(name_and_type_ref_index_at(which));
+- int name_index = extract_low_short_from_int(ref_index);
+- return symbol_at(name_index);
+-}
+-
+-
+-symbolOop constantPoolOopDesc::signature_ref_at(int which) {
+- jint ref_index = name_and_type_at(name_and_type_ref_index_at(which));
+- int signature_index = extract_high_short_from_int(ref_index);
+- return symbol_at(signature_index);
+-}
+-
+-
+ BasicType constantPoolOopDesc::basic_type_for_signature_at(int which) {
+ return FieldType::basic_type(symbol_at(which));
+ }
diff --git a/src/share/vm/oops/constantPoolOop.hpp b/src/share/vm/oops/constantPoolOop.hpp
--- a/src/share/vm/oops/constantPoolOop.hpp
+++ b/src/share/vm/oops/constantPoolOop.hpp
-@@ -51,6 +51,7 @@
+@@ -53,6 +53,7 @@
void release_tag_at_put(int which, jbyte t) { tags()->release_byte_at_put(which, t); }
enum FlagBit {
@@ -2935,7 +2955,7 @@ diff --git a/src/share/vm/oops/constantP
FB_has_pseudo_string = 2
};
-@@ -94,7 +95,9 @@
+@@ -96,7 +97,9 @@
typeArrayOop tags() const { return _tags; }
bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); }
@@ -2945,7 +2965,60 @@ diff --git a/src/share/vm/oops/constantP
// Klass holding pool
klassOop pool_holder() const { return _pool_holder; }
-@@ -408,16 +411,16 @@
+@@ -343,19 +346,22 @@
+ // name_ref_index_at, signature_ref_index_at) all expect constant pool indices
+ // from the bytecodes to be passed in, which are actually potentially byte-swapped
+ // contstant pool cache indices. See field_or_method_at.
++ int map_instruction_operand_to_index(int operand);
+
+ // Lookup for entries consisting of (klass_index, name_and_type index)
+ klassOop klass_ref_at(int which, TRAPS);
+ symbolOop klass_ref_at_noresolve(int which);
+- symbolOop name_ref_at(int which);
+- symbolOop signature_ref_at(int which); // the type descriptor
++ symbolOop name_ref_at(int which) { return impl_name_ref_at(which, false); }
++ symbolOop signature_ref_at(int which) { return impl_signature_ref_at(which, false); }
+
+- int klass_ref_index_at(int which);
+- int name_and_type_ref_index_at(int which);
++ int klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, false); }
++ int name_and_type_ref_index_at(int which) { return impl_name_and_type_ref_index_at(which, false); }
+
+ // Lookup for entries consisting of (name_index, signature_index)
+- int name_ref_index_at(int which);
+- int signature_ref_index_at(int which);
++ int name_ref_index_at(int which_nt);
++ int signature_ref_index_at(int which_nt);
++ symbolOop nt_name_ref_at(int which_nt) { return symbol_at(name_ref_index_at(which_nt)); }
++ symbolOop nt_signature_ref_at(int which_nt) { return symbol_at(signature_ref_index_at(which_nt)); }
+
+ BasicType basic_type_for_signature_at(int which);
+
+@@ -397,10 +403,10 @@
+ // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
+ // future by other Java code. These take constant pool indices rather than possibly-byte-swapped
+ // constant pool cache indices as do the peer methods above.
+- symbolOop uncached_name_ref_at(int which);
+- symbolOop uncached_signature_ref_at(int which);
+- int uncached_klass_ref_index_at(int which);
+- int uncached_name_and_type_ref_index_at(int which);
++ symbolOop uncached_name_ref_at(int which) { return impl_name_ref_at(which, true); }
++ symbolOop uncached_signature_ref_at(int which) { return impl_signature_ref_at(which, true); }
++ int uncached_klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, true); }
++ int uncached_name_and_type_ref_index_at(int which) { return impl_name_and_type_ref_index_at(which, true); }
+
+ // Sharing
+ int pre_resolve_shared_klasses(TRAPS);
+@@ -413,16 +419,19 @@
+
+ private:
+
++ symbolOop impl_name_ref_at(int which, bool uncached);
++ symbolOop impl_signature_ref_at(int which, bool uncached);
++ int impl_klass_ref_index_at(int which, bool uncached);
++ int impl_name_and_type_ref_index_at(int which, bool uncached);
++
+ // Takes either a constant pool cache index in possibly byte-swapped
// byte order (which comes from the bytecodes after rewriting) or,
// if "uncached" is true, a vanilla constant pool index
jint field_or_method_at(int which, bool uncached) {
@@ -2961,20 +3034,14 @@ diff --git a/src/share/vm/oops/constantP
}
assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
return *int_at_addr(i);
- }
-+
-+ int map_instruction_operand_to_index(int operand);
-
- // Used while constructing constant pool (only by ClassFileParser)
- jint klass_index_at(int which) {
diff --git a/src/share/vm/oops/cpCacheKlass.cpp b/src/share/vm/oops/cpCacheKlass.cpp
--- a/src/share/vm/oops/cpCacheKlass.cpp
+++ b/src/share/vm/oops/cpCacheKlass.cpp
-@@ -135,11 +135,47 @@
+@@ -169,11 +169,47 @@
void constantPoolCacheKlass::oop_copy_contents(PSPromotionManager* pm,
oop obj) {
assert(obj->is_constantPoolCache(), "should be constant pool");
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ constantPoolCacheOop cache = (constantPoolCacheOop)obj;
+ // during a scavenge, it is safe to inspect my pool, since it is perm
+ constantPoolOop pool = cache->constant_pool();
@@ -2997,7 +3064,7 @@ diff --git a/src/share/vm/oops/cpCacheKl
void constantPoolCacheKlass::oop_push_contents(PSPromotionManager* pm,
oop obj) {
assert(obj->is_constantPoolCache(), "should be constant pool");
-+ if (InvokeDynamic) {
++ if (EnableInvokeDynamic) {
+ constantPoolCacheOop cache = (constantPoolCacheOop)obj;
+ // during a scavenge, it is safe to inspect my pool, since it is perm
+ constantPoolOop pool = cache->constant_pool();
@@ -3049,15 +3116,12 @@ diff --git a/src/share/vm/oops/cpCacheOo
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface: {
if (method->can_be_statically_bound()) {
-@@ -208,6 +219,23 @@
- set_f2(index);
- set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), false, false, false, true) | method()->size_of_parameters());
- set_bytecode_1(Bytecodes::_invokeinterface);
-+}
-+
-+
+@@ -211,6 +222,23 @@
+ }
+
+
+void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, int index) {
-+ methodOop method = (methodOop) java_dyn_impl_DynCallSite::vmref(call_site());
++ methodOop method = (methodOop) impl_java_dyn_CallSiteImpl::vmmethod(call_site());
+ assert(method->is_method(), "must be initialized properly");
+ int param_size = method->size_of_parameters();
+ assert(param_size > 1, "method argument size must include MH.this & initial dynamic receiver");
@@ -3070,9 +3134,12 @@ diff --git a/src/share/vm/oops/cpCacheOo
+ set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), false, false, false, true) | param_size);
+ // do not do set_bytecode on a secondary CP cache entry
+ //set_bytecode_1(Bytecodes::_invokedynamic);
- }
-
-
++}
++
++
+ class LocalOopClosure: public OopClosure {
+ private:
+ void (*_f)(oop*);
@@ -392,7 +420,11 @@
// print separator
if (index == 0) tty->print_cr(" -------------");
@@ -3132,7 +3199,7 @@ diff --git a/src/share/vm/oops/cpCacheOo
Bytecodes::Code bytecode_1() const { return Bytecodes::cast((_indices >> 16) & 0xFF); }
Bytecodes::Code bytecode_2() const { return Bytecodes::cast((_indices >> 24) & 0xFF); }
volatile oop f1() const { return _f1; }
-@@ -311,10 +324,30 @@
+@@ -314,10 +327,30 @@
// Initialization
void initialize(intArray& inverse_index_map);
@@ -3161,8 +3228,8 @@ diff --git a/src/share/vm/oops/cpCacheOo
+ return e;
+ }
- // Code generation
- static ByteSize base_offset() { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); }
+ // GC support
+ // If the _length field has not been set, the size of the
diff --git a/src/share/vm/oops/generateOopMap.cpp b/src/share/vm/oops/generateOopMap.cpp
--- a/src/share/vm/oops/generateOopMap.cpp
+++ b/src/share/vm/oops/generateOopMap.cpp
@@ -3193,93 +3260,10 @@ diff --git a/src/share/vm/oops/generateO
case Bytecodes::_newarray:
case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;
case Bytecodes::_checkcast: do_checkcast(); break;
-diff --git a/src/share/vm/oops/instanceKlass.cpp b/src/share/vm/oops/instanceKlass.cpp
---- a/src/share/vm/oops/instanceKlass.cpp
-+++ b/src/share/vm/oops/instanceKlass.cpp
-@@ -1996,9 +1996,11 @@
-
- // Printing
-
-+#define BULLET " - "
-+
- void FieldPrinter::do_field(fieldDescriptor* fd) {
-- if (fd->is_static() == (_obj == NULL)) {
-- _st->print(" - ");
-+ _st->print(BULLET);
-+ if (fd->is_static() || (_obj == NULL)) {
- fd->print_on(_st);
- _st->cr();
- } else {
-@@ -2019,7 +2021,7 @@
- value->is_typeArray() &&
- offset <= (juint) value->length() &&
- offset + length <= (juint) value->length()) {
-- st->print("string: ");
-+ st->print(BULLET"string: ");
- Handle h_obj(obj);
- java_lang_String::print(h_obj, st);
- st->cr();
-@@ -2027,22 +2029,22 @@
- }
- }
-
-- st->print_cr("fields:");
-+ st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj));
- FieldPrinter print_nonstatic_field(st, obj);
- do_nonstatic_fields(&print_nonstatic_field);
-
- if (as_klassOop() == SystemDictionary::class_klass()) {
- klassOop mirrored_klass = java_lang_Class::as_klassOop(obj);
-- st->print(" - fake entry for mirror: ");
-+ st->print(BULLET"fake entry for mirror: ");
- mirrored_klass->print_value_on(st);
- st->cr();
-- st->print(" - fake entry resolved_constructor: ");
-+ st->print(BULLET"fake entry resolved_constructor: ");
- methodOop ctor = java_lang_Class::resolved_constructor(obj);
- ctor->print_value_on(st);
- klassOop array_klass = java_lang_Class::array_klass(obj);
-- st->print(" - fake entry for array: ");
-+ st->cr();
-+ st->print(BULLET"fake entry for array: ");
- array_klass->print_value_on(st);
-- st->cr();
- st->cr();
- }
- }
-@@ -2051,6 +2053,28 @@
- st->print("a ");
- name()->print_value_on(st);
- obj->print_address_on(st);
-+ if (as_klassOop() == SystemDictionary::string_klass()
-+ && java_lang_String::value(obj) != NULL) {
-+ ResourceMark rm;
-+ int len = java_lang_String::length(obj);
-+ int plen = (len < 24 ? len : 12);
-+ char* str = java_lang_String::as_utf8_string(obj, 0, plen);
-+ st->print(" = \"%s\"", str);
-+ if (len > plen)
-+ st->print("...[%d]", len);
-+ } else if (as_klassOop() == SystemDictionary::class_klass()) {
-+ klassOop k = java_lang_Class::as_klassOop(obj);
-+ st->print(" = ");
-+ if (k != NULL) {
-+ k->print_value_on(st);
-+ } else {
-+ const char* tname = type2name(java_lang_Class::primitive_type(obj));
-+ st->print("%s", tname ? tname : "type?");
-+ }
-+ } else if (java_lang_boxing_object::is_instance(obj)) {
-+ st->print(" = ");
-+ java_lang_boxing_object::print(obj, st);
-+ }
- }
-
- #endif // ndef PRODUCT
diff --git a/src/share/vm/oops/instanceKlass.hpp b/src/share/vm/oops/instanceKlass.hpp
--- a/src/share/vm/oops/instanceKlass.hpp
+++ b/src/share/vm/oops/instanceKlass.hpp
-@@ -161,6 +161,8 @@
+@@ -163,6 +163,8 @@
klassOop _implementors[implementors_limit];
// Generic signature, or null if none.
symbolOop _generic_signature;
@@ -3288,7 +3272,7 @@ diff --git a/src/share/vm/oops/instanceK
// Annotations for this class, or null if none.
typeArrayOop _class_annotations;
// Annotation objects (byte arrays) for fields, or null if no annotations.
-@@ -443,6 +445,10 @@
+@@ -461,6 +463,10 @@
u2 method_index) { _enclosing_method_class_index = class_index;
_enclosing_method_method_index = method_index; }
@@ -3299,7 +3283,7 @@ diff --git a/src/share/vm/oops/instanceK
// jmethodID support
static jmethodID get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
jmethodID new_id, jmethodID* new_jmeths);
-@@ -723,6 +729,7 @@
+@@ -741,6 +747,7 @@
oop* adr_inner_classes() const { return (oop*)&this->_inner_classes;}
oop* adr_implementors() const { return (oop*)&this->_implementors[0];}
oop* adr_generic_signature() const { return (oop*)&this->_generic_signature;}
@@ -3359,260 +3343,30 @@ diff --git a/src/share/vm/oops/instanceK
ik->release_set_methods_jmethod_ids(NULL);
ik->release_set_methods_cached_itable_indices(NULL);
ik->set_class_annotations(NULL);
-@@ -487,6 +494,8 @@
-
- // Printing
-
-+#define BULLET " - "
-+
- static const char* state_names[] = {
- "unparseable_by_gc", "allocated", "loaded", "linked", "being_initialized", "fully_initialized", "initialization_error"
- };
-@@ -497,13 +506,13 @@
- instanceKlass* ik = instanceKlass::cast(klassOop(obj));
- klassKlass::oop_print_on(obj, st);
-
-- st->print(" - instance size: %d", ik->size_helper()); st->cr();
-- st->print(" - klass size: %d", ik->object_size()); st->cr();
-- st->print(" - access: "); ik->access_flags().print_on(st); st->cr();
-- st->print(" - state: "); st->print_cr(state_names[ik->_init_state]);
-- st->print(" - name: "); ik->name()->print_value_on(st); st->cr();
-- st->print(" - super: "); ik->super()->print_value_on(st); st->cr();
-- st->print(" - sub: ");
-+ st->print(BULLET"instance size: %d", ik->size_helper()); st->cr();
-+ st->print(BULLET"klass size: %d", ik->object_size()); st->cr();
-+ st->print(BULLET"access: "); ik->access_flags().print_on(st); st->cr();
-+ st->print(BULLET"state: "); st->print_cr(state_names[ik->_init_state]);
-+ st->print(BULLET"name: "); ik->name()->print_value_on(st); st->cr();
-+ st->print(BULLET"super: "); ik->super()->print_value_on(st); st->cr();
-+ st->print(BULLET"sub: ");
- Klass* sub = ik->subklass();
- int n;
- for (n = 0; sub != NULL; n++, sub = sub->next_sibling()) {
-@@ -516,12 +525,12 @@
- st->cr();
-
- if (ik->is_interface()) {
-- st->print_cr(" - nof implementors: %d", ik->nof_implementors());
-+ st->print_cr(BULLET"nof implementors: %d", ik->nof_implementors());
- int print_impl = 0;
- for (int i = 0; i < instanceKlass::implementors_limit; i++) {
- if (ik->implementor(i) != NULL) {
- if (++print_impl == 1)
-- st->print_cr(" - implementor: ");
-+ st->print_cr(BULLET"implementor: ");
- st->print(" ");
- ik->implementor(i)->print_value_on(st);
- }
-@@ -529,34 +538,33 @@
- if (print_impl > 0) st->cr();
- }
-
-- st->print(" - arrays: "); ik->array_klasses()->print_value_on(st); st->cr();
-- st->print(" - methods: "); ik->methods()->print_value_on(st); st->cr();
-+ st->print(BULLET"arrays: "); ik->array_klasses()->print_value_on(st); st->cr();
-+ st->print(BULLET"methods: "); ik->methods()->print_value_on(st); st->cr();
- if (Verbose) {
- objArrayOop methods = ik->methods();
- for(int i = 0; i < methods->length(); i++) {
- tty->print("%d : ", i); methods->obj_at(i)->print_value(); tty->cr();
- }
- }
-- st->print(" - method ordering: "); ik->method_ordering()->print_value_on(st); st->cr();
-- st->print(" - local interfaces: "); ik->local_interfaces()->print_value_on(st); st->cr();
-- st->print(" - trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr();
-- st->print(" - constants: "); ik->constants()->print_value_on(st); st->cr();
-- st->print(" - class loader: "); ik->class_loader()->print_value_on(st); st->cr();
-- st->print(" - protection domain: "); ik->protection_domain()->print_value_on(st); st->cr();
-- st->print(" - host class: "); ik->host_klass()->print_value_on(st); st->cr();
-- st->print(" - signers: "); ik->signers()->print_value_on(st); st->cr();
-+ st->print(BULLET"method ordering: "); ik->method_ordering()->print_value_on(st); st->cr();
-+ st->print(BULLET"local interfaces: "); ik->local_interfaces()->print_value_on(st); st->cr();
-+ st->print(BULLET"trans. interfaces: "); ik->transitive_interfaces()->print_value_on(st); st->cr();
-+ st->print(BULLET"constants: "); ik->constants()->print_value_on(st); st->cr();
-+ st->print(BULLET"class loader: "); ik->class_loader()->print_value_on(st); st->cr();
-+ st->print(BULLET"protection domain: "); ik->protection_domain()->print_value_on(st); st->cr();
-+ st->print(BULLET"host class: "); ik->host_klass()->print_value_on(st); st->cr();
-+ st->print(BULLET"signers: "); ik->signers()->print_value_on(st); st->cr();
- if (ik->source_file_name() != NULL) {
-- st->print(" - source file: ");
-+ st->print(BULLET"source file: ");
- ik->source_file_name()->print_value_on(st);
- st->cr();
- }
- if (ik->source_debug_extension() != NULL) {
-- st->print(" - source debug extension: ");
-+ st->print(BULLET"source debug extension: ");
- ik->source_debug_extension()->print_value_on(st);
- st->cr();
- }
-
-- st->print_cr(" - previous version: ");
- {
- ResourceMark rm;
- // PreviousVersionInfo objects returned via PreviousVersionWalker
-@@ -564,38 +572,48 @@
- // GrowableArray _after_ the PreviousVersionWalker destructor
- // has destroyed the handles.
- {
-+ bool have_pv = false;
- PreviousVersionWalker pvw(ik);
- for (PreviousVersionInfo * pv_info = pvw.next_previous_version();
- pv_info != NULL; pv_info = pvw.next_previous_version()) {
-+ if (!have_pv)
-+ st->print(BULLET"previous version: ");
-+ have_pv = true;
- pv_info->prev_constant_pool_handle()()->print_value_on(st);
- }
-- st->cr();
-+ if (have_pv) st->cr();
+@@ -578,6 +585,11 @@
} // pvw is cleaned up
} // rm is cleaned up
- if (ik->generic_signature() != NULL) {
-- st->print(" - generic signature: ");
-+ st->print(BULLET"generic signature: ");
- ik->generic_signature()->print_value_on(st);
-+ st->cr();
- }
-- st->print(" - inner classes: "); ik->inner_classes()->print_value_on(st); st->cr();
-- st->print(" - java mirror: "); ik->java_mirror()->print_value_on(st); st->cr();
-- st->print(" - vtable length %d (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable()); st->cr();
-- st->print(" - itable length %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr();
-- st->print_cr(" - static fields:");
+ if (ik->bootstrap_method() != NULL) {
+ st->print(BULLET"bootstrap method: ");
+ ik->bootstrap_method()->print_value_on(st);
+ st->cr();
+ }
-+ st->print(BULLET"inner classes: "); ik->inner_classes()->print_value_on(st); st->cr();
-+ st->print(BULLET"java mirror: "); ik->java_mirror()->print_value_on(st); st->cr();
-+ st->print(BULLET"vtable length %d (start addr: " INTPTR_FORMAT ")", ik->vtable_length(), ik->start_of_vtable()); st->cr();
-+ st->print(BULLET"itable length %d (start addr: " INTPTR_FORMAT ")", ik->itable_length(), ik->start_of_itable()); st->cr();
-+ st->print_cr(BULLET"---- static fields (%d words):", ik->static_field_size());
- FieldPrinter print_static_field(st);
- ik->do_local_static_fields(&print_static_field);
-- st->print_cr(" - non-static fields:");
-- FieldPrinter print_nonstatic_field(st, obj);
-+ st->print_cr(BULLET"---- non-static fields (%d words):", ik->nonstatic_field_size());
-+ FieldPrinter print_nonstatic_field(st);
- ik->do_nonstatic_fields(&print_nonstatic_field);
-
-- st->print(" - static oop maps: ");
-+ st->print(BULLET"static oop maps: ");
- if (ik->static_oop_field_size() > 0) {
- int first_offset = ik->offset_of_static_fields();
- st->print("%d-%d", first_offset, first_offset + ik->static_oop_field_size() - 1);
- }
- st->cr();
-
-- st->print(" - non-static oop maps: ");
-+ st->print(BULLET"non-static oop maps: ");
- OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
- OopMapBlock* end_map = map + ik->nonstatic_oop_map_size();
- while (map < end_map) {
-diff --git a/src/share/vm/oops/methodOop.cpp b/src/share/vm/oops/methodOop.cpp
---- a/src/share/vm/oops/methodOop.cpp
-+++ b/src/share/vm/oops/methodOop.cpp
-@@ -792,6 +792,7 @@
- _imcp_invoke_name = 1, // utf8: 'invoke'
- _imcp_invoke_signature, // utf8: (variable symbolOop)
- _imcp_method_type_value, // string: (variable java/dyn/MethodType, sic)
-+ _imcp_related_invoke_method, // string: (variable methodOop, sic)
- _imcp_limit
- };
-
-@@ -819,7 +820,8 @@
- Handle method_type, TRAPS) {
- methodHandle empty;
-
-- assert(holder() == SystemDictionary::java_dyn_MethodHandle_klass(),
-+ assert(holder() == SystemDictionary::java_dyn_MethodHandle_klass() ||
-+ holder() == SystemDictionary::java_dyn_Dynamic_klass(),
- "must be a JSR 292 magic type");
-
- if (TraceMethodHandles) {
-@@ -836,6 +838,7 @@
- cp->symbol_at_put(_imcp_invoke_name, vmSymbols::invoke_name());
- cp->symbol_at_put(_imcp_invoke_signature, signature());
- cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature());
-+ cp->string_at_put(_imcp_related_invoke_method, vmSymbols::void_signature());
- cp->set_pool_holder(holder());
-
- // set up the fancy stuff:
-@@ -847,6 +850,7 @@
- 0, 0, 0, CHECK_(empty));
- m = methodHandle(THREAD, m_oop);
- }
-+ cp->pseudo_string_at_put(_imcp_related_invoke_method, m());
- m->set_constants(cp());
- m->set_name_index(_imcp_invoke_name);
- m->set_signature_index(_imcp_invoke_signature);
-@@ -880,6 +884,42 @@
- return m;
- }
-
-+methodOop methodOopDesc::related_invoke_method(int relation) const {
-+ if (!is_method_handle_invoke()) { assert(false, "caller resp."); return NULL; }
-+ methodOop idm = (methodOop) constants()->pseudo_string_at(_imcp_related_invoke_method);
-+ if (this == idm) return NULL;
-+#ifdef ASSERT
-+ assert(idm->is_method() && methodOop(idm)->is_method_handle_invoke(), "");
-+ klassOop expect = ((relation == RM_invdyn)
-+ ? SystemDictionary::java_dyn_Dynamic_klass()
-+ : SystemDictionary::java_dyn_MethodHandle_klass());
-+ assert(idm->method_holder() == expect, "expected type of related method");
-+#endif //ASSERT
-+ return idm;
-+}
-+
-+void methodOopDesc::set_related_invoke_method(methodOop idm, int relation) {
-+ if (!is_method_handle_invoke()) { assert(false, "caller resp."); return; }
-+
-+#ifdef ASSERT
-+ assert(idm != NULL && this != idm && idm->is_method() && methodOop(idm)->is_method_handle_invoke(), "");
-+ if (method_holder() == SystemDictionary::java_dyn_MethodHandle_klass()) {
-+ assert(relation == RM_invdyn, "expected relation");
-+ assert(idm->method_holder() == SystemDictionary::java_dyn_Dynamic_klass(), "MH -> Dyn");
-+ assert(idm->method_handle_type() == this->method_handle_type(), "same types");
-+ } else if (method_holder() == SystemDictionary::java_dyn_Dynamic_klass()) {
-+ assert(relation == RM_extinv, "expected relation");
-+ assert(idm->method_holder() == SystemDictionary::java_dyn_MethodHandle_klass(), "Dyn -> MH");
-+ assert(idm->method_handle_type() != this->method_handle_type(), "MH type is extension");
-+ } else {
-+ ShouldNotReachHere();
-+ }
-+ methodOop oldidm = (methodOop) constants()->pseudo_string_at(_imcp_related_invoke_method);
-+ assert(this == oldidm || idm == oldidm, "one change allowed");
-+#endif //ASSERT
-+
-+ constants()->pseudo_string_at_put(_imcp_related_invoke_method, idm);
-+}
-
-
- methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
+ if (ik->generic_signature() != NULL) {
+ st->print(BULLET"generic signature: ");
+ ik->generic_signature()->print_value_on(st);
diff --git a/src/share/vm/oops/methodOop.hpp b/src/share/vm/oops/methodOop.hpp
--- a/src/share/vm/oops/methodOop.hpp
+++ b/src/share/vm/oops/methodOop.hpp
-@@ -529,7 +529,17 @@
+@@ -534,7 +534,7 @@
oop method_handle_type() const;
- static jint* method_type_pointer_chase();
- // presize interpreter frames for extra stack slots, if needed
-- static int extra_stack() { return MethodHandles ? 2 : 0; }
-+ static int extra_stack() { return InvokeDynamic ? 2 : MethodHandles ? 1 : 0; }
-+ private:
-+ methodOop related_invoke_method(int relation) const;
-+ void set_related_invoke_method(methodOop idm, int relation);
-+ enum { RM_invdyn, RM_extinv };
-+ public:
-+ methodOop invokedynamic_method() const { return related_invoke_method(RM_invdyn); }
-+ void set_invokedynamic_method(methodOop idm) { set_related_invoke_method(idm, RM_invdyn); }
-+ methodOop extended_invoke_method() const { return related_invoke_method(RM_extinv); }
-+ void set_extended_invoke_method(methodOop ext) { set_related_invoke_method(ext, RM_extinv); }
-+
+ static jint* method_type_offsets_chain(); // series of pointer-offsets, terminated by -1
+ // presize interpreter frames for extra interpreter stack entries, if needed
+- static int extra_stack_entries() { return EnableMethodHandles ? (int)MethodHandlePushLimit : 0; }
++ static int extra_stack_entries() { return (EnableMethodHandles ? (int)MethodHandlePushLimit : 0) + (EnableInvokeDynamic ? 1 : 0); }
+ static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize()
// RedefineClasses() support:
bool is_old() const { return access_flags().is_old(); }
- void set_is_old() { _access_flags.set_is_old(); }
diff --git a/src/share/vm/opto/bytecodeInfo.cpp b/src/share/vm/opto/bytecodeInfo.cpp
--- a/src/share/vm/opto/bytecodeInfo.cpp
+++ b/src/share/vm/opto/bytecodeInfo.cpp
@@ -3628,21 +3382,21 @@ diff --git a/src/share/vm/opto/doCall.cp
diff --git a/src/share/vm/opto/doCall.cpp b/src/share/vm/opto/doCall.cpp
--- a/src/share/vm/opto/doCall.cpp
+++ b/src/share/vm/opto/doCall.cpp
-@@ -245,6 +245,14 @@
- !holder_klass->is_interface()) {
- uncommon_trap(Deoptimization::Reason_uninitialized,
- Deoptimization::Action_reinterpret,
-+ holder_klass);
-+ return true;
-+ }
+@@ -248,6 +248,14 @@
+ holder_klass);
+ return true;
+ }
+ if (dest_method->is_method_handle_invoke()
+ && holder_klass->name() == ciSymbol::java_dyn_Dynamic()) {
+ // FIXME: NYI
+ uncommon_trap(Deoptimization::Reason_unhandled,
+ Deoptimization::Action_none,
- holder_klass);
- return true;
- }
++ holder_klass);
++ return true;
++ }
+
+ assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility");
+ return false;
diff --git a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
--- a/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
+++ b/src/share/vm/prims/jvmtiClassFileReconstituter.cpp
@@ -3651,7 +3405,7 @@ diff --git a/src/share/vm/prims/jvmtiCla
assert(len == 3 || (code == Bytecodes::_invokeinterface && len ==5),
"sanity check");
+ int cpci = Bytes::get_native_u2(bcp+1);
-+ bool is_invokedynamic = (InvokeDynamic && bs.raw_code() == Bytecodes::_invokedynamic);
++ bool is_invokedynamic = (EnableInvokeDynamic && bs.raw_code() == Bytecodes::_invokedynamic);
+ if (is_invokedynamic)
+ cpci = Bytes::get_native_u4(bcp+1);
// cache cannot be pre-fetched since some classes won't have it yet
@@ -3686,16 +3440,16 @@ diff --git a/src/share/vm/prims/methodHa
diff --git a/src/share/vm/prims/methodHandles.cpp b/src/share/vm/prims/methodHandles.cpp
--- a/src/share/vm/prims/methodHandles.cpp
+++ b/src/share/vm/prims/methodHandles.cpp
-@@ -613,6 +613,16 @@
+@@ -2231,6 +2231,16 @@
JVM_END
+JVM_ENTRY(void, MH_linkCallSite(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) {
+ // No special action required, yet.
+ oop site_oop = JNIHandles::resolve(site_jh);
-+ if (site_oop == NULL || site_oop->klass() != SystemDictionary::dyn_impl_DynCallSite_klass())
++ if (site_oop == NULL || site_oop->klass() != SystemDictionary::CallSiteImpl_klass())
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "call site");
-+ java_dyn_impl_DynCallSite::set_target(site_oop, JNIHandles::resolve(target_jh));
++ impl_java_dyn_CallSiteImpl::set_target(site_oop, JNIHandles::resolve(target_jh));
+}
+JVM_END
+
@@ -3703,48 +3457,46 @@ diff --git a/src/share/vm/prims/methodHa
/// JVM_RegisterMethodHandleMethods
#define ADR "J"
-@@ -630,6 +640,7 @@
- #define DMH DYNI"DMH;"
- #define MT DYNP"MethodType;"
- #define MTFM DYNI"MTForm;"
-+#define DCST DYNI"DynCallSite;"
+@@ -2249,6 +2259,7 @@
+ #define AMH IDYN"AdapterMethodHandle;"
+ #define BMH IDYN"BoundMethodHandle;"
+ #define DMH IDYN"DirectMethodHandle;"
++#define CSTI IDYN"CallSiteImpl;"
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
-@@ -641,7 +652,8 @@
- {CC"init", CC"("DMH OBJ"Z)V", FN_PTR(MH_init_DMH)},
- {CC"init", CC"("MTFM MT")V", FN_PTR(MH_init_MTForm)},
- {CC"getMethodName", CC"("MH")"STRG, FN_PTR(MH_methodName)},
-- {CC"getVMRef", CC"("MH")"OBJ, FN_PTR(MH_vmref)}
-+ {CC"getVMRef", CC"("MH")"OBJ, FN_PTR(MH_vmref)},
-+ {CC"linkCallSite", CC"("DCST MH")V", FN_PTR(MH_linkCallSite)}
- };
-
-
+@@ -2263,6 +2274,7 @@
+ {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHI_init_Mem)},
+ {CC"expand", CC"("MEM")V", FN_PTR(MHI_expand_Mem)},
+ {CC"resolve", CC"("MEM""CLS")V", FN_PTR(MHI_resolve_Mem)},
++ {CC"linkCallSite", CC"("CSTI MH")V", FN_PTR(MH_linkCallSite)},
+ {CC"getTarget", CC"("MH"I)"OBJ, FN_PTR(MHI_getTarget)},
+ {CC"getConstant", CC"(I)I", FN_PTR(MHI_getConstant)},
+ // static native int getNamedCon(int which, Object[] name)
diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp
--- a/src/share/vm/runtime/arguments.cpp
+++ b/src/share/vm/runtime/arguments.cpp
-@@ -2573,6 +2573,12 @@
+@@ -2620,6 +2620,12 @@
}
#endif // PRODUCT
-+ if (InvokeDynamic && !MethodHandles) {
-+ if (!FLAG_IS_DEFAULT(MethodHandles)) {
-+ warning("forcing MethodHandles true to support InvokeDynamic");
++ if (EnableInvokeDynamic && !EnableMethodHandles) {
++ if (!FLAG_IS_DEFAULT(EnableMethodHandles)) {
++ warning("forcing EnableMethodHandles true to allow EnableInvokeDynamic");
+ }
-+ MethodHandles = true;
-+ }
- if (MethodHandles && !AnonymousClasses) {
++ EnableMethodHandles = true;
++ }
+ if (EnableMethodHandles && !AnonymousClasses) {
if (!FLAG_IS_DEFAULT(AnonymousClasses)) {
- warning("forcing AnonymousClasses true to support MethodHandles");
+ warning("forcing AnonymousClasses true to enable EnableMethodHandles");
diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp
--- a/src/share/vm/runtime/globals.hpp
+++ b/src/share/vm/runtime/globals.hpp
-@@ -3239,6 +3239,12 @@
- develop(bool, TraceMethodHandles, false, \
- "trace internal method handle operations") \
+@@ -3285,6 +3285,12 @@
+ diagnostic(bool, OptimizeMethodHandles, true, \
+ "when constructing method handles, try to improve them") \
\
-+ product(bool, InvokeDynamic, false, \
++ product(bool, EnableInvokeDynamic, false, \
+ "recognize the invokedynamic instruction") \
+ \
+ develop(bool, TraceInvokeDynamic, false, \
@@ -3756,18 +3508,18 @@ diff --git a/src/share/vm/runtime/shared
diff --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp
--- a/src/share/vm/runtime/sharedRuntime.cpp
+++ b/src/share/vm/runtime/sharedRuntime.cpp
-@@ -793,6 +793,7 @@
+@@ -780,6 +780,7 @@
KlassHandle receiver_klass (THREAD, receiver->klass());
klassOop rk = constants->klass_ref_at(bytecode_index, CHECK_(nullHandle));
// klass is already loaded
-+ assert(rk != SystemDictionary::java_dyn_Dynamic_klass(), "compiler should have caught this");
++ assert(rk != SystemDictionary::Dynamic_klass(), "compiler should have caught this");
KlassHandle static_receiver_klass (THREAD, rk);
assert(receiver_klass->is_subtype_of(static_receiver_klass()), "actual receiver must be subclass of static receiver klass");
if (receiver_klass->oop_is_instance()) {
diff --git a/src/share/vm/utilities/globalDefinitions.hpp b/src/share/vm/utilities/globalDefinitions.hpp
--- a/src/share/vm/utilities/globalDefinitions.hpp
+++ b/src/share/vm/utilities/globalDefinitions.hpp
-@@ -578,7 +578,7 @@
+@@ -588,7 +588,7 @@
inline TosState as_TosState(BasicType type) {
switch (type) {
case T_BYTE : return btos;
@@ -3776,12 +3528,10 @@ diff --git a/src/share/vm/utilities/glob
case T_CHAR : return ctos;
case T_SHORT : return stos;
case T_INT : return itos;
-@@ -590,6 +590,22 @@
- case T_OBJECT : return atos;
- }
+@@ -602,6 +602,22 @@
return ilgl;
-+}
-+
+ }
+
+inline BasicType as_BasicType(TosState state) {
+ switch (state) {
+ //case ztos: return T_BOOLEAN;//FIXME
@@ -3796,6 +3546,8 @@ diff --git a/src/share/vm/utilities/glob
+ case vtos : return T_VOID;
+ }
+ return T_ILLEGAL;
- }
-
-
++}
++
+
+ // Helper function to convert BasicType info into TosState
+ // Note: Cannot define here as it uses global constant at the time being.
--- a/series Sat Mar 21 23:57:50 2009 -0700
+++ b/series Fri Apr 03 00:24:23 2009 -0700
@@ -9,7 +9,8 @@ meth-6655638.patch #-/meth
meth-6655638.patch #-/meth #+05f8c84c5daa
meth.patch #-/meth #+05f8c84c5daa
-indy.patch #-/indy #+8fb16f199266 #+jdk7-b38
+indy.patch #-/indy #+05f8c84c5daa
+
annot.patch #-/annot #+d1605aabd0a1 #+jdk7-b30 #-testable
#inti.patch #-/inti #+d1605aabd0a1 #+jdk7-b30 #-buildable
callcc.patch #-/callcc #+d1605aabd0a1 #+jdk7-b30 #-testable