--- a/anonk.patch Mon Sep 01 15:49:33 2008 -0700
+++ b/anonk.patch Mon Sep 01 22:35:12 2008 -0700
@@ -538,20 +538,19 @@ diff --git a/src/share/vm/oops/constantP
}
#endif // SERIALGC
-@@ -278,6 +301,12 @@
+@@ -278,6 +301,11 @@
assert(obj->is_constantPool(), "must be constantPool");
Klass::oop_print_on(obj, st);
constantPoolOop cp = constantPoolOop(obj);
+ if (cp->flags() != 0) {
+ st->print(" - flags : 0x%x", cp->flags());
+ if (cp->has_pseudo_string()) st->print(" has_pseudo_string");
-+ if (cp->has_invokedynamic()) st->print(" has_invokedynamic");
+ st->cr();
+ }
// Temp. remove cache so we can do lookups with original indicies.
constantPoolCacheHandle cache (THREAD, cp->cache());
-@@ -302,7 +331,7 @@
+@@ -302,7 +330,7 @@
break;
case JVM_CONSTANT_UnresolvedString :
case JVM_CONSTANT_String :
@@ -560,7 +559,7 @@ diff --git a/src/share/vm/oops/constantP
anObj->print_value_on(st);
st->print(" {0x%lx}", (address)anObj);
break;
-@@ -382,8 +411,12 @@
+@@ -382,8 +410,12 @@
"should be symbol or instance");
}
if (cp->tag_at(i).is_string()) {
@@ -640,13 +639,12 @@ diff --git a/src/share/vm/oops/constantP
int _length; // number of elements in the array
// only set to non-zero if constant pool is merged by RedefineClasses
int _orig_length;
-@@ -48,6 +49,17 @@
+@@ -48,6 +49,16 @@
void set_tags(typeArrayOop tags) { oop_store_without_check((oop*)&_tags, tags); }
void tag_at_put(int which, jbyte t) { tags()->byte_at_put(which, t); }
void release_tag_at_put(int which, jbyte t) { tags()->release_byte_at_put(which, t); }
+
+ enum FlagBit {
-+ FB_has_invokedynamic = 1,
+ FB_has_pseudo_string = 2
+ };
+
@@ -658,19 +656,17 @@ diff --git a/src/share/vm/oops/constantP
private:
intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(constantPoolOopDesc)); }
-@@ -81,6 +93,11 @@
+@@ -81,6 +92,9 @@
public:
typeArrayOop tags() const { return _tags; }
+
+ bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); }
-+ bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); }
+ void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); }
-+ void set_invokedynamic() { set_flag_at(FB_has_invokedynamic); }
// Klass holding pool
klassOop pool_holder() const { return _pool_holder; }
-@@ -272,6 +289,23 @@
+@@ -272,6 +286,23 @@
return string_at_impl(h_this, which, CHECK_NULL);
}
@@ -694,7 +690,7 @@ diff --git a/src/share/vm/oops/constantP
// only called when we are sure a string entry is already resolved (via an
// earlier string_at call.
oop resolved_string_at(int which) {
-@@ -293,6 +327,7 @@
+@@ -293,6 +324,7 @@
// UTF8 char* representation was chosen to avoid conversion of
// java_lang_Strings at resolved entries into symbolOops
// or vice versa.
--- a/meth.patch Mon Sep 01 15:49:33 2008 -0700
+++ b/meth.patch Mon Sep 01 22:35:12 2008 -0700
@@ -359,7 +359,7 @@ diff --git a/src/cpu/sparc/vm/cppInterpr
const int slop_factor = 2*wordSize;
const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
-+ (InvokeDynamic ? 1 : 0) + // extra push slot for MH insertion
++ methodOopDesc::extra_stack() + // extra push slot for MH insertion
frame::memory_parameter_word_sp_offset + // register save area + param window
(native ? frame::interpreter_frame_extra_outgoing_argument_words : 0); // JNI, class
@@ -367,8 +367,8 @@ diff --git a/src/cpu/sparc/vm/cppInterpr
__ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
__ lduh(max_stack, O3); // Full size expression stack
-+ if (InvokeDynamic)
-+ __ inc(O3, wordSize);
++ if (MethodHandles)
++ __ inc(O3, methodOopDesc::extra_stack());
__ sll(O3, LogBytesPerWord, O3);
__ sub(O2, O3, O3);
// __ sub(O3, wordSize, O3); // so prepush doesn't look out of bounds
@@ -393,85 +393,6 @@ diff --git a/src/cpu/sparc/vm/cppInterpr
to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
// sparc specific
-diff --git a/src/cpu/sparc/vm/interp_masm_sparc.cpp b/src/cpu/sparc/vm/interp_masm_sparc.cpp
---- a/src/cpu/sparc/vm/interp_masm_sparc.cpp
-+++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp
-@@ -831,10 +831,26 @@
- }
-
-
--void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset) {
-+void InterpreterMacroAssembler::get_index_at_bcp(Register Rtmp, Register Rdst,
-+ int bcp_offset, bool giant_index) {
-+ assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
-+ if (!giant_index) {
-+ get_2_byte_integer_at_bcp(bcp_offset, Rtmp, Rdst, Unsigned);
-+ } else {
-+ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
-+ 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
-+ }
-+}
-+
-+
-+void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register tmp,
-+ int bcp_offset, bool giant_index) {
- assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
- assert_different_registers(cache, tmp);
- assert_not_delayed();
-+ assert(!giant_index,"NYI");
- 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
-@@ -843,10 +859,12 @@
- }
-
-
--void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) {
-+void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
-+ int bcp_offset, bool giant_index) {
- assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
- assert_different_registers(cache, tmp);
- assert_not_delayed();
-+ assert(!giant_index,"NYI");
- 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 @@
- // Count a virtual call in the bytecodes.
-
- void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
-- Register scratch) {
-+ Register scratch,
-+ bool receiver_can_be_null) {
- if (ProfileInterpreter) {
- Label profile_continue;
-
-diff --git a/src/cpu/sparc/vm/interp_masm_sparc.hpp b/src/cpu/sparc/vm/interp_masm_sparc.hpp
---- a/src/cpu/sparc/vm/interp_masm_sparc.hpp
-+++ b/src/cpu/sparc/vm/interp_masm_sparc.hpp
-@@ -191,8 +191,9 @@
- Register Rdst,
- setCCOrNot should_set_CC = dont_set_CC );
-
-- void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset);
-- void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset);
-+ void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
-+ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
-+ void get_index_at_bcp(Register Rtmp, Register Rdst, int bcp_offset, bool giant_index = false);
-
-
- // common code
-@@ -304,7 +305,7 @@
- void profile_not_taken_branch(Register scratch);
- void profile_call(Register scratch);
- void profile_final_call(Register scratch);
-- void profile_virtual_call(Register receiver, Register scratch);
-+ void profile_virtual_call(Register receiver, Register scratch, bool receiver_can_be_null = false);
- void profile_ret(TosState state, Register return_bci, Register scratch);
- void profile_null_seen(Register scratch);
- void profile_typecheck(Register klass, Register scratch);
diff --git a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
--- a/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
+++ b/src/cpu/sparc/vm/interpreterGenerator_sparc.hpp
@@ -1025,10 +946,15 @@ 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
-@@ -108,6 +108,34 @@
- }
-
-
+@@ -103,6 +103,34 @@
+ CAST_FROM_FN_PTR(address,
+ InterpreterRuntime::throw_ClassCastException),
+ Otos_i);
++ __ should_not_reach_here();
++ return entry;
++}
++
++
+#ifdef ASSERT
+address last_WrongMethodType_caller;
+#endif //ASSERT
@@ -1052,93 +978,18 @@ diff --git a/src/cpu/sparc/vm/templateIn
+ InterpreterRuntime::throw_WrongMethodTypeException),
+ G5_method_type, // required
+ G3_method_handle); // actual
-+ __ should_not_reach_here();
-+ return entry;
-+}
-+
-+
- address TemplateInterpreterGenerator::generate_ArrayIndexOutOfBounds_handler(const char* name) {
- address entry = __ pc();
- // expression stack must be empty before entering the VM if an exception happened
-@@ -132,7 +160,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 (unbox) {
-+ incoming_state = atos;
-+ }
-+ } else {
-+ assert(!unbox, "old behavior");
-+ }
-+
- address compiled_entry = __ pc();
- Label cont;
-
-@@ -147,7 +184,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.
-
-- if( state == ltos ) {
-+ if( incoming_state == ltos ) {
- __ srl (G1, 0,O1);
- __ srlx(G1,32,O0);
- }
-@@ -164,16 +201,42 @@
-
- __ mov(Llast_SP, SP); // Remove any adapter added stack space.
-
-+ if (unbox && state != atos) {
-+ // cast and unbox
-+ __ unimplemented();
-+ }
-
- const Register cache = G3_scratch;
- const Register size = G1_scratch;
-+ Label L_got_cache, L_giant_index;
-+ if (InvokeDynamic) {
-+ __ ldub(Lbcp, 0, size);
-+ __ cmp(size, Bytecodes::_invokedynamic);
-+ __ br(Assembler::equal, false, Assembler::pn, L_giant_index);
-+ __ delayed()->nop();
-+ }
- __ get_cache_and_index_at_bcp(cache, G1_scratch, 1);
-+ ////__ get_cache_and_index_at_bcp(cache, G1_scratch, 1, false);
-+ __ bind(L_got_cache);
-+ if (unbox && state == atos) {
-+ // insert a casting conversion, to keep verifier sane
-+ __ unimplemented();
-+ }
- __ 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
- __ add(Lesp, size, Lesp); // pop arguments
- __ dispatch_next(state, step);
-+
-+ // out of the main line of code...
-+ if (InvokeDynamic) {
-+ __ bind(L_giant_index);
-+ __ unimplemented();
-+ ////__ get_cache_and_index_at_bcp(cache, G1_scratch, 1, true);
-+ __ ba(false, L_got_cache);
-+ __ delayed()->nop();
-+ }
-
+ __ should_not_reach_here();
return entry;
}
-@@ -448,6 +511,7 @@
+@@ -448,6 +476,7 @@
const int extra_space =
rounded_vm_local_words + // frame local scratch space
-+ (InvokeDynamic ? 1 : 0) + // extra push slot for MH insertion
++ methodOopDesc::extra_stack() + // extra push slot for MH insertion
frame::memory_parameter_word_sp_offset + // register save area
(native_call ? frame::interpreter_frame_extra_outgoing_argument_words : 0);
-@@ -1445,7 +1509,8 @@
+@@ -1445,7 +1474,8 @@
// callee_locals and max_stack are counts, not the size in frame.
const int locals_size =
round_to(callee_extra_locals * Interpreter::stackElementWords(), WordsPerLong);
@@ -1148,40 +999,6 @@ diff --git a/src/cpu/sparc/vm/templateIn
return (round_to((max_stack_words
+ rounded_vm_local_words
+ frame::memory_parameter_word_sp_offset), WordsPerLong)
-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
-@@ -1907,7 +1907,8 @@
- __ delayed()->set((int)bytecode(), O1);
-
- address entry;
-- switch (bytecode()) {
-+ Bytecodes::Code code = Bytecodes::java_code(bytecode());
-+ switch (code) {
- case Bytecodes::_getstatic : // fall through
- case Bytecodes::_putstatic : // fall through
- case Bytecodes::_getfield : // fall through
-@@ -3053,6 +3054,20 @@
- }
-
-
-+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");
-+ return;
-+ }
-+
-+ __ stop("invokedynamic NYI");
-+}
-+
-+
- //----------------------------------------------------------------------------------------------------
- // Allocation
-
diff --git a/src/cpu/x86/vm/assembler_x86_32.cpp b/src/cpu/x86/vm/assembler_x86_32.cpp
--- a/src/cpu/x86/vm/assembler_x86_32.cpp
+++ b/src/cpu/x86/vm/assembler_x86_32.cpp
@@ -1556,31 +1373,7 @@ diff --git a/src/cpu/x86/vm/assembler_x8
//----
void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
-@@ -1464,6 +1554,23 @@
- void movoop(Register dst, jobject obj);
- void movoop(Address dst, jobject obj);
-
-+ void movptr(Register dst, Register src) {
-+ LP64_ONLY( movq(dst, src) );
-+ NOT_LP64( movl(dst, src) );
-+ }
-+ void movptr(Register dst, Address src) {
-+ LP64_ONLY( movq(dst, src) );
-+ NOT_LP64( movl(dst, src) );
-+ }
-+ void movptr(Address dst, Register src) {
-+ LP64_ONLY( movq(dst, src) );
-+ NOT_LP64( movl(dst, src) );
-+ }
-+ void movptr(Address dst, intptr_t src) {
-+ LP64_ONLY( movq(dst, src) );
-+ NOT_LP64( movl(dst, src) );
-+ }
-+
- void movptr(ArrayAddress dst, Register src);
- // can this do an lea?
- void movptr(Register dst, ArrayAddress src);
-@@ -1481,6 +1588,18 @@
+@@ -1481,6 +1571,22 @@
#undef VIRTUAL
@@ -1590,6 +1383,10 @@ diff --git a/src/cpu/x86/vm/assembler_x8
+ void push(Register d) { pushl(d); }
+ void push(intptr_t d) { pushl(d); }
+ void mov(Register a, Register b) { movl(a, b); }
++ void movptr(Register d, Register s) { movl(d, s); }
++ void movptr(Register d, Address s) { movl(d, s); }
++ void movptr(Address d, Register s) { movl(d, s); }
++ void movptr(Address d, intptr_t s) { movl(d, s); }
+ void addptr(Register a, Register b) { addl(a, b); }
+ void addptr(Register a, intptr_t b) { addl(a, b); }
+ void testptr(Register a, Register b) { testl(a, b); }
@@ -1965,23 +1762,7 @@ diff --git a/src/cpu/x86/vm/assembler_x8
//----
// Debugging
-@@ -1434,6 +1525,15 @@
- void movoop(Register dst, jobject obj);
- void movoop(Address dst, jobject obj);
-
-+ void movptr(Address dst, Register src) {
-+ LP64_ONLY( movq(dst, src) );
-+ NOT_LP64( movl(dst, src) );
-+ }
-+ void movptr(Register dst, Address src) {
-+ LP64_ONLY( movq(dst, src) );
-+ NOT_LP64( movl(dst, src) );
-+ }
-+
- void movptr(ArrayAddress dst, Register src);
- void movptr(Register dst, AddressLiteral src);
-
-@@ -1451,6 +1551,18 @@
+@@ -1451,6 +1542,22 @@
// Can push value or effective address
void pushptr(AddressLiteral src);
@@ -1991,6 +1772,10 @@ diff --git a/src/cpu/x86/vm/assembler_x8
+ void push(Register d) { pushq(d); }
+ void push(intptr_t d) { pushq(d); }
+ void mov(Register a, Register b) { movq(a, b); }
++ void movptr(Register d, Register s) { movq(d, s); }
++ void movptr(Register d, Address s) { movq(d, s); }
++ void movptr(Address d, Register s) { movq(d, s); }
++ void movptr(Address d, intptr_t s) { movq(d, s); }
+ void addptr(Register a, Register b) { addq(a, b); }
+ void addptr(Register a, intptr_t b) { addq(a, b); }
+ void testptr(Register a, Register b) { testq(a, b); }
@@ -2079,46 +1864,7 @@ diff --git a/src/cpu/x86/vm/interp_masm_
diff --git a/src/cpu/x86/vm/interp_masm_x86_32.cpp b/src/cpu/x86/vm/interp_masm_x86_32.cpp
--- a/src/cpu/x86/vm/interp_masm_x86_32.cpp
+++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp
-@@ -188,20 +188,33 @@
- }
-
-
--void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset) {
-+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));
-+ } else {
-+ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
-+ movl(reg, Address(rsi, bcp_offset));
-+ assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
-+ notl(reg); // convert to plain index
-+ }
-+}
-+
-+
-+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));
-+ get_cache_index_at_bcp(index, bcp_offset, giant_index);
- movl(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
- assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
- shll(index, 2); // convert from field index to ConstantPoolCacheEntry index
- }
-
-
--void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) {
-- assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
-+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));
-+ 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
-@@ -587,13 +600,18 @@
+@@ -587,13 +587,18 @@
}
@@ -2140,53 +1886,13 @@ diff --git a/src/cpu/x86/vm/interp_masm_
if (JvmtiExport::can_post_interpreter_events()) {
Label run_compiled_code;
-@@ -1236,7 +1254,9 @@
- }
-
-
--void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp, Register reg2) {
-+void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp,
-+ Register reg2,
-+ bool receiver_can_be_null) {
- if (ProfileInterpreter) {
- Label profile_continue;
-
-@@ -1246,8 +1266,15 @@
- // We are making a call. Increment the count.
- increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
-
-+ Label skip_receiver_profile;
-+ if (receiver_can_be_null) {
-+ testptr(receiver, receiver);
-+ jcc(Assembler::zero, skip_receiver_profile);
-+ }
-+
- // Record the receiver type.
- record_klass_in_profile(receiver, mdp, reg2);
-+ bind(skip_receiver_profile);
-
- // The method data pointer needs to be updated to reflect the new target.
- update_mdp_by_constant(mdp,
diff --git a/src/cpu/x86/vm/interp_masm_x86_32.hpp b/src/cpu/x86/vm/interp_masm_x86_32.hpp
--- a/src/cpu/x86/vm/interp_masm_x86_32.hpp
+++ b/src/cpu/x86/vm/interp_masm_x86_32.hpp
-@@ -76,8 +76,9 @@
- void get_cpool_and_tags(Register cpool, Register tags) { get_constant_pool(cpool); movl(tags, Address(cpool, constantPoolOopDesc::tags_offset_in_bytes()));
- }
- void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
-- void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset);
-- void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset);
-+ void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, bool giant_index = false);
-+ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
-+ void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false);
-
- // Expression stack
- void f2ieee(); // truncate ftos to 32bits
-@@ -103,6 +104,15 @@
-
+@@ -104,6 +104,15 @@
void pop(TosState state); // transition vtos -> state
void push(TosState state); // transition state -> vtos
-+
+
+ void pop(Register r ) { ((MacroAssembler*)this)->pop(r); }
+
+ void push(Register r ) { ((MacroAssembler*)this)->push(r); }
@@ -2195,10 +1901,11 @@ diff --git a/src/cpu/x86/vm/interp_masm_
+ // These are dummies to prevent surprise implicit conversions to Register
+ void pop(void* v ); // Add unimplemented ambiguous method
+ void push(void* v ); // Add unimplemented ambiguous method
-
++
DEBUG_ONLY(void verify_stack_tag(frame::Tag t);)
-@@ -152,6 +162,7 @@
+ #ifndef CC_INTERP
+@@ -152,6 +161,7 @@
// jump to an invoked target
@@ -2206,65 +1913,10 @@ diff --git a/src/cpu/x86/vm/interp_masm_
void jump_from_interpreted(Register method, Register temp);
// Returning from interpreted functions
-@@ -216,7 +227,8 @@
- void profile_not_taken_branch(Register mdp);
- void profile_call(Register mdp);
- void profile_final_call(Register mdp);
-- void profile_virtual_call(Register receiver, Register mdp, Register scratch2);
-+ void profile_virtual_call(Register receiver, Register mdp, Register scratch2,
-+ bool receiver_can_be_null = false);
- void profile_ret(Register return_bci, Register mdp);
- void profile_null_seen(Register mdp);
- void profile_typecheck(Register mdp, Register klass, Register scratch);
diff --git a/src/cpu/x86/vm/interp_masm_x86_64.cpp b/src/cpu/x86/vm/interp_masm_x86_64.cpp
--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp
+++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp
-@@ -186,12 +186,27 @@
- }
-
-
-+void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
-+ int bcp_offset,
-+ 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));
-+ } else {
-+ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
-+ movl(index, Address(r13, bcp_offset));
-+ assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
-+ notl(index); // convert to plain index
-+ }
-+}
-+
-+
- void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
- Register index,
-- int bcp_offset) {
-- assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
-+ int bcp_offset,
-+ bool giant_index) {
- assert(cache != index, "must use different registers");
-- load_unsigned_word(index, Address(r13, bcp_offset));
-+ get_cache_index_at_bcp(index, bcp_offset, giant_index);
- movq(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
- assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
- // convert from field index to ConstantPoolCacheEntry index
-@@ -201,10 +216,10 @@
-
- void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
- Register tmp,
-- int bcp_offset) {
-- assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
-+ int bcp_offset,
-+ bool giant_index) {
- assert(cache != tmp, "must use different register");
-- load_unsigned_word(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
-@@ -601,13 +616,18 @@
+@@ -601,13 +601,18 @@
MacroAssembler::call_VM_leaf_base(entry_point, 3);
}
@@ -2287,53 +1939,13 @@ diff --git a/src/cpu/x86/vm/interp_masm_
if (JvmtiExport::can_post_interpreter_events()) {
Label run_compiled_code;
-@@ -1276,7 +1296,8 @@
-
- void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
- Register mdp,
-- Register reg2) {
-+ Register reg2,
-+ bool receiver_can_be_null) {
- if (ProfileInterpreter) {
- Label profile_continue;
-
-@@ -1286,8 +1307,15 @@
- // We are making a call. Increment the count.
- increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
-
-+ Label skip_receiver_profile;
-+ if (receiver_can_be_null) {
-+ testptr(receiver, receiver);
-+ jcc(Assembler::zero, skip_receiver_profile);
-+ }
-+
- // Record the receiver type.
- record_klass_in_profile(receiver, mdp, reg2);
-+ bind(skip_receiver_profile);
-
- // The method data pointer needs to be updated to reflect the new target.
- update_mdp_by_constant(mdp,
diff --git a/src/cpu/x86/vm/interp_masm_x86_64.hpp b/src/cpu/x86/vm/interp_masm_x86_64.hpp
--- a/src/cpu/x86/vm/interp_masm_x86_64.hpp
+++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp
-@@ -94,9 +94,10 @@
-
- void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
- void get_cache_and_index_at_bcp(Register cache, Register index,
-- int bcp_offset);
-+ int bcp_offset, bool giant_index = false);
- void get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
-- int bcp_offset);
-+ int bcp_offset, bool giant_index = false);
-+ void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false);
-
- void pop_ptr(Register r = rax);
- void pop_i(Register r = rax);
-@@ -111,6 +112,15 @@
-
+@@ -112,6 +112,15 @@
void pop(TosState state); // transition vtos -> state
void push(TosState state); // transition state -> vtos
-+
+
+ void pop(Register r ) { ((MacroAssembler*)this)->pop(r); }
+
+ void push(Register r ) { ((MacroAssembler*)this)->push(r); }
@@ -2342,10 +1954,11 @@ diff --git a/src/cpu/x86/vm/interp_masm_
+ // These are dummies to prevent surprise implicit conversions to Register
+ void pop(void* v ); // Add unimplemented ambiguous method
+ void push(void* v ); // Add unimplemented ambiguous method
-
++
// Tagged stack support, pop and push both tag and value.
void pop_ptr(Register r, Register tag);
-@@ -166,6 +176,7 @@
+ void push_ptr(Register r, Register tag);
+@@ -166,6 +175,7 @@
void dispatch_via (TosState state, address* table);
// jump to an invoked target
@@ -2353,16 +1966,6 @@ diff --git a/src/cpu/x86/vm/interp_masm_
void jump_from_interpreted(Register method, Register temp);
-@@ -222,7 +233,8 @@
- void profile_call(Register mdp);
- void profile_final_call(Register mdp);
- void profile_virtual_call(Register receiver, Register mdp,
-- Register scratch2);
-+ Register scratch2,
-+ bool receiver_can_be_null = false);
- void profile_ret(Register return_bci, Register mdp);
- void profile_null_seen(Register mdp);
- void profile_typecheck(Register mdp, Register klass, Register scratch);
diff --git a/src/cpu/x86/vm/interpreterGenerator_x86.hpp b/src/cpu/x86/vm/interpreterGenerator_x86.hpp
--- a/src/cpu/x86/vm/interpreterGenerator_x86.hpp
+++ b/src/cpu/x86/vm/interpreterGenerator_x86.hpp
@@ -2928,10 +2531,11 @@ 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
-@@ -92,6 +92,43 @@
+@@ -91,6 +91,43 @@
+ rax);
return entry;
}
-
++
+#ifdef ASSERT
+address last_WrongMethodType_caller;
+#endif //ASSERT
@@ -2968,178 +2572,10 @@ diff --git a/src/cpu/x86/vm/templateInte
+ return entry;
+}
+
-+
+
address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) {
assert(!pass_oop || message == NULL, "either oop or message but not both");
- address entry = __ pc();
-@@ -129,13 +166,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 (unbox) {
-+ incoming_state = atos;
-+ }
-+ } else {
-+ assert(!unbox, "old behavior");
-+ }
-+
- Label interpreter_entry;
- address compiled_entry = __ pc();
-
- #ifdef COMPILER2
- // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases
-- if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) {
-+ if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) {
- for (int i = 1; i < 8; i++) {
- __ ffree(i);
- }
-@@ -143,7 +189,7 @@
- __ empty_FPU_stack();
- }
- #endif
-- if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) {
-+ if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) {
- __ MacroAssembler::verify_FPU(1, "generate_return_entry_for compiled");
- } else {
- __ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled");
-@@ -159,12 +205,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.
-- if (state == ftos && UseSSE >= 1) {
-+ if (incoming_state == ftos && UseSSE >= 1) {
- __ subl(rsp, wordSize);
- __ movflt(Address(rsp, 0), xmm0);
- __ fld_s(Address(rsp, 0));
- __ addl(rsp, wordSize);
-- } else if (state == dtos && UseSSE >= 2) {
-+ } else if (incoming_state == dtos && UseSSE >= 2) {
- __ subl(rsp, 2*wordSize);
- __ movdbl(Address(rsp, 0), xmm0);
- __ fld_d(Address(rsp, 0));
-@@ -180,13 +226,116 @@
-
- __ restore_bcp();
- __ restore_locals();
-- __ get_cache_and_index_at_bcp(rbx, rcx, 1);
-+
-+ Label L_fail;
-+
-+ if (unbox && state != atos) {
-+ // cast and unbox
-+ BasicType type = as_BasicType(state);
-+ if (type == T_BYTE) type = T_BOOLEAN; // FIXME
-+ KlassHandle boxk = KlassHandles::box_klass(type);
-+ __ mov32(rbx, ExternalAddress((address) boxk.raw_value()));
-+ __ testl(rax, rax);
-+ Label L_got_value, L_get_value;
-+ // convert nulls to zeroes (avoid NPEs here)
-+ if (!(type == T_FLOAT || type == T_DOUBLE)) {
-+ // if rax already contains zero bits, forge ahead
-+ __ jcc(Assembler::zero, L_got_value);
-+ } else {
-+ __ jcc(Assembler::notZero, L_get_value);
-+ __ fldz();
-+ __ jmp(L_got_value);
-+ }
-+ __ bind(L_get_value);
-+ __ cmp32(rbx, Address(rax, oopDesc::klass_offset_in_bytes()));
-+ __ jcc(Assembler::notEqual, L_fail);
-+ int offset = java_lang_boxing_object::value_offset_in_bytes(type);
-+ // 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;
-+ // 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;
-+ default: ShouldNotReachHere();
-+ }
-+ __ bind(L_got_value);
-+
-+ // put FPU results into xmm0, as above:
-+ if (state == ftos && UseSSE >= 1) {
-+ __ subl(rsp, wordSize);
-+ __ movflt(Address(rsp, 0), xmm0);
-+ __ fld_s(Address(rsp, 0));
-+ __ addl(rsp, wordSize);
-+ } else if (state == dtos && UseSSE >= 2) {
-+ __ subl(rsp, 2*wordSize);
-+ __ movdbl(Address(rsp, 0), xmm0);
-+ __ fld_d(Address(rsp, 0));
-+ __ addl(rsp, 2*wordSize);
-+ }
-+ }
-+
-+ Label L_got_cache, L_giant_index;
-+ if (InvokeDynamic) {
-+ __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic);
-+ __ jcc(Assembler::equal, L_giant_index);
-+ }
-+ __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
-+ __ bind(L_got_cache);
-+ if (unbox && state == atos) {
-+ // insert a casting conversion, to keep verifier sane
-+ Label L_ok, L_ok_pops;
-+ __ 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(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(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);
-+ __ jmp(L_fail);
-+
-+ __ bind(L_ok_pops);
-+ // restore pushed temp regs:
-+ __ pop(rcx);
-+ __ pop(rbx);
-+ __ pop(rax);
-+ __ bind(L_ok);
-+ }
- __ movl(rbx, Address(rbx, rcx,
- Address::times_4, constantPoolCacheOopDesc::base_offset() +
- ConstantPoolCacheEntry::flags_offset()));
- __ andl(rbx, 0xFF);
- __ leal(rsp, Address(rsp, rbx, Interpreter::stackElementScale()));
- __ dispatch_next(state, step);
-+
-+ // out of the main line of code...
-+ if (InvokeDynamic) {
-+ __ bind(L_giant_index);
-+ __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
-+ __ jmp(L_got_cache);
-+
-+ if (unbox) {
-+ __ bind(L_fail);
-+ __ push(rbx); // missed klass (required)
-+ __ push(rax); // bad object (actual)
-+ __ movptr(rdx, ExternalAddress((address) &Interpreter::_throw_WrongMethodType_entry));
-+ __ call(rdx);
-+ }
-+ }
-+
- return entry;
- }
-
-@@ -1364,6 +1513,7 @@
+@@ -1364,6 +1401,7 @@
case Interpreter::empty : entry_point = ((InterpreterGenerator*)this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*)this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*)this)->generate_abstract_entry(); break;
@@ -3147,7 +2583,7 @@ diff --git a/src/cpu/x86/vm/templateInte
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
-@@ -1394,9 +1544,10 @@
+@@ -1394,9 +1432,10 @@
// be sure to change this if you add/subtract anything to/from the overhead area
const int overhead_size = -frame::interpreter_frame_initial_sp_offset;
@@ -3163,10 +2599,13 @@ 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
-@@ -98,6 +98,36 @@
- return entry;
- }
-
+@@ -95,6 +95,36 @@
+ InterpreterRuntime::
+ throw_ClassCastException),
+ c_rarg1);
++ return entry;
++}
++
+#ifdef ASSERT
+address last_WrongMethodType_caller;
+#endif //ASSERT
@@ -3194,60 +2633,10 @@ diff --git a/src/cpu/x86/vm/templateInte
+ throw_WrongMethodTypeException),
+ // pass required type, failing object (or NULL)
+ c_rarg1, c_rarg2);
-+ return entry;
-+}
-+
- address TemplateInterpreterGenerator::generate_exception_handler_common(
- const char* name, const char* message, bool pass_oop) {
- assert(!pass_oop || message == NULL, "either oop or message but not both");
-@@ -144,7 +174,17 @@
-
-
- address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
-- int step) {
-+ int step,
-+ bool unbox) {
-+ TosState incoming_state = state;
-+ if (InvokeDynamic) {
-+ if (unbox) {
-+ incoming_state = atos;
-+ }
-+ Unimplemented();
-+ } else {
-+ assert(!unbox, "old behavior");
-+ }
-
- // amd64 doesn't need to do anything special about compiled returns
- // to the interpreter so the code that exists on x86 to place a sentinel
-@@ -159,7 +199,13 @@
-
- __ restore_bcp();
- __ restore_locals();
-- __ get_cache_and_index_at_bcp(rbx, rcx, 1);
-+ Label L_got_cache, L_giant_index;
-+ if (InvokeDynamic) {
-+ __ cmpb(Address(r13, 0), Bytecodes::_invokedynamic);
-+ __ jcc(Assembler::equal, L_giant_index);
-+ }
-+ __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
-+ __ bind(L_got_cache);
- __ movl(rbx, Address(rbx, rcx,
- Address::times_8,
- in_bytes(constantPoolCacheOopDesc::base_offset()) +
-@@ -168,6 +214,12 @@
- if (TaggedStackInterpreter) __ shll(rbx, 1); // 2 slots per parameter.
- __ leaq(rsp, Address(rsp, rbx, Address::times_8));
- __ dispatch_next(state, step);
-+
-+ if (InvokeDynamic) {
-+ __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
-+ __ jmp(L_got_cache);
-+ }
-+
return entry;
}
-@@ -1243,6 +1295,7 @@
+@@ -1243,6 +1273,7 @@
case Interpreter::empty : entry_point = ((InterpreterGenerator*) this)->generate_empty_entry(); break;
case Interpreter::accessor : entry_point = ((InterpreterGenerator*) this)->generate_accessor_entry(); break;
case Interpreter::abstract : entry_point = ((InterpreterGenerator*) this)->generate_abstract_entry(); break;
@@ -3255,7 +2644,7 @@ diff --git a/src/cpu/x86/vm/templateInte
case Interpreter::java_lang_math_sin : break;
case Interpreter::java_lang_math_cos : break;
case Interpreter::java_lang_math_tan : break;
-@@ -1272,7 +1325,8 @@
+@@ -1272,7 +1303,8 @@
-(frame::interpreter_frame_initial_sp_offset) + entry_size;
const int stub_code = frame::entry_frame_after_call_words;
@@ -3268,172 +2657,7 @@ diff --git a/src/cpu/x86/vm/templateTabl
diff --git a/src/cpu/x86/vm/templateTable_x86_32.cpp b/src/cpu/x86/vm/templateTable_x86_32.cpp
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp
+++ b/src/cpu/x86/vm/templateTable_x86_32.cpp
-@@ -132,12 +132,12 @@
- __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, rsi, bc);
- #ifndef ASSERT
- __ jmpb(patch_done);
-+#else
-+ __ jmp(patch_done);
-+#endif
- __ bind(fast_patch);
- }
--#else
-- __ jmp(patch_done);
-- __ bind(fast_patch);
-- }
-+#ifdef ASSERT
- Label okay;
- __ load_unsigned_byte(scratch, at_bcp(0));
- __ cmpl(scratch, (int)Bytecodes::java_code(bytecode));
-@@ -2015,6 +2015,7 @@
-
- void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) {
- assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
-+ bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
-
- Register temp = rbx;
-
-@@ -2022,13 +2023,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()));
-- __ shrl(temp, shift_count);
-- // have we resolved this bytecode?
-- __ andl(temp, 0xFF);
-- __ cmpl(temp, (int)bytecode());
-- __ jcc(Assembler::equal, resolved);
-+ __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
-+ if (is_invokedynamic) {
-+ // we are resolved if the f1 field contains a non-null CallSite object
-+ __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
-+ __ jcc(Assembler::notEqual, resolved);
-+ } else {
-+ __ movl(temp, Address(Rcache, index, Address::times_4, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
-+ __ shrl(temp, shift_count);
-+ // have we resolved this bytecode?
-+ __ andl(temp, 0xFF);
-+ __ cmpl(temp, (int)bytecode());
-+ __ jcc(Assembler::equal, resolved);
-+ }
-
- // resolve first time through
- address entry;
-@@ -2041,12 +2048,13 @@
- case Bytecodes::_invokespecial : // fall through
- case Bytecodes::_invokestatic : // fall through
- case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
-+ case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
- default : ShouldNotReachHere(); break;
- }
- __ movl(temp, (int)bytecode());
- __ call_VM(noreg, entry, temp);
- // Update registers with resolved info
-- __ get_cache_and_index_at_bcp(Rcache, index, 1);
-+ __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
- __ bind(resolved);
- }
-
-@@ -2761,9 +2769,14 @@
- }
-
-
--void TemplateTable::prepare_invoke(Register method, Register index, int byte_no, Bytecodes::Code code) {
-+void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) {
-+ bool neg_byte_no = (byte_no < 0);
-+ if (neg_byte_no) byte_no = -byte_no;
-+
- // determine flags
-+ Bytecodes::Code code = bytecode();
- const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
-+ const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
- const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
- const bool is_invokespecial = code == Bytecodes::_invokespecial;
- const bool load_receiver = code != Bytecodes::_invokestatic;
-@@ -2773,6 +2786,9 @@
- const Register recv = rcx;
- 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();
-@@ -2784,8 +2800,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)));
-- __ verify_oop(recv);
-+ Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1));
-+ if (is_invokedynamic) {
-+ __ lea(recv, recv_addr);
-+ } else {
-+ __ movptr(recv, recv_addr);
-+ __ verify_oop(recv);
-+ }
- }
-
- // do null check if needed
-@@ -2802,11 +2823,14 @@
- // Make sure we don't need to mask flags for tosBits after the above shift
- 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));
-+ {
-+ address table =
-+ (is_invdyn_bootstrap)
-+ ? (address)Interpreter::return_5_unbox_addrs_by_index_table()
-+ : (is_invokeinterface || is_invokedynamic)
-+ ? (address)Interpreter::return_5_addrs_by_index_table()
-+ : (address)Interpreter::return_3_addrs_by_index_table();
-+ __ movl(flags, Address(noreg, flags, Address::times_4, (int)table));
- }
-
- // push return address
-@@ -2868,7 +2892,7 @@
-
- void TemplateTable::invokevirtual(int byte_no) {
- transition(vtos, vtos);
-- prepare_invoke(rbx, noreg, byte_no, bytecode());
-+ prepare_invoke(rbx, noreg, byte_no);
-
- // rbx,: index
- // rcx: receiver
-@@ -2880,7 +2904,7 @@
-
- void TemplateTable::invokespecial(int byte_no) {
- transition(vtos, vtos);
-- prepare_invoke(rbx, noreg, byte_no, bytecode());
-+ prepare_invoke(rbx, noreg, byte_no);
- // do the call
- __ verify_oop(rbx);
- __ profile_call(rax);
-@@ -2890,7 +2914,7 @@
-
- void TemplateTable::invokestatic(int byte_no) {
- transition(vtos, vtos);
-- prepare_invoke(rbx, noreg, byte_no, bytecode());
-+ prepare_invoke(rbx, noreg, byte_no);
- // do the call
- __ verify_oop(rbx);
- __ profile_call(rax);
-@@ -2906,7 +2930,7 @@
-
- void TemplateTable::invokeinterface(int byte_no) {
- transition(vtos, vtos);
-- prepare_invoke(rax, rbx, byte_no, bytecode());
-+ prepare_invoke(rax, rbx, byte_no);
-
- // rax,: Interface
- // rbx,: index
-@@ -2932,6 +2956,57 @@
+@@ -2932,6 +2932,57 @@
// profile this call
__ profile_virtual_call(rdx, rsi, rdi);
@@ -3491,292 +2715,13 @@ diff --git a/src/cpu/x86/vm/templateTabl
__ movl(rdi, rdx); // Save klassOop in rdi
-@@ -3005,6 +3080,79 @@
- // rcx: receiver
- // rbx,: methodOop
- __ jump_from_interpreted(rbx, rdx);
-+}
-+
-+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");
-+ return;
-+ }
-+
-+ prepare_invoke(rax, rbx, byte_no);
-+
-+ // rax: CallSite object (f1)
-+ // rbx: unused (f2)
-+ // rcx: receiver address
-+ // rdx: flags (unused)
-+
-+ if (ProfileInterpreter) {
-+ Label L;
-+ __ movl(rdx, Address(rcx, 0));
-+ __ testl(rdx, rdx);
-+ __ jcc(Assembler::zero, L);
-+
-+ // Get receiver klass into rdx
-+ __ movl(rdx, Address(rdx, oopDesc::klass_offset_in_bytes()));
-+ __ verify_oop(rdx);
-+ __ bind(L);
-+
-+ // profile this call
-+ __ profile_virtual_call(rdx, rsi, rdi, true);
-+ }
-+
-+ Label handle_unlinked_site;
-+ __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_impl_DynCallSite::target_offset_in_bytes, rcx)));
-+ __ testptr(rcx, rcx);
-+ __ jcc(Assembler::zero, handle_unlinked_site);
-+
-+ __ prepare_to_jump_from_interpreted();
-+ __ jump_to_method_handle_entry(rcx, rdx);
-+
-+ // Initial calls come here...
-+ __ bind(handle_unlinked_site);
-+ __ pop(rcx); // remove return address pushed by prepare_invoke
-+
-+ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic);
-+ // squish stacked arguments together on stack, preceded by call site
-+ // return bootstrap method as a handle in rcx
-+ __ restore_bcp(); // rsi must be correct for call_VM
-+ __ call_VM(rax, entry, rax);
-+ __ movl(rdi, rax); // protect MH from prepare_invoke
-+
-+ // recompute return address
-+ __ restore_bcp(); // rsi must be correct for prepare_invoke
-+ prepare_invoke(rax, rbx, -byte_no);
-+ // rax: CallSite object (f1)
-+ // rbx: unused (f2)
-+ // rcx: receiver address (now holds arglist)
-+ // rdx: flags
-+
-+ // save SP now, before we add the bootstrap call to the stack
-+ __ prepare_to_jump_from_interpreted();
-+
-+ // let's play adapter
-+ __ pop(rbx); // return value
-+ __ push(rdi); // boot MH
-+ __ push(rax); // call site
-+ __ movptr(rcx, Address(rcx, 0));
-+ __ push(rcx); // arglist
-+ __ push(rbx); // return value
-+ __ mov(rcx, rdi);
-+ __ jump_to_method_handle_entry(rcx, rdx);
- }
-
- //----------------------------------------------------------------------------------------------------
-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
-@@ -22,8 +22,7 @@
- *
- */
-
-- static void prepare_invoke(Register method, Register index, int byte_no,
-- Bytecodes::Code code);
-+ static void prepare_invoke(Register method, Register index, int byte_no);
- static void invokevirtual_helper(Register index, Register recv,
- Register flags);
- static void volatile_barrier( );
diff --git a/src/cpu/x86/vm/templateTable_x86_64.cpp b/src/cpu/x86/vm/templateTable_x86_64.cpp
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp
+++ b/src/cpu/x86/vm/templateTable_x86_64.cpp
-@@ -144,12 +144,12 @@
- scratch, r13, bc);
- #ifndef ASSERT
- __ jmpb(patch_done);
-+#else
-+ __ jmp(patch_done);
-+#endif
- __ bind(fast_patch);
- }
--#else
-- __ jmp(patch_done);
-- __ bind(fast_patch);
-- }
-+#ifdef ASSERT
- Label okay;
- __ load_unsigned_byte(scratch, at_bcp(0));
- __ cmpl(scratch, (int) Bytecodes::java_code(bytecode));
-@@ -1989,6 +1989,7 @@
- Register Rcache,
- Register index) {
- assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
-+ bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
-
- const Register temp = rbx;
- assert_different_registers(Rcache, index, temp);
-@@ -1996,19 +1997,29 @@
- 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_8,
-- constantPoolCacheOopDesc::base_offset() +
-- ConstantPoolCacheEntry::indices_offset()));
-- __ shrl(temp, shift_count);
-- // have we resolved this bytecode?
-- __ andl(temp, 0xFF);
-- __ cmpl(temp, (int) bytecode());
-- __ jcc(Assembler::equal, resolved);
-+ if (is_invokedynamic) {
-+ // we are resolved if the f1 field contains a non-null CallSite object
-+ __ cmpptr(Address(Rcache,
-+ index, Address::times_ptr,
-+ constantPoolCacheOopDesc::base_offset() +
-+ ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
-+ __ jcc(Assembler::notEqual, resolved);
-+ } else {
-+ __ 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);
-+ __ cmpl(temp, (int) bytecode());
-+ __ jcc(Assembler::equal, resolved);
-+ }
-
- // resolve first time through
- address entry;
-- switch (bytecode()) {
-+ Bytecodes::Code code = Bytecodes::java_code(bytecode());
-+ switch (code) {
- case Bytecodes::_getstatic:
- case Bytecodes::_putstatic:
- case Bytecodes::_getfield:
-@@ -2021,6 +2032,9 @@
- case Bytecodes::_invokeinterface:
- entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
- break;
-+ case Bytecodes::_invokedynamic:
-+ entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
-+ break;
- default:
- ShouldNotReachHere();
- break;
-@@ -2029,7 +2043,7 @@
- __ call_VM(noreg, entry, temp);
-
- // Update registers with resolved info
-- __ get_cache_and_index_at_bcp(Rcache, index, 1);
-+ __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
- __ bind(resolved);
- }
-
-@@ -2764,10 +2778,14 @@
-
- void TemplateTable::prepare_invoke(Register method,
- Register index,
-- int byte_no,
-- Bytecodes::Code code) {
-+ int byte_no) {
-+ bool neg_byte_no = (byte_no < 0);
-+ if (neg_byte_no) byte_no = -byte_no;
-+
- // determine flags
-+ Bytecodes::Code code = bytecode();
- const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
-+ const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
- const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
- const bool is_invokespecial = code == Bytecodes::_invokespecial;
- const bool load_receiver = code != Bytecodes::_invokestatic;
-@@ -2777,6 +2795,9 @@
- const Register recv = rcx;
- 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();
-@@ -2788,9 +2809,14 @@
- __ movl(recv, flags);
- __ andl(recv, 0xFF);
- if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
-- __ movq(recv, Address(rsp, recv, Address::times_8,
-- -Interpreter::expr_offset_in_bytes(1)));
-- __ verify_oop(recv);
-+ Address recv_addr(rsp, recv, Address::times_8,
-+ -Interpreter::expr_offset_in_bytes(1));
-+ if (is_invokedynamic) {
-+ __ lea(recv, recv_addr);
-+ } else {
-+ __ movptr(recv, recv_addr);
-+ __ verify_oop(recv);
-+ }
- }
-
- // do null check if needed
-@@ -2808,10 +2834,15 @@
- ConstantPoolCacheEntry::verify_tosBits();
- // load return address
- {
-- 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));
-+ address table_addr =
-+ (is_invdyn_bootstrap)
-+ ? (address)Interpreter::return_5_unbox_addrs_by_index_table()
-+ : (is_invokeinterface || is_invokedynamic)
-+ ? (address)Interpreter::return_5_addrs_by_index_table()
-+ : (address)Interpreter::return_3_addrs_by_index_table();
-+ ExternalAddress table(table_addr);
-+ __ lea(rscratch1, table);
-+ __ movptr(flags, Address(rscratch1, flags, Address::times_ptr));
- }
-
- // push return address
-@@ -2877,7 +2908,7 @@
-
- void TemplateTable::invokevirtual(int byte_no) {
- transition(vtos, vtos);
-- prepare_invoke(rbx, noreg, byte_no, bytecode());
-+ prepare_invoke(rbx, noreg, byte_no);
-
- // rbx: index
- // rcx: receiver
-@@ -2889,7 +2920,7 @@
-
- void TemplateTable::invokespecial(int byte_no) {
- transition(vtos, vtos);
-- prepare_invoke(rbx, noreg, byte_no, bytecode());
-+ prepare_invoke(rbx, noreg, byte_no);
- // do the call
- __ verify_oop(rbx);
- __ profile_call(rax);
-@@ -2899,7 +2930,7 @@
-
- void TemplateTable::invokestatic(int byte_no) {
- transition(vtos, vtos);
-- prepare_invoke(rbx, noreg, byte_no, bytecode());
-+ prepare_invoke(rbx, noreg, byte_no);
- // do the call
- __ verify_oop(rbx);
- __ profile_call(rax);
-@@ -2913,7 +2944,7 @@
-
- void TemplateTable::invokeinterface(int byte_no) {
- transition(vtos, vtos);
-- prepare_invoke(rax, rbx, byte_no, bytecode());
-+ prepare_invoke(rax, rbx, byte_no);
-
- // rax: Interface
- // rbx: index
-@@ -2939,6 +2970,57 @@
-
+@@ -2940,6 +2940,57 @@
// profile this call
__ profile_virtual_call(rdx, r13, r14);
-+
+
+ if (MethodHandles) { // %%% let's use this refactored code always
+ Label no_such_interface, no_such_method;
+
@@ -3827,102 +2772,10 @@ diff --git a/src/cpu/x86/vm/templateTabl
+ }
+
+ // %%% remove this old code, in favor of the previous block:
-
++
__ movq(r14, rdx); // Save klassOop in r14
-@@ -3029,6 +3111,79 @@
- // rcx: receiver
- // rbx: methodOop
- __ jump_from_interpreted(rbx, rdx);
-+}
-+
-+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");
-+ return;
-+ }
-+
-+ prepare_invoke(rax, rbx, byte_no);
-+
-+ // rax: CallSite object (f1)
-+ // rbx: unused (f2)
-+ // rcx: receiver address
-+ // rdx: flags (unused)
-+
-+ if (ProfileInterpreter) {
-+ Label L;
-+ __ movl(rdx, Address(rcx, 0));
-+ __ testl(rdx, rdx);
-+ __ jcc(Assembler::zero, L);
-+
-+ // Get receiver klass into rdx
-+ __ movl(rdx, Address(rdx, oopDesc::klass_offset_in_bytes()));
-+ __ verify_oop(rdx);
-+ __ bind(L);
-+
-+ // profile this call
-+ __ profile_virtual_call(rdx, r13, r14, true);
-+ }
-+
-+ Label handle_unlinked_site;
-+ __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_impl_DynCallSite::target_offset_in_bytes, rcx)));
-+ __ testptr(rcx, rcx);
-+ __ jcc(Assembler::zero, handle_unlinked_site);
-+
-+ __ prepare_to_jump_from_interpreted();
-+ __ jump_to_method_handle_entry(rcx, rdx);
-+
-+ // Initial calls come here...
-+ __ bind(handle_unlinked_site);
-+ __ pop(rcx); // remove return address pushed by prepare_invoke
-+
-+ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic);
-+ // squish stacked arguments together on stack, preceded by call site
-+ // return bootstrap method as a handle in rcx
-+ __ restore_bcp(); // rsi must be correct for call_VM
-+ __ call_VM(rax, entry, rax);
-+ __ movl(rdi, rax); // protect MH from prepare_invoke
-+
-+ // recompute return address
-+ __ restore_bcp(); // rsi must be correct for prepare_invoke
-+ prepare_invoke(rax, rbx, -byte_no);
-+ // rax: CallSite object (f1)
-+ // rbx: unused (f2)
-+ // rcx: receiver address (now holds arglist)
-+ // rdx: flags
-+
-+ // save SP now, before we add the bootstrap call to the stack
-+ __ prepare_to_jump_from_interpreted();
-+
-+ // let's play adapter
-+ __ pop(rbx); // return value
-+ __ push(rdi); // boot MH
-+ __ push(rax); // call site
-+ __ movptr(rcx, Address(rcx, 0));
-+ __ push(rcx); // arglist
-+ __ push(rbx); // return value
-+ __ mov(rcx, rdi);
-+ __ jump_to_method_handle_entry(rcx, rdx);
- }
-
- //-----------------------------------------------------------------------------
-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
-@@ -22,8 +22,7 @@
- *
- */
-
-- static void prepare_invoke(Register method, Register index, int byte_no,
-- Bytecodes::Code code);
-+ static void prepare_invoke(Register method, Register index, int byte_no);
- static void invokevirtual_helper(Register index, Register recv,
- Register flags);
- static void volatile_barrier(Assembler::Membar_mask_bits order_constraint);
+ // Compute start of first itableOffsetEntry (which is at the end of
diff --git a/src/cpu/x86/vm/vtableStubs_x86_32.cpp b/src/cpu/x86/vm/vtableStubs_x86_32.cpp
--- a/src/cpu/x86/vm/vtableStubs_x86_32.cpp
+++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp
@@ -4164,49 +3017,10 @@ diff --git a/src/share/vm/asm/assembler.
// Bang stack to trigger StackOverflowError at a safe location
// implementation delegates to machine-specific bang_stack_with_offset
void generate_stack_overflow_check( int frame_size_in_bytes );
-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) {
- code = Bytecodes::_invokespecial;
-+ }
-+
-+ if (InvokeDynamic && 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 @@
- case Bytecodes::_invokespecial : // fall through
- case Bytecodes::_invokestatic : // fall through
- case Bytecodes::_invokeinterface: invoke(code); break;
-- case Bytecodes::_xxxunusedxxx : ShouldNotReachHere(); break;
- case Bytecodes::_new : new_instance(s.get_index_big()); break;
- case Bytecodes::_newarray : new_type_array(); break;
- case Bytecodes::_anewarray : new_object_array(); break;
-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();
- }
- }
-- break;
-- case Bytecodes::_xxxunusedxxx:
-- ShouldNotReachHere();
- 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
-@@ -675,6 +675,37 @@
+@@ -675,6 +675,30 @@
}
// ------------------------------------------------------------------
@@ -4232,13 +3046,6 @@ diff --git a/src/share/vm/ci/ciMethod.cp
+ 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
@@ -4247,121 +3054,15 @@ diff --git a/src/share/vm/ci/ciMethod.hp
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
-@@ -207,6 +207,9 @@
+@@ -207,6 +207,8 @@
bool check_call(int refinfo_index, bool is_static) const;
void build_method_data(); // make sure it exists in the VM also
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; }
-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
-@@ -303,7 +303,7 @@
- int ciBytecodeStream::get_method_index() {
- switch (cur_bc()) {
- case Bytecodes::_invokeinterface:
-- return Bytes::get_Java_u2(_pc-4);
-+ return get_index_int();
- case Bytecodes::_invokevirtual:
- case Bytecodes::_invokespecial:
- case Bytecodes::_invokestatic:
-diff --git a/src/share/vm/ci/ciStreams.hpp b/src/share/vm/ci/ciStreams.hpp
---- a/src/share/vm/ci/ciStreams.hpp
-+++ b/src/share/vm/ci/ciStreams.hpp
-@@ -91,11 +91,13 @@
- _end = _start + max;
- }
-
-- address cur_bcp() { return _bc_start; } // Returns bcp to current instruction
-+ address cur_bcp() const { return _bc_start; } // Returns bcp to current instruction
- int next_bci() const { return _pc -_start; }
- int cur_bci() const { return _bc_start - _start; }
-+ int instruction_size() const { return _pc - _bc_start; }
-
- Bytecodes::Code cur_bc() const{ return check_java(_bc); }
-+ Bytecodes::Code raw_cur_bc() const { return Bytecodes::raw_code_at(cur_bcp()); }
- 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 @@
- return check_java(_bc);
- }
-
-- bool is_wide() { return ( _pc == _was_wide ); }
-+ bool is_wide() const { return ( _pc == _was_wide ); }
-
- // Get a byte index following this bytecode.
- // If prefixed with a wide bytecode, get a wide index.
- int get_index() const {
-+ assert_index_size(is_wide() ? 2 : 1);
- return (_pc == _was_wide) // was widened?
- ? Bytes::get_Java_u2(_bc_start+2) // yes, return wide index
- : _bc_start[1]; // no, return narrow index
- }
-
-- // Set a byte index following this bytecode.
-- // If prefixed with a wide bytecode, get a wide index.
-- void put_index(int idx) {
-- if (_pc == _was_wide) // was widened?
-- Bytes::put_Java_u2(_bc_start+2,idx); // yes, set wide index
-- else
-- _bc_start[1]=idx; // no, set narrow index
-+ // Get 2-byte index (getfield/putstatic/etc)
-+ int get_index_big() const {
-+ assert_index_size(2);
-+ return Bytes::get_Java_u2(_bc_start+1);
- }
-
-- // Get 2-byte index (getfield/putstatic/etc)
-- int get_index_big() const { return Bytes::get_Java_u2(_bc_start+1); }
-+ // Get 2-byte index (or 4-byte, for invokedynamic)
-+ int get_index_int() const {
-+ return has_giant_index() ? get_index_giant() : get_index_big();
-+ }
-+
-+ // Get 4-byte index, for invokedynamic.
-+ int get_index_giant() const {
-+ assert_index_size(4);
-+ return Bytes::get_native_u4(_bc_start+1);
-+ }
-+
-+ bool has_giant_index() const { return (raw_cur_bc() == Bytecodes::_invokedynamic); }
-
- // 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]); }
-@@ -225,6 +232,22 @@
- ciKlass* get_declared_method_holder();
- int get_method_holder_index();
- int get_method_signature_index();
-+
-+ private:
-+ void assert_index_size(int required_size) const {
-+#ifdef ASSERT
-+ int isize = instruction_size() - (is_wide() ? 1 : 0) - 1;
-+ if (isize == 2 && raw_cur_bc() == Bytecodes::_iinc)
-+ isize = 1;
-+ else if (isize <= 2)
-+ ; // no change
-+ else if (has_giant_index())
-+ isize = 4;
-+ else
-+ isize = 2;
-+ assert(isize = required_size, "wrong index size");
-+#endif
-+ }
- };
-
-
diff --git a/src/share/vm/classfile/classFileParser.cpp b/src/share/vm/classfile/classFileParser.cpp
--- a/src/share/vm/classfile/classFileParser.cpp
+++ b/src/share/vm/classfile/classFileParser.cpp
@@ -4625,11 +3326,10 @@ diff --git a/src/share/vm/classfile/java
// Support for java_lang_ref_Reference
oop java_lang_ref_Reference::pending_list_lock() {
instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
-@@ -2016,6 +2044,207 @@
- int offset = ik->offset_of_static_fields() + static_clock_offset;
+@@ -2017,6 +2045,161 @@
SystemDictionary::soft_reference_klass()->long_field_put(offset, value);
-+}
+ }
+
+
+// Support for java_dyn_MethodHandle
@@ -4785,69 +3485,21 @@ diff --git a/src/share/vm/classfile/java
+}
+
+
-+// 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();
-+ 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();
-+ }
-+}
-+
-+oop java_dyn_impl_DynCallSite::type(oop site) {
-+ return site->obj_field(_type_offset);
-+}
-+
-+oop java_dyn_impl_DynCallSite::target(oop site) {
-+ return site->obj_field(_target_offset);
-+}
-+
-+void java_dyn_impl_DynCallSite::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);
-+}
-+
-+void java_dyn_impl_DynCallSite::set_vmref(oop site, oop ref) {
-+ site->obj_field_put(_vmref_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);
- }
-
-
-@@ -2354,6 +2583,13 @@
+
+
+ // Support for java_security_AccessControlContext
+@@ -2354,6 +2537,10 @@
java_lang_System::compute_offsets();
java_lang_Thread::compute_offsets();
java_lang_ThreadGroup::compute_offsets();
-+ if (MethodHandles || InvokeDynamic) {
++ if (MethodHandles) {
+ java_dyn_MethodHandle::compute_offsets();
+ java_dyn_MethodType::compute_offsets();
-+ }
-+ if (InvokeDynamic) {
-+ java_dyn_impl_DynCallSite::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
-@@ -2371,6 +2607,9 @@
+@@ -2371,6 +2558,9 @@
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
}
sun_misc_AtomicLongCSImpl::compute_offsets();
@@ -4869,7 +3521,7 @@ diff --git a/src/share/vm/classfile/java
static int value_offset_in_bytes(BasicType type) {
return ( type == T_LONG || type == T_DOUBLE ) ? long_value_offset :
-@@ -769,6 +771,141 @@
+@@ -769,6 +771,107 @@
};
@@ -4974,40 +3626,6 @@ diff --git a/src/share/vm/classfile/java
+};
+
+
-+// Interface to java.dyn.impl.DynCallSite objects
-+
-+class java_dyn_impl_DynCallSite: AllStatic {
-+ friend class JavaClasses;
-+
-+private:
-+ static int _type_offset;
-+ static int _target_offset;
-+ static int _vmref_offset;
-+ static int _vmdata_offset;
-+
-+ static void compute_offsets();
-+
-+public:
-+ // Accessors
-+ static oop type(oop site);
-+
-+ 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);
-+
-+ // 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; }
-+};
-+
-+
// Interface to java.security.AccessControlContext objects
class java_security_AccessControlContext: AllStatic {
@@ -5087,20 +3705,25 @@ diff --git a/src/share/vm/classfile/syst
}
-@@ -1883,6 +1898,12 @@
+@@ -1883,6 +1898,17 @@
instanceKlass::cast(WK_KLASS(weak_reference_klass))->set_reference_type(REF_WEAK);
instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
+
-+ initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(java_dyn_MethodHandle_klass), scan, CHECK);
-+ if (WK_KLASS(java_dyn_MethodHandle_klass) == NULL) {
-+ // Skip the rest of the dynamic typing classes, if MethodHandle is not found.
-+ scan = WKID(WK_KLASS_ENUM_NAME(java_dyn_Dynamic_klass)+1);
++ WKID meth_group_start = WK_KLASS_ENUM_NAME(java_dyn_MethodHandle_klass);
++ WKID meth_group_end = WK_KLASS_ENUM_NAME(java_dyn_WrongMethodTypeException_klass);
++ initialize_wk_klasses_until(meth_group_start, scan, CHECK);
++ if (MethodHandles) {
++ initialize_wk_klasses_through(meth_group_start, scan, CHECK);
++ }
++ if (_well_known_klasses[meth_group_start] == NULL) {
++ // Skip the rest of the method handle classes, if MethodHandle is not loaded.
++ scan = WKID(meth_group_end+1);
+ }
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
-@@ -1922,6 +1943,13 @@
+@@ -1922,6 +1948,13 @@
return (BasicType)i;
}
return T_OBJECT;
@@ -5114,7 +3737,7 @@ diff --git a/src/share/vm/classfile/syst
}
// Constraints on class loaders. The details of the algorithm can be
-@@ -2134,11 +2162,56 @@
+@@ -2134,11 +2167,56 @@
}
@@ -5172,7 +3795,7 @@ diff --git a/src/share/vm/classfile/syst
char* SystemDictionary::check_signature_loaders(symbolHandle signature,
Handle loader1, Handle loader2,
bool is_method, TRAPS) {
-@@ -2159,6 +2232,224 @@
+@@ -2159,6 +2237,91 @@
sig_strm.next();
}
return NULL;
@@ -5215,75 +3838,6 @@ diff --git a/src/share/vm/classfile/syst
+ methodOop m = (methodOop) spe->property_oop();
+ assert(m->is_method(), "");
+ return m;
-+}
-+
-+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 || !MethodHandles) 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();
-+ }
+}
+
+// Ask Java code to find or construct a java.dyn.MethodType for the given
@@ -5330,70 +3884,6 @@ diff --git a/src/share/vm/classfile/syst
+ vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(),
+ &args, CHECK_(empty));
+ return Handle(THREAD, (oop) result.get_jobject());
-+}
-+
-+
-+// 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,
-+ symbolHandle name,
-+ methodHandle mh_invdyn,
-+ jlong vmdata,
-+ TRAPS) {
-+ Handle empty;
-+ // call java.dyn.impl.DynCallSite::makeSite(caller, name, mtype, vmdata)
-+ 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);
-+ JavaValue result(T_OBJECT);
-+ JavaCalls::call_static(&result,
-+ SystemDictionary::dyn_impl_DynCallSite_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());
-+ return call_site_oop;
-+}
-+
-+Handle SystemDictionary::find_bootstrap_method(KlassHandle caller,
-+ KlassHandle search_bootstrap_klass,
-+ TRAPS) {
-+ Handle empty;
-+ if (!caller->oop_is_instance()) return empty;
-+
-+ instanceKlassHandle ik(THREAD, caller());
-+
-+ if (ik->bootstrap_method() != NULL) {
-+ return Handle(THREAD, ik->bootstrap_method());
-+ }
-+
-+ // call java.dyn.Linkage::findBootstrapMethod(caller, sbk)
-+ JavaCallArguments args(Handle(THREAD, ik->java_mirror()));
-+ if (search_bootstrap_klass.is_null())
-+ args.push_oop(Handle());
-+ else
-+ args.push_oop(search_bootstrap_klass->java_mirror());
-+ JavaValue result(T_OBJECT);
-+ JavaCalls::call_static(&result,
-+ SystemDictionary::java_dyn_Linkage_klass(),
-+ vmSymbols::findBootstrapMethod_name(),
-+ vmSymbols::findBootstrapMethod_signature(),
-+ &args, CHECK_(empty));
-+ oop boot_method_oop = (oop) result.get_jobject();
-+
-+ if (boot_method_oop != NULL) {
-+ // probably no race conditions, but let's be careful:
-+ if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL)
-+ ik->set_bootstrap_method(boot_method_oop);
-+ else
-+ boot_method_oop = ik->bootstrap_method();
-+ } else {
-+ boot_method_oop = ik->bootstrap_method();
-+ }
-+
-+ return Handle(THREAD, boot_method_oop);
}
@@ -5408,7 +3898,7 @@ diff --git a/src/share/vm/classfile/syst
// Certain classes are preloaded, such as java.lang.Object and java.lang.String.
// They are all "well-known", in the sense that no class loader is allowed
-@@ -131,6 +132,21 @@
+@@ -131,6 +132,15 @@
template(reflect_constant_pool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
template(reflect_unsafe_static_field_accessor_impl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
\
@@ -5421,16 +3911,10 @@ diff --git a/src/share/vm/classfile/syst
+ 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) \
-+ /* 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) \
-@@ -161,6 +177,7 @@
+@@ -161,6 +171,7 @@
class SystemDictionary : AllStatic {
friend class VMStructs;
friend class CompactingPermGenGen;
@@ -5438,18 +3922,13 @@ diff --git a/src/share/vm/classfile/syst
NOT_PRODUCT(friend class instanceKlassKlass;)
public:
-@@ -447,6 +464,36 @@
+@@ -447,6 +458,17 @@
static char* check_signature_loaders(symbolHandle signature, Handle loader1,
Handle loader2, bool is_method, TRAPS);
+ // JSR 292
+ // find the java.dyn.MethodHandle::invoke method for a given signature
+ static methodOop find_method_handle_invoke(symbolHandle signature,
-+ 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);
@@ -5458,24 +3937,10 @@ diff --git a/src/share/vm/classfile/syst
+ 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,
-+ symbolHandle name,
-+ methodHandle mh_invoke,
-+ jlong vmdata,
-+ TRAPS);
-+
-+ // coordinate with Java about bootstrap methods
-+ static Handle find_bootstrap_method(KlassHandle caller,
-+ // This argument is non-null only when a
-+ // classfile attribute has been found:
-+ KlassHandle search_bootstrap_klass,
-+ TRAPS);
-+
// Utility for printing loader "name" as part of tracing constraints
static const char* loader_name(oop loader) {
return ((loader) == NULL ? "<bootloader>" :
-@@ -463,6 +510,7 @@
+@@ -463,6 +485,7 @@
enum Constants {
_loader_constraint_size = 107, // number of entries in constraint table
_resolution_error_size = 107, // number of entries in resolution error table
@@ -5483,7 +3948,7 @@ diff --git a/src/share/vm/classfile/syst
_nof_buckets = 1009 // number of buckets in hash table
};
-@@ -492,6 +540,9 @@
+@@ -492,6 +515,9 @@
// Resolution errors
static ResolutionErrorTable* _resolution_errors;
@@ -5493,7 +3958,7 @@ diff --git a/src/share/vm/classfile/syst
public:
// for VM_CounterDecay iteration support
friend class CounterDecay;
-@@ -509,6 +560,7 @@
+@@ -509,6 +535,7 @@
static PlaceholderTable* placeholders() { return _placeholders; }
static LoaderConstraintTable* constraints() { return _loader_constraints; }
static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
@@ -5501,7 +3966,7 @@ diff --git a/src/share/vm/classfile/syst
// Basic loading operations
static klassOop resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
-@@ -598,3 +650,17 @@
+@@ -598,3 +625,17 @@
static bool _has_loadClassInternal;
static bool _has_checkPackageAccess;
};
@@ -5522,23 +3987,12 @@ diff --git a/src/share/vm/classfile/vmSy
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") \
-@@ -214,7 +215,32 @@
+@@ -214,7 +214,24 @@
template(sun_reflect_UnsafeStaticFieldAccessorImpl, "sun/reflect/UnsafeStaticFieldAccessorImpl")\
template(base_name, "base") \
\
- /* common method names */ \
+ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
-+ template(java_dyn_Dynamic, "java/dyn/Dynamic") \
-+ template(java_dyn_Linkage, "java/dyn/Linkage") \
-+ 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") \
@@ -5548,23 +4002,18 @@ diff --git a/src/share/vm/classfile/vmSy
+ 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(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(findBootstrapMethod_name, "findBootstrapMethod") \
-+ template(findBootstrapMethod_signature, "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/dyn/MethodHandle;") \
+ \
+ /* common method and field names */ \
template(object_initializer_name, "<init>") \
template(class_initializer_name, "<clinit>") \
template(println_name, "println") \
-@@ -284,6 +310,16 @@
+@@ -284,6 +301,16 @@
template(value_name, "value") \
template(frontCacheEnabled_name, "frontCacheEnabled") \
template(stringCacheEnabled_name, "stringCacheEnabled") \
@@ -5581,7 +4030,7 @@ diff --git a/src/share/vm/classfile/vmSy
\
/* non-intrinsic name/signature pairs: */ \
template(register_method_name, "register") \
-@@ -347,6 +383,7 @@
+@@ -347,6 +374,7 @@
template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
template(void_object_signature, "()Ljava/lang/Object;") \
template(void_class_signature, "()Ljava/lang/Class;") \
@@ -5589,16 +4038,6 @@ diff --git a/src/share/vm/classfile/vmSy
template(object_array_object_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
template(exception_void_signature, "(Ljava/lang/Exception;)V") \
template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
-@@ -418,8 +455,8 @@
- template(serializePropertiesToByteArray_signature, "()[B") \
- template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \
- template(classRedefinedCount_name, "classRedefinedCount") \
-+ \
- /*end*/
--
-
-
- // Here are all the intrinsics known to the runtime and the CI.
diff --git a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
--- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
+++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
@@ -5684,41 +4123,6 @@ diff --git a/src/share/vm/includeDB_core
stubGenerator_<arch_model>.cpp methodOop.hpp
stubGenerator_<arch_model>.cpp nativeInst_<arch>.hpp
stubGenerator_<arch_model>.cpp objArrayKlass.hpp
-@@ -4038,6 +4060,7 @@
- templateTable_<arch_model>.cpp interpreterRuntime.hpp
- templateTable_<arch_model>.cpp interpreter.hpp
- templateTable_<arch_model>.cpp methodDataOop.hpp
-+templateTable_<arch_model>.cpp methodHandles.hpp
- templateTable_<arch_model>.cpp objArrayKlass.hpp
- templateTable_<arch_model>.cpp oop.inline.hpp
- templateTable_<arch_model>.cpp sharedRuntime.hpp
-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
-@@ -28,6 +31,12 @@
- constantPoolKlass.cpp psPromotionManager.inline.hpp
- 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
-@@ -28,6 +28,7 @@
- jvmtiClassFileReconstituter.cpp bytes_<arch>.hpp
- jvmtiClassFileReconstituter.cpp jvmtiClassFileReconstituter.hpp
- jvmtiClassFileReconstituter.cpp symbolTable.hpp
-+jvmtiClassFileReconstituter.cpp signature.hpp
-
- jvmtiClassFileReconstituter.hpp jvmtiEnv.hpp
-
diff --git a/src/share/vm/interpreter/abstractInterpreter.hpp b/src/share/vm/interpreter/abstractInterpreter.hpp
--- a/src/share/vm/interpreter/abstractInterpreter.hpp
+++ b/src/share/vm/interpreter/abstractInterpreter.hpp
@@ -5730,470 +4134,6 @@ diff --git a/src/share/vm/interpreter/ab
java_lang_math_sin, // implementation of java.lang.Math.sin (x)
java_lang_math_cos, // implementation of java.lang.Math.cos (x)
java_lang_math_tan, // implementation of java.lang.Math.tan (x)
-@@ -90,8 +91,6 @@
- static address _slow_signature_handler; // the native method generic (slow) signature handler
-
- static address _rethrow_exception_entry; // rethrows an activation in previous frame
--
--
-
- friend class AbstractInterpreterGenerator;
- friend class InterpreterGenerator;
-@@ -218,6 +217,77 @@
- stackElementSize()) + tag_offset_in_bytes();
- }
-
-+ // access to stacked values according to type:
-+ static oop* oop_addr_in_slot(intptr_t* slot_addr) {
-+ return (oop*) slot_addr;
-+ }
-+ template<class T>
-+ static T* subword_addr_in_slot(intptr_t* slot_addr) {
-+ if ((int) sizeof(T) < wordSize && !Bytes::is_Java_byte_ordering_different())
-+ // big-endian LP64
-+ return (T*)(slot_addr + 1) - 1;
-+ else
-+ return (T*) slot_addr;
-+ }
-+ static jint* int_addr_in_slot(intptr_t* slot_addr) {
-+ return subword_addr_in_slot<jint>(slot_addr);
-+ }
-+ static jlong long_in_slot(intptr_t* slot_addr) {
-+ if (sizeof(intptr_t) >= sizeof(jlong)) {
-+ return *(jlong*) slot_addr;
-+ } else if (!TaggedStackInterpreter) {
-+ return Bytes::get_native_u8((address)slot_addr);
-+ } else {
-+ assert(sizeof(intptr_t) * 2 == sizeof(jlong), "ILP32");
-+ // assemble the long in memory order (not arithmetic order)
-+ union { jlong j; jint i[2]; } u;
-+ u.i[0] = (jint) slot_addr[0*stackElementSize()];
-+ u.i[1] = (jint) slot_addr[1*stackElementSize()];
-+ return u.j;
-+ }
-+ }
-+ static void set_long_in_slot(intptr_t* slot_addr, jlong value) {
-+ if (sizeof(intptr_t) >= sizeof(jlong)) {
-+ *(jlong*) slot_addr = value;
-+ } else if (!TaggedStackInterpreter) {
-+ Bytes::put_native_u8((address)slot_addr, value);
-+ } else {
-+ assert(sizeof(intptr_t) * 2 == sizeof(jlong), "ILP32");
-+ // assemble the long in memory order (not arithmetic order)
-+ union { jlong j; jint i[2]; } u;
-+ u.j = value;
-+ slot_addr[0*stackElementSize()] = (intptr_t) u.i[0];
-+ slot_addr[1*stackElementSize()] = (intptr_t) u.i[1];
-+ }
-+ }
-+ static void get_jvalue_in_slot(intptr_t* slot_addr, BasicType type, jvalue* value) {
-+ switch (type) {
-+ case T_BOOLEAN: value->z = *subword_addr_in_slot<jboolean>(slot_addr); break;
-+ case T_CHAR: value->c = *subword_addr_in_slot<jchar>(slot_addr); break;
-+ case T_BYTE: value->c = *subword_addr_in_slot<jbyte>(slot_addr); break;
-+ case T_SHORT: value->c = *subword_addr_in_slot<jshort>(slot_addr); break;
-+ case T_INT: value->i = *subword_addr_in_slot<jint>(slot_addr); break;
-+ case T_LONG: value->j = long_in_slot(slot_addr); break;
-+ case T_FLOAT: value->f = *subword_addr_in_slot<jfloat>(slot_addr); break;
-+ case T_DOUBLE: value->d = jdouble_cast(long_in_slot(slot_addr)); break;
-+ case T_OBJECT: value->l = (jobject) *oop_addr_in_slot(slot_addr); break;
-+ default: ShouldNotReachHere();
-+ }
-+ }
-+ static void set_jvalue_in_slot(intptr_t* slot_addr, BasicType type, jvalue* value) {
-+ switch (type) {
-+ case T_BOOLEAN: *subword_addr_in_slot<jbyte>(slot_addr) = (value->z != 0); break;
-+ case T_CHAR: *subword_addr_in_slot<jchar>(slot_addr) = value->c; break;
-+ case T_BYTE: *subword_addr_in_slot<jbyte>(slot_addr) = value->c; break;
-+ case T_SHORT: *subword_addr_in_slot<jshort>(slot_addr) = value->c; break;
-+ case T_INT: *subword_addr_in_slot<jint>(slot_addr) = value->i; break;
-+ case T_LONG: set_long_in_slot(slot_addr, value->j); break;
-+ case T_FLOAT: *subword_addr_in_slot<jfloat>(slot_addr) = value->f; break;
-+ case T_DOUBLE: set_long_in_slot(slot_addr, jlong_cast(value->d)); break;
-+ case T_OBJECT: *oop_addr_in_slot(slot_addr) = (oop) value->l; break;
-+ default: ShouldNotReachHere();
-+ }
-+ }
- };
-
- //------------------------------------------------------------------------------------------------------------------------
-diff --git a/src/share/vm/interpreter/bytecode.cpp b/src/share/vm/interpreter/bytecode.cpp
---- a/src/share/vm/interpreter/bytecode.cpp
-+++ b/src/share/vm/interpreter/bytecode.cpp
-@@ -34,12 +34,6 @@
- }
-
-
--void Bytecode::set_fast_index(int i) {
-- assert(0 <= i && i < 0x10000, "illegal index value");
-- Bytes::put_native_u2(addr_at(1), (jushort)i);
--}
--
--
- bool Bytecode::check_must_rewrite() const {
- assert(Bytecodes::can_rewrite(code()), "post-check only");
-
-@@ -118,7 +112,10 @@
-
-
- int Bytecode_invoke::index() const {
-- return Bytes::get_Java_u2(bcp() + 1);
-+ if (has_giant_index())
-+ return Bytes::get_native_u4(bcp() + 1);
-+ else
-+ return Bytes::get_Java_u2(bcp() + 1);
- }
-
-
-diff --git a/src/share/vm/interpreter/bytecode.hpp b/src/share/vm/interpreter/bytecode.hpp
---- a/src/share/vm/interpreter/bytecode.hpp
-+++ b/src/share/vm/interpreter/bytecode.hpp
-@@ -65,14 +65,6 @@
- // The base class for different kinds of bytecode abstractions.
- // Provides the primitive operations to manipulate code relative
- // to an objects 'this' pointer.
--//
--// Note: Even though it seems that the fast_index & set_fast_index
--// functions are machine specific, they're not. They only use
--// the natural way to store a 16bit index on a given machine,
--// independent of the particular byte ordering. Since all other
--// places in the system that refer to these indices use the
--// same method (the natural byte ordering on the platform)
--// this will always work and be machine-independent).
-
- class Bytecode: public ThisRelativeObj {
- protected:
-@@ -83,24 +75,41 @@
- // Attributes
- address bcp() const { return addr_at(0); }
- address next_bcp() const { return addr_at(0) + Bytecodes::length_at(bcp()); }
-+ int instruction_size() const { return Bytecodes::length_at(bcp()); }
-
- Bytecodes::Code code() const { return Bytecodes::code_at(addr_at(0)); }
-+ Bytecodes::Code raw_code() const { return Bytecodes::raw_code_at(addr_at(0)); }
- Bytecodes::Code java_code() const { return Bytecodes::java_code(code()); }
- bool must_rewrite() const { return Bytecodes::can_rewrite(code()) && check_must_rewrite(); }
- bool is_active_breakpoint() const { return Bytecodes::is_active_breakpoint_at(bcp()); }
-
-- int one_byte_index() const { return byte_at(1); }
-- int two_byte_index() const { return (byte_at(1) << 8) + byte_at(2); }
-+ int one_byte_index() const { assert_index_size(1); return byte_at(1); }
-+ int two_byte_index() const { assert_index_size(2); return (byte_at(1) << 8) + byte_at(2); }
-+
- int offset() const { return (two_byte_index() << 16) >> 16; }
- address destination() const { return bcp() + offset(); }
-- int fast_index() const { return Bytes::get_native_u2(addr_at(1)); }
-
- // Attribute modification
- void set_code(Bytecodes::Code code);
-- void set_fast_index(int i);
-
- // Creation
- inline friend Bytecode* Bytecode_at(address bcp);
-+
-+ private:
-+ void assert_index_size(int required_size) const {
-+#ifdef ASSERT
-+ int isize = instruction_size() - 1;
-+ if (isize == 2 && raw_code() == Bytecodes::_iinc)
-+ isize = 1;
-+ else if (isize <= 2)
-+ ; // no change
-+ else if (raw_code() == Bytecodes::_invokedynamic)
-+ isize = 4;
-+ else
-+ isize = 2;
-+ assert(isize = required_size, "wrong index size");
-+#endif
-+ }
- };
-
- inline Bytecode* Bytecode_at(address bcp) {
-@@ -185,6 +194,7 @@
- symbolOop signature() const; // returns the signature of the invoked method
- BasicType result_type(Thread *thread) const; // returns the result type of the invoke
-
-+ Bytecodes::Code raw_code() const { return Bytecodes::raw_code_at(bcp(), _method()); }
- Bytecodes::Code code() const { return Bytecodes::code_at(bcp(), _method()); }
- Bytecodes::Code adjusted_invoke_code() const { return Bytecodes::java_code(code()); }
-
-@@ -195,6 +205,7 @@
- bool is_invokevirtual() const { return adjusted_invoke_code() == Bytecodes::_invokevirtual; }
- bool is_invokestatic() const { return adjusted_invoke_code() == Bytecodes::_invokestatic; }
- bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; }
-+ bool has_giant_index() const { return raw_code() == Bytecodes::_invokedynamic; }
-
- bool is_valid() const { return is_invokeinterface() ||
- is_invokevirtual() ||
-diff --git a/src/share/vm/interpreter/bytecodeStream.hpp b/src/share/vm/interpreter/bytecodeStream.hpp
---- a/src/share/vm/interpreter/bytecodeStream.hpp
-+++ b/src/share/vm/interpreter/bytecodeStream.hpp
-@@ -108,7 +108,9 @@
- int end_bci() const { return _end_bci; }
-
- Bytecodes::Code code() const { return _code; }
-+ Bytecodes::Code raw_code() const { return Bytecodes::raw_code_at(bcp()); }
- bool is_wide() const { return _is_wide; }
-+ int instruction_size() const { return (_next_bci - _bci); }
- bool is_last_bytecode() const { return _next_bci >= _end_bci; }
-
- address bcp() const { return method()->code_base() + _bci; }
-@@ -122,8 +124,29 @@
- int dest_w() const { return bci() + (int )Bytes::get_Java_u4(bcp() + 1); }
-
- // Unsigned indices, widening
-- int get_index() const { return (is_wide()) ? Bytes::get_Java_u2(bcp() + 2) : bcp()[1]; }
-- int get_index_big() const { return (int)Bytes::get_Java_u2(bcp() + 1); }
-+ int get_index() const { assert_index_size(is_wide() ? 2 : 1);
-+ return (is_wide()) ? Bytes::get_Java_u2(bcp() + 2) : bcp()[1]; }
-+ int get_index_big() const { assert_index_size(2);
-+ return (int)Bytes::get_Java_u2(bcp() + 1); }
-+ int get_index_int() const { return has_giant_index() ? get_index_giant() : get_index_big(); }
-+ int get_index_giant() const { assert_index_size(4); return Bytes::get_native_u4(bcp() + 1); }
-+ int has_giant_index() const { return (raw_code() == Bytecodes::_invokedynamic); }
-+
-+ private:
-+ void assert_index_size(int required_size) const {
-+#ifdef ASSERT
-+ int isize = instruction_size() - (int)_is_wide - 1;
-+ if (isize == 2 && raw_code() == Bytecodes::_iinc)
-+ isize = 1;
-+ else if (isize <= 2)
-+ ; // no change
-+ else if (has_giant_index())
-+ isize = 4;
-+ else
-+ isize = 2;
-+ assert(isize = required_size, "wrong index size");
-+#endif
-+ }
- };
-
- // In BytecodeStream, non-java bytecodes will be translated into the
-diff --git a/src/share/vm/interpreter/bytecodeTracer.cpp b/src/share/vm/interpreter/bytecodeTracer.cpp
---- a/src/share/vm/interpreter/bytecodeTracer.cpp
-+++ b/src/share/vm/interpreter/bytecodeTracer.cpp
-@@ -48,12 +48,15 @@
-
- int get_index() { return *(address)_next_pc++; }
- int get_big_index() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
-+ int get_giant_index() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; }
- int get_index_special() { return (is_wide()) ? get_big_index() : get_index(); }
- methodOop method() { return _current_method; }
- bool is_wide() { return _is_wide; }
-
-
-+ bool check_index(int i, bool in_cp_cache, int& cp_index, outputStream* st = tty);
- void print_constant(int i, outputStream* st = tty);
-+ void print_field_or_method(int i, outputStream* st = tty);
- void print_attributes(Bytecodes::Code code, int bci, outputStream* st = tty);
- void bytecode_epilog(int bci, outputStream* st = tty);
-
-@@ -182,7 +185,71 @@
- }
- }
-
-+bool BytecodePrinter::check_index(int i, bool in_cp_cache, int& cp_index, outputStream* st) {
-+ constantPoolOop constants = method()->constants();
-+ int ilimit = constants->length(), climit = 0;
-+
-+ constantPoolCacheOop cache = NULL;
-+ if (in_cp_cache) {
-+ cache = constants->cache();
-+ if (cache != NULL) {
-+ //climit = cache->length(); // %%% private!
-+ size_t size = cache->size() * HeapWordSize;
-+ size -= sizeof(constantPoolCacheOopDesc);
-+ size /= sizeof(ConstantPoolCacheEntry);
-+ climit = (int) size;
-+ }
-+ }
-+
-+ if (in_cp_cache && constantPoolCacheOopDesc::is_secondary_index(i)) {
-+ i = constantPoolCacheOopDesc::decode_secondary_index(i);
-+ st->print(" secondary cache[%d] of", i);
-+ if (i >= 0 && i < climit) {
-+ if (!cache->entry_at(i)->is_secondary_entry()) {
-+ st->print_cr(" not secondary entry?", i);
-+ return false;
-+ }
-+ i = cache->entry_at(i)->main_entry_index();
-+ goto check_cache_index;
-+ } else {
-+ st->print_cr(" not in cache[*]?", i);
-+ return false;
-+ }
-+ }
-+
-+ if (cache != NULL) {
-+ i = Bytes::swap_u2(i);
-+ if (WizardMode) st->print(" (swap=%d)", i);
-+ goto check_cache_index;
-+ }
-+
-+ check_cp_index:
-+ if (i >= 0 && i < ilimit) {
-+ if (WizardMode) st->print(" cp[%d]", i);
-+ cp_index = i;
-+ return true;
-+ }
-+
-+ st->print_cr(" CP[%d] not in CP", i);
-+ return false;
-+
-+ check_cache_index:
-+ if (i >= 0 && i < climit) {
-+ if (cache->entry_at(i)->is_secondary_entry()) {
-+ st->print_cr(" secondary entry?");
-+ return false;
-+ }
-+ i = cache->entry_at(i)->constant_pool_index();
-+ goto check_cp_index;
-+ }
-+ st->print_cr(" not in CP[*]?", i);
-+ return false;
-+}
-+
- void BytecodePrinter::print_constant(int i, outputStream* st) {
-+ int orig_i = i;
-+ if (!check_index(orig_i, false, i, st)) return;
-+
- constantPoolOop constants = method()->constants();
- constantTag tag = constants->tag_at(i);
-
-@@ -203,13 +270,37 @@
- st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
- } else if (tag.is_unresolved_klass()) {
- st->print_cr(" <unresolved klass at %d>", i);
-- } else ShouldNotReachHere();
-+ } else {
-+ st->print_cr(" bad tag=%d at %d", tag.value(), i);
-+ }
- }
-
-+void BytecodePrinter::print_field_or_method(int i, outputStream* st) {
-+ int orig_i = i;
-+ if (!check_index(orig_i, true, i, st)) return;
-
--void BytecodePrinter::print_attributes(Bytecodes::Code code, int bci, outputStream* st) {
-+ constantPoolOop constants = method()->constants();
-+ constantTag tag = constants->tag_at(i);
-+
-+ switch (tag.value()) {
-+ case JVM_CONSTANT_InterfaceMethodref:
-+ case JVM_CONSTANT_Methodref:
-+ case JVM_CONSTANT_Fieldref:
-+ break;
-+ default:
-+ st->print_cr(" bad tag=%d at %d", tag.value(), i);
-+ return;
-+ }
-+
-+ symbolOop name = constants->name_ref_at(orig_i);
-+ symbolOop signature = constants->signature_ref_at(orig_i);
-+ st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string());
-+}
-+
-+
-+void BytecodePrinter::print_attributes(Bytecodes::Code raw_code, int bci, outputStream* st) {
- // Show attributes of pre-rewritten codes
-- code = Bytecodes::java_code(code);
-+ Bytecodes::Code code = Bytecodes::java_code(raw_code);
- // If the code doesn't have any fields there's nothing to print.
- // note this is ==1 because the tableswitch and lookupswitch are
- // zero size (for some reason) and we want to print stuff out for them.
-@@ -354,33 +445,25 @@
- case Bytecodes::_putstatic:
- case Bytecodes::_getstatic:
- case Bytecodes::_putfield:
-- case Bytecodes::_getfield: {
-- int i = get_big_index();
-- constantPoolOop constants = method()->constants();
-- symbolOop field = constants->name_ref_at(i);
-- st->print_cr(" %d <%s>", i, field->as_C_string());
-- }
-+ case Bytecodes::_getfield:
-+ print_field_or_method(get_big_index(), st);
- break;
-
- case Bytecodes::_invokevirtual:
- case Bytecodes::_invokespecial:
- case Bytecodes::_invokestatic:
-- { int i = get_big_index();
-- constantPoolOop constants = method()->constants();
-- symbolOop name = constants->name_ref_at(i);
-- symbolOop signature = constants->signature_ref_at(i);
-- st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string());
-- }
-+ print_field_or_method(get_big_index(), st);
- break;
-
- case Bytecodes::_invokeinterface:
-- { int i = get_big_index();
-+ if (raw_code == Bytecodes::_invokedynamic) {
-+ int i = get_giant_index();
-+ print_field_or_method(i, st);
-+ } else {
-+ int i = get_big_index();
- int n = get_index();
-- get_index();
-- constantPoolOop constants = method()->constants();
-- symbolOop name = constants->name_ref_at(i);
-- symbolOop signature = constants->signature_ref_at(i);
-- st->print_cr(" %d <%s> <%s> %d", i, name->as_C_string(), signature->as_C_string(), n);
-+ get_index(); // ignore zero byte
-+ print_field_or_method(i, st);
- }
- break;
-
-diff --git a/src/share/vm/interpreter/bytecodes.cpp b/src/share/vm/interpreter/bytecodes.cpp
---- a/src/share/vm/interpreter/bytecodes.cpp
-+++ b/src/share/vm/interpreter/bytecodes.cpp
-@@ -345,7 +345,7 @@
- def(_invokespecial , "invokespecial" , "bjj" , NULL , T_ILLEGAL, -1, true);
- def(_invokestatic , "invokestatic" , "bjj" , NULL , T_ILLEGAL, 0, true);
- def(_invokeinterface , "invokeinterface" , "bjj__", NULL , T_ILLEGAL, -1, true);
-- def(_xxxunusedxxx , "xxxunusedxxx" , NULL , NULL , T_VOID , 0, false);
-+ //_invokedynamic is below
- def(_new , "new" , "bii" , NULL , T_OBJECT , 1, true );
- def(_newarray , "newarray" , "bc" , NULL , T_OBJECT , 0, true );
- def(_anewarray , "anewarray" , "bii" , NULL , T_OBJECT , 0, true );
-@@ -396,6 +396,9 @@
- // Faster method invocation.
- def(_fast_invokevfinal , "fast_invokevfinal" , "bjj" , NULL , T_ILLEGAL, -1, true, _invokevirtual );
-
-+ // JSR 292 (this is not an externally visible bytecode)
-+ def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, -1, true, _invokeinterface );
-+
- def(_fast_linearswitch , "fast_linearswitch" , "" , NULL , T_VOID , -1, false, _lookupswitch );
- def(_fast_binaryswitch , "fast_binaryswitch" , "" , NULL , T_VOID , -1, false, _lookupswitch );
-
-diff --git a/src/share/vm/interpreter/bytecodes.hpp b/src/share/vm/interpreter/bytecodes.hpp
---- a/src/share/vm/interpreter/bytecodes.hpp
-+++ b/src/share/vm/interpreter/bytecodes.hpp
-@@ -218,7 +218,7 @@
- _invokespecial = 183, // 0xb7
- _invokestatic = 184, // 0xb8
- _invokeinterface = 185, // 0xb9
-- _xxxunusedxxx = 186, // 0xba
-+ _invokedynamic = 186, // 0xba // if InvokeDynamic
- _new = 187, // 0xbb
- _newarray = 188, // 0xbc
- _anewarray = 189, // 0xbd
-@@ -305,8 +305,12 @@
-
-
- // Fetch a bytecode, hiding breakpoints as necessary:
-+ static Code raw_code_at(address bcp, methodOop method = NULL) {
-+ return cast(*bcp);
-+ }
- static Code code_at(address bcp, methodOop method = NULL) {
-- Code code = cast(*bcp); return (code != _breakpoint) ? code : non_breakpoint_code_at(bcp, method);
-+ Code code = raw_code_at(bcp);
-+ return (code != _breakpoint) ? code : non_breakpoint_code_at(bcp, method);
- }
- static Code java_code_at(address bcp, methodOop method = NULL) {
- return java_code(code_at(bcp, method));
diff --git a/src/share/vm/interpreter/cppInterpreter.cpp b/src/share/vm/interpreter/cppInterpreter.cpp
--- a/src/share/vm/interpreter/cppInterpreter.cpp
+++ b/src/share/vm/interpreter/cppInterpreter.cpp
@@ -6264,174 +4204,10 @@ diff --git a/src/share/vm/interpreter/in
// exception_handler_for_exception(...) returns the continuation address,
-@@ -591,7 +614,7 @@
- JvmtiExport::post_raw_breakpoint(thread, method, bcp);
- IRT_END
-
--IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode))
-+IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code bytecode)) {
- // extract receiver from the outgoing argument list if necessary
- Handle receiver(thread, NULL);
- if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
-@@ -636,7 +659,6 @@
- if (already_resolved(thread)) return;
-
- if (bytecode == Bytecodes::_invokeinterface) {
--
- if (TraceItables && Verbose) {
- ResourceMark rm(thread);
- tty->print_cr("Resolving: klass: %s to method: %s", info.resolved_klass()->name()->as_C_string(), info.resolved_method()->name()->as_C_string());
-@@ -660,7 +682,133 @@
- info.resolved_method(),
- info.vtable_index());
- }
-+}
- IRT_END
-+
-+
-+// First time execution: Resolve symbols, create a permanent DynCallSite object.
-+IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
-+ ResourceMark rm(thread);
-+
-+ assert(InvokeDynamic, "");
-+ const Bytecodes::Code bytecode = Bytecodes::_invokedynamic;
-+
-+ methodHandle caller_method(thread, method(thread));
-+
-+ // first determine if there is a bootstrap method
-+ {
-+ 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());
-+ }
-+ }
-+
-+ constantPoolHandle pool(thread, caller_method->constants());
-+ pool->set_invokedynamic(); // mark header to flag active call sites
-+
-+ int raw_index = four_byte_index(thread);
-+ assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "invokedynamic indexes marked specially");
-+
-+ // 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();
-+
-+ // first resolve the signature to a MH.invoke methodOop
-+ if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) {
-+ JvmtiHideSingleStepping jhss(thread);
-+ CallInfo info;
-+ LinkResolver::resolve_invoke(info, Handle(), pool,
-+ raw_index, bytecode, CHECK);
-+ pool->cache()->entry_at(main_index)->set_method(
-+ bytecode,
-+ info.resolved_method(),
-+ info.vtable_index());
-+ }
-+
-+ // 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.
-+ 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(), "");
-+
-+ Handle call_site
-+ = SystemDictionary::make_dynamic_call_site(caller_method->method_holder(),
-+ pool->uncached_name_ref_at(call_index),
-+ mh_extinv, vmdata, CHECK);
-+ pool->cache()->entry_at(site_index)->set_dynamic_call(call_site(), 0);
-+}
-+IRT_END
-+
-+
-+// 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));
-+ Handle mh_type(thread, mh_invdyn->method_handle_type());
-+ objArrayHandle mh_ptypes(thread, java_dyn_MethodType::ptypes(mh_type()));
-+
-+ // squish the arguments down to a single array
-+ int nargs = mh_ptypes->length();
-+ objArrayHandle arg_array;
-+ {
-+ objArrayOop aaoop = oopFactory::new_objArray(SystemDictionary::object_klass(), nargs, CHECK);
-+ arg_array = objArrayHandle(thread, aaoop);
-+ }
-+ frame fr = thread->last_frame();
-+ assert(fr.interpreter_frame_bcp() != NULL, "sanity");
-+ int tos_offset = 0;
-+ for (int i = nargs; --i >= 0; ) {
-+ intptr_t* slot_addr = fr.interpreter_frame_tos_at(tos_offset++);
-+ oop ptype = mh_ptypes->obj_at(i);
-+ oop arg = NULL;
-+ if (!java_lang_Class::is_primitive(ptype)) {
-+ arg = *(oop*) slot_addr;
-+ } else {
-+ assert(i > 0, "first argument is always an oop");
-+ BasicType bt = java_lang_Class::primitive_type(ptype);
-+ assert(frame::interpreter_frame_expression_stack_direction() < 0, "else reconsider this code");
-+ jvalue value;
-+ Interpreter::get_jvalue_in_slot(slot_addr, bt, &value);
-+ tos_offset += type2size[bt]-1;
-+ arg = java_lang_boxing_object::create(bt, &value, CHECK);
-+ // FIXME: These boxing objects are not canonicalized under
-+ // the Java autoboxing rules. They should be...
-+ // The best approach would be to push the arglist creation into Java.
-+ // The JVM should use a lower-level interface to communicate argument lists.
-+ }
-+ arg_array->obj_at_put(i, arg);
-+ }
-+
-+ // return the argument array by storing it down over the first argument:
-+ assert(nargs > 0, "always a first argument");
-+ *fr.interpreter_frame_tos_at(tos_offset - 1) = (intptr_t) arg_array();
-+
-+ // now find the bootstrap method
-+ oop bootstrap_mh_oop = instanceKlass::cast(fr.interpreter_frame_method()->method_holder())->bootstrap_method();
-+ assert(bootstrap_mh_oop != NULL, "must already be determined");
-+ thread->set_vm_result(bootstrap_mh_oop);
-+}
-+IRT_END
-+
-
-
- //------------------------------------------------------------------------------------------------------------------------
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
-@@ -42,8 +42,11 @@
- static bool already_resolved(JavaThread *thread) { return cache_entry(thread)->is_resolved(code(thread)); }
- static int one_byte_index(JavaThread *thread) { return bcp(thread)[1]; }
- static int two_byte_index(JavaThread *thread) { return Bytes::get_Java_u2(bcp(thread) + 1); }
-+ static int four_byte_index(JavaThread *thread) { return Bytes::get_native_u4(bcp(thread) + 1); }
- static int number_of_dimensions(JavaThread *thread) { return bcp(thread)[3]; }
-- static ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return method(thread)->constants()->cache()->entry_at(Bytes::get_native_u2(bcp(thread) + 1)); }
-+
-+ static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i) { return method(thread)->constants()->cache()->entry_at(i); }
-+ static ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return cache_entry_at(thread, Bytes::get_native_u2(bcp(thread) + 1)); }
- static void note_trap(JavaThread *thread, int reason, TRAPS);
-
- public:
-@@ -66,6 +69,7 @@
+@@ -66,6 +66,7 @@
static void throw_StackOverflowError(JavaThread* thread);
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, char* name, jint index);
static void throw_ClassCastException(JavaThread* thread, oopDesc* obj);
@@ -6439,21 +4215,10 @@ diff --git a/src/share/vm/interpreter/in
static void create_exception(JavaThread* thread, char* name, char* message);
static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj);
static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);
-@@ -82,7 +86,9 @@
- static void new_illegal_monitor_state_exception(JavaThread* thread);
-
- // Calls
-- static void resolve_invoke (JavaThread* thread, Bytecodes::Code bytecode);
-+ static void resolve_invoke (JavaThread* thread, Bytecodes::Code bytecode);
-+ static void resolve_invokedynamic(JavaThread* thread);
-+ static void bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site);
-
- // Breakpoints
- static void _breakpoint(JavaThread* thread, methodOopDesc* method, address bcp);
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
-@@ -149,6 +149,33 @@
+@@ -149,6 +149,20 @@
void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
instanceKlass *ik = instanceKlass::cast(klass());
result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature()));
@@ -6471,23 +4236,10 @@ diff --git a/src/share/vm/interpreter/li
+ 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);
-+ }
-+ }
}
void LinkResolver::check_method_accessability(KlassHandle ref_klass,
-@@ -238,6 +265,11 @@
+@@ -238,6 +252,11 @@
if (resolved_method.is_null()) { // not found in the class hierarchy
// 3. lookup method in all the interfaces implemented by the resolved klass
lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
@@ -6499,56 +4251,6 @@ diff --git a/src/share/vm/interpreter/li
if (resolved_method.is_null()) {
// 4. method lookup failed
-@@ -315,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
-@@ -746,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);
- }
-
-@@ -928,6 +969,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;
-+ case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break;
- case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break;
- }
- return;
-@@ -989,6 +1031,18 @@
- 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);
-+}
-+
- //------------------------------------------------------------------------------------------------------------------------
- #ifndef PRODUCT
-
diff --git a/src/share/vm/interpreter/linkResolver.hpp b/src/share/vm/interpreter/linkResolver.hpp
--- a/src/share/vm/interpreter/linkResolver.hpp
+++ b/src/share/vm/interpreter/linkResolver.hpp
@@ -6560,367 +4262,6 @@ diff --git a/src/share/vm/interpreter/li
static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
-@@ -146,6 +147,7 @@
- static void resolve_special_call (CallInfo& result, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS);
- static void resolve_virtual_call (CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
- static void resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, bool check_null_and_abstract, TRAPS);
-+ static void resolve_dynamic_call (CallInfo& result, KlassHandle resolved_klass, symbolHandle method_name, symbolHandle method_signature, KlassHandle current_klass, bool check_access, TRAPS);
-
- // same as above for compile-time resolution; but returns null handle instead of throwing an exception on error
- // also, does not initialize klass (i.e., no side effects)
-@@ -166,6 +168,7 @@
- static void resolve_invokespecial (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
- static void resolve_invokevirtual (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
- static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
-+ static void resolve_invokedynamic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
-
- static void resolve_invoke (CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
- };
-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 @@
- # include "incls/_precompiled.incl"
- # include "incls/_rewriter.cpp.incl"
-
--
--// Computes an index_map (new_index -> original_index) for contant pool entries
-+// Computes a CPC map (new_index -> original_index) for constant pool entries
- // that are referred to by the interpreter at runtime via the constant pool cache.
--void Rewriter::compute_index_maps(constantPoolHandle pool, intArray*& index_map, intStack*& inverse_index_map) {
-- const int length = pool->length();
-- index_map = new intArray(length, -1);
-- // Choose an initial value large enough that we don't get frequent
-- // calls to grow().
-- inverse_index_map = new intStack(length / 2);
-+// Also computes a CP map (original_index -> new_index).
-+// Marks entries in CP which require additional processing.
-+void Rewriter::compute_index_maps() {
-+ const int length = _pool->length();
-+ init_cp_map(length);
- for (int i = 0; i < length; i++) {
-- switch (pool->tag_at(i).value()) {
-+ 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: {
-- index_map->at_put(i, inverse_index_map->length());
-- inverse_index_map->append(i);
-- }
-+ add_cp_cache_entry(i);
-+ break;
- }
- }
-+
-+ guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1),
-+ "all cp cache indexes fit in a u2");
- }
-
-
--// 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
-+ int encoded = constantPoolCacheOopDesc::encode_secondary_index(main_entry);
-+ int plain_secondary_index = _cp_cache_map.append(encoded);
-+ return constantPoolCacheOopDesc::encode_secondary_index(plain_secondary_index);
-+}
-+
-+
-+
-+// Creates a constant pool cache given a CPC map
-+void Rewriter::make_constant_pool_cache(TRAPS) {
-+ const int length = _cp_cache_map.length();
-+ constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length, CHECK);
-+ cache->initialize(_cp_cache_map);
-+ _pool->set_cache(cache);
-+ cache->set_constant_pool(_pool());
- }
-
-
-@@ -96,8 +119,40 @@
- }
-
-
-+// Rewrite a classfile-order CP index into a native-order CPC index.
-+int Rewriter::rewrite_member_reference(address bcp, int offset) {
-+ address p = bcp + offset;
-+ int cp_index = Bytes::get_Java_u2(p);
-+ int cache_index = cp_entry_to_cp_cache(cp_index);
-+ Bytes::put_native_u2(p, cache_index);
-+ return cp_index;
-+}
-+
-+
-+void Rewriter::rewrite_invokedynamic(address bcp, int offset, int cp_index) {
-+ address p = bcp + offset;
-+ assert(InvokeDynamic, "");
-+ assert(p[-1] == Bytecodes::_invokeinterface, "");
-+ p[-1] = Bytecodes::_invokedynamic;
-+ int cpc = cp_entry_to_cp_cache(cp_index);
-+ 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,
-+ // not just one per distinct CP entry. In other words, the
-+ // CPC-to-CP relation is many-to-one for invokedynamic entries.
-+ // This means we must use a larger index size than u2 to address
-+ // all these entries. That is the main reason invokedynamic
-+ // must have a five-byte instruction format. (Of course, other JVM
-+ // implementations can use the bytes for other purposes.)
-+ Bytes::put_native_u4(p, cpc2);
-+ // Note: We use native_u4 format exclusively for 4-byte indexes.
-+}
-+
-+
- // Rewrites a method given the index_map information
--methodHandle Rewriter::rewrite_method(methodHandle method, intArray& index_map, TRAPS) {
-+void Rewriter::scan_method(methodOop method) {
-
- int nof_jsrs = 0;
- bool has_monitor_bytecodes = false;
-@@ -114,8 +169,10 @@
- const int code_length = method->code_size();
-
- int bc_length;
-+ int cp_index;
- for (int bci = 0; bci < code_length; bci += bc_length) {
- address bcp = code_base + bci;
-+ int prefix_length = 0;
- c = (Bytecodes::Code)(*bcp);
-
- // Since we have the code, see if we can get the length
-@@ -130,6 +187,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) {
-+ prefix_length = 1;
- c = (Bytecodes::Code)bcp[1];
- }
- }
-@@ -152,14 +210,20 @@
- case Bytecodes::_putstatic : // fall through
- case Bytecodes::_getfield : // fall through
- case Bytecodes::_putfield : // fall through
-+ case Bytecodes::_invokespecial : // fall through
- case Bytecodes::_invokevirtual : // 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 :
-+ 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);
-+ break;
- case Bytecodes::_jsr : // fall through
- case Bytecodes::_jsr_w : nof_jsrs++; break;
- case Bytecodes::_monitorenter : // fall through
-@@ -177,53 +241,56 @@
- // have to be rewritten, so we run the oopMapGenerator on the method
- if (nof_jsrs > 0) {
- method->set_has_jsrs();
-- ResolveOopMapConflicts romc(method);
-- methodHandle original_method = method;
-- method = romc.do_potential_rewrite(CHECK_(methodHandle()));
-- if (method() != original_method()) {
-- // Insert invalid bytecode into original methodOop and set
-- // interpreter entrypoint, so that a executing this method
-- // will manifest itself in an easy recognizable form.
-- address bcp = original_method->bcp_from(0);
-- *bcp = (u1)Bytecodes::_shouldnotreachhere;
-- int kind = Interpreter::method_kind(original_method);
-- original_method->set_interpreter_kind(kind);
-- }
-+ // Second pass will revisit this method.
-+ assert(method->has_jsrs(), "");
-+ }
-+}
-
-- // Update monitor matching info.
-- if (romc.monitor_safe()) {
-- method->set_guaranteed_monitor_matching();
-- }
-+// After constant pool is created, revisit methods containing jsrs.
-+methodHandle Rewriter::rewrite_jsrs(methodHandle method, TRAPS) {
-+ ResolveOopMapConflicts romc(method);
-+ methodHandle original_method = method;
-+ method = romc.do_potential_rewrite(CHECK_(methodHandle()));
-+ if (method() != original_method()) {
-+ // Insert invalid bytecode into original methodOop and set
-+ // interpreter entrypoint, so that a executing this method
-+ // will manifest itself in an easy recognizable form.
-+ address bcp = original_method->bcp_from(0);
-+ *bcp = (u1)Bytecodes::_shouldnotreachhere;
-+ int kind = Interpreter::method_kind(original_method);
-+ original_method->set_interpreter_kind(kind);
- }
-
-- // Setup method entrypoints for compiler and interpreter
-- method->link_method(method, CHECK_(methodHandle()));
-+ // Update monitor matching info.
-+ if (romc.monitor_safe()) {
-+ method->set_guaranteed_monitor_matching();
-+ }
-
- return method;
- }
-
-
- void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
-- // gather starting points
- ResourceMark rm(THREAD);
-- constantPoolHandle pool (THREAD, klass->constants());
-- objArrayHandle methods (THREAD, klass->methods());
-- assert(pool->cache() == NULL, "constant pool cache must not be set yet");
-+ Rewriter rw(klass, CHECK);
-+ // (That's all, folks.)
-+}
-+
-+Rewriter::Rewriter(instanceKlassHandle klass, TRAPS)
-+ : _klass(klass),
-+ // gather starting points
-+ _pool( THREAD, klass->constants()),
-+ _methods(THREAD, klass->methods())
-+{
-+ assert(_pool->cache() == NULL, "constant pool cache must not be set yet");
-
- // determine index maps for methodOop rewriting
-- intArray* index_map = NULL;
-- intStack* inverse_index_map = NULL;
-- compute_index_maps(pool, index_map, inverse_index_map);
-+ compute_index_maps();
-
-- // allocate constant pool cache
-- constantPoolCacheHandle cache = new_constant_pool_cache(*inverse_index_map, CHECK);
-- pool->set_cache(cache());
-- cache->set_constant_pool(pool());
--
-- if (RegisterFinalizersAtInit && klass->name() == vmSymbols::java_lang_Object()) {
-- int i = methods->length();
-+ if (RegisterFinalizersAtInit && _klass->name() == vmSymbols::java_lang_Object()) {
-+ int i = _methods->length();
- while (i-- > 0) {
-- methodOop method = (methodOop)methods->obj_at(i);
-+ methodOop method = (methodOop)_methods->obj_at(i);
- 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 @@
- }
- }
-
-- // rewrite methods
-- { int i = methods->length();
-- while (i-- > 0) {
-- methodHandle m(THREAD, (methodOop)methods->obj_at(i));
-- m = rewrite_method(m, *index_map, CHECK);
-+ // rewrite methods, in two passes
-+ int i, len = _methods->length();
-+
-+ for (i = len; --i >= 0; ) {
-+ methodOop method = (methodOop)_methods->obj_at(i);
-+ scan_method(method);
-+ }
-+
-+ // allocate constant pool cache, now that we've seen all the bytecodes
-+ make_constant_pool_cache(CHECK);
-+
-+ for (i = len; --i >= 0; ) {
-+ methodHandle m(THREAD, (methodOop)_methods->obj_at(i));
-+
-+ if (m->has_jsrs()) {
-+ m = rewrite_jsrs(m, CHECK);
- // Method might have gotten rewritten.
-- methods->obj_at_put(i, m());
-+ _methods->obj_at_put(i, m());
- }
-+
-+ // Set up method entry points for compiler and interpreter.
-+ m->link_method(m, CHECK);
- }
- }
-diff --git a/src/share/vm/interpreter/rewriter.hpp b/src/share/vm/interpreter/rewriter.hpp
---- a/src/share/vm/interpreter/rewriter.hpp
-+++ b/src/share/vm/interpreter/rewriter.hpp
-@@ -25,13 +25,44 @@
- // The Rewriter adds caches to the constant pool and rewrites bytecode indices
- // pointing into the constant pool for better interpreter performance.
-
--class Rewriter: public AllStatic {
-+class Rewriter: public StackObj {
- private:
-- static void compute_index_maps(constantPoolHandle pool, intArray*& index_map, intStack*& inverse_index_map);
-- static constantPoolCacheHandle new_constant_pool_cache(intArray& inverse_index_map, TRAPS);
-- static methodHandle rewrite_method(methodHandle method, intArray& index_map, TRAPS);
-- static void rewrite_Object_init(methodHandle method, TRAPS);
-+ instanceKlassHandle _klass;
-+ constantPoolHandle _pool;
-+ objArrayHandle _methods;
-+ intArray _cp_map;
-+ intStack _cp_cache_map;
-+
-+ void init_cp_map(int length) {
-+ _cp_map.initialize(length, -1);
-+ // Choose an initial value large enough that we don't get frequent
-+ // 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) {
-+ 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));
-+ 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);
-+
-+ // All the work goes in here:
-+ Rewriter(instanceKlassHandle klass, TRAPS);
-+
-+ void compute_index_maps();
-+ void make_constant_pool_cache(TRAPS);
-+ void scan_method(methodOop m);
-+ methodHandle rewrite_jsrs(methodHandle m, TRAPS);
-+ void rewrite_Object_init(methodHandle m, TRAPS);
-+ int rewrite_member_reference(address bcp, int offset);
-+ void rewrite_invokedynamic(address bcp, int offset, int cp_index);
-
- public:
-+ // Driver routine:
- static void rewrite(instanceKlassHandle klass, TRAPS);
- };
diff --git a/src/share/vm/interpreter/templateInterpreter.cpp b/src/share/vm/interpreter/templateInterpreter.cpp
--- a/src/share/vm/interpreter/templateInterpreter.cpp
+++ b/src/share/vm/interpreter/templateInterpreter.cpp
@@ -6932,59 +4273,7 @@ diff --git a/src/share/vm/interpreter/te
address TemplateInterpreter::_throw_NullPointerException_entry = NULL;
address TemplateInterpreter::_throw_StackOverflowError_entry = NULL;
address TemplateInterpreter::_throw_exception_entry = NULL;
-@@ -177,12 +178,14 @@
- #endif // !PRODUCT
- EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries];
- EntryPoint TemplateInterpreter::_earlyret_entry;
-+EntryPoint TemplateInterpreter::_return_unbox_entry;
- EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ];
- EntryPoint TemplateInterpreter::_continuation_entry;
- EntryPoint TemplateInterpreter::_safept_entry;
-
- address TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
- address TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
-+address TemplateInterpreter::_return_5_unbox_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
-
- DispatchTable TemplateInterpreter::_active_table;
- DispatchTable TemplateInterpreter::_normal_table;
-@@ -250,6 +253,22 @@
- }
- }
-
-+ if (InvokeDynamic) {
-+ CodeletMark cm(_masm, "unboxing return entry points");
-+ Interpreter::_return_unbox_entry =
-+ EntryPoint(
-+ generate_return_unbox_entry_for(btos, 5),
-+ generate_return_unbox_entry_for(ctos, 5),
-+ generate_return_unbox_entry_for(stos, 5),
-+ generate_return_unbox_entry_for(atos, 5), // cast conversion
-+ generate_return_unbox_entry_for(itos, 5),
-+ generate_return_unbox_entry_for(ltos, 5),
-+ generate_return_unbox_entry_for(ftos, 5),
-+ generate_return_unbox_entry_for(dtos, 5),
-+ Interpreter::_return_entry[5].entry(vtos) // no unboxing for void
-+ );
-+ }
-+
- { CodeletMark cm(_masm, "earlyret entry points");
- Interpreter::_earlyret_entry =
- EntryPoint(
-@@ -297,8 +316,11 @@
-
- for (int j = 0; j < number_of_states; j++) {
- const TosState states[] = {btos, ctos, stos, itos, ltos, ftos, dtos, atos, vtos};
-- Interpreter::_return_3_addrs_by_index[Interpreter::TosState_as_index(states[j])] = Interpreter::return_entry(states[j], 3);
-- Interpreter::_return_5_addrs_by_index[Interpreter::TosState_as_index(states[j])] = Interpreter::return_entry(states[j], 5);
-+ 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)
-+ Interpreter::_return_5_unbox_addrs_by_index[index] = Interpreter::return_unbox_entry(states[j], 5);
- }
-
- { CodeletMark cm(_masm, "continuation entry points");
-@@ -341,6 +363,7 @@
+@@ -341,6 +342,7 @@
Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" );
Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero");
Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler();
@@ -6992,7 +4281,7 @@ diff --git a/src/share/vm/interpreter/te
Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL );
Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
}
-@@ -358,6 +381,7 @@
+@@ -358,6 +360,7 @@
method_entry(empty)
method_entry(accessor)
method_entry(abstract)
@@ -7000,29 +4289,10 @@ diff --git a/src/share/vm/interpreter/te
method_entry(java_lang_math_sin )
method_entry(java_lang_math_cos )
method_entry(java_lang_math_tan )
-@@ -520,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);
-+}
-+
-+
-+address TemplateInterpreter::return_unbox_entry(TosState state, int length) {
-+ assert(InvokeDynamic, "");
-+ if (state == vtos) {
-+ // no unboxing to do, actually
-+ return return_entry(state, length);
-+ } else {
-+ assert(length == 5, "unboxing entries generated for invokedynamic only");
-+ return _return_unbox_entry.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
-@@ -77,14 +77,15 @@
+@@ -77,6 +77,7 @@
friend class VMStructs;
friend class InterpreterMacroAssembler;
friend class TemplateInterpreterGenerator;
@@ -7030,17 +4300,6 @@ diff --git a/src/share/vm/interpreter/te
friend class TemplateTable;
// friend class Interpreter;
public:
-
- enum MoreConstants {
-- number_of_return_entries = 9, // number of return entry points
-- number_of_deopt_entries = 9, // number of deoptimization entry points
-- number_of_return_addrs = 9 // number of return addresses
-+ number_of_return_entries = number_of_states, // number of return entry points
-+ number_of_deopt_entries = number_of_states, // number of deoptimization entry points
-+ number_of_return_addrs = number_of_states // number of return addresses
- };
-
- protected:
@@ -93,6 +94,7 @@
static address _throw_ArrayStoreException_entry;
static address _throw_ArithmeticException_entry;
@@ -7049,75 +4308,17 @@ diff --git a/src/share/vm/interpreter/te
static address _throw_NullPointerException_entry;
static address _throw_exception_entry;
-@@ -108,12 +110,14 @@
- #endif // !PRODUCT
- static EntryPoint _return_entry[number_of_return_entries]; // entry points to return to from a call
- static EntryPoint _earlyret_entry; // entry point to return early from a call
-+ static EntryPoint _return_unbox_entry; // entry point to unbox a return value from a call
- static EntryPoint _deopt_entry[number_of_deopt_entries]; // entry points to return to from a deoptimization
- static EntryPoint _continuation_entry;
- static EntryPoint _safept_entry;
-
- static address _return_3_addrs_by_index[number_of_return_addrs]; // for invokevirtual return entries
- static address _return_5_addrs_by_index[number_of_return_addrs]; // for invokeinterface return entries
-+ static address _return_5_unbox_addrs_by_index[number_of_return_addrs]; // for invokedynamic bootstrap methods
-
- 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)
-@@ -154,10 +158,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; }
-+ static address* return_5_unbox_addrs_by_index_table() { return _return_5_unbox_addrs_by_index; }
- static int TosState_as_index(TosState state); // computes index into return_3_entry_by_index table
-
- static address return_entry (TosState state, int length);
- static address deopt_entry (TosState state, int length);
-+ static address return_unbox_entry(TosState state, int length);
-
- // Safepoint support
- static void notice_safepoints(); // stops the thread when reaching a safepoint
diff --git a/src/share/vm/interpreter/templateInterpreterGenerator.hpp b/src/share/vm/interpreter/templateInterpreterGenerator.hpp
--- a/src/share/vm/interpreter/templateInterpreterGenerator.hpp
+++ b/src/share/vm/interpreter/templateInterpreterGenerator.hpp
-@@ -48,9 +48,13 @@
+@@ -48,6 +48,7 @@
}
address generate_exception_handler_common(const char* name, const char* message, bool pass_oop);
address generate_ClassCastException_handler();
+ address generate_WrongMethodType_handler();
address generate_ArrayIndexOutOfBounds_handler(const char* name);
address generate_continuation_for(TosState state);
-- address generate_return_entry_for(TosState state, int step);
-+ address generate_return_entry_for(TosState state, int step, bool unbox = false);
-+ address generate_return_unbox_entry_for(TosState state, int step) {
-+ return generate_return_entry_for(state, step, true);
-+ }
- address generate_earlyret_entry_for(TosState state);
- address generate_deopt_entry_for(TosState state, int step);
- address generate_safept_entry_for(TosState state, address runtime_entry);
-diff --git a/src/share/vm/interpreter/templateTable.cpp b/src/share/vm/interpreter/templateTable.cpp
---- a/src/share/vm/interpreter/templateTable.cpp
-+++ b/src/share/vm/interpreter/templateTable.cpp
-@@ -500,6 +500,8 @@
-
- def(Bytecodes::_fast_invokevfinal , ubcp|disp|clvm|____, vtos, vtos, fast_invokevfinal , 2 );
-
-+ // JSR 292 (this is not an externally visible bytecode)
-+ def(Bytecodes::_invokedynamic , ubcp|disp|clvm|____, vtos, vtos, invokedynamic , 1 );
-
- def(Bytecodes::_fast_linearswitch , ubcp|disp|____|____, itos, vtos, fast_linearswitch , _ );
- def(Bytecodes::_fast_binaryswitch , ubcp|disp|____|____, itos, vtos, fast_binaryswitch , _ );
-diff --git a/src/share/vm/interpreter/templateTable.hpp b/src/share/vm/interpreter/templateTable.hpp
---- a/src/share/vm/interpreter/templateTable.hpp
-+++ b/src/share/vm/interpreter/templateTable.hpp
-@@ -260,6 +260,7 @@
- static void invokespecial(int byte_no);
- static void invokestatic(int byte_no);
- static void invokeinterface(int byte_no);
-+ static void invokedynamic(int byte_no);
- static void fast_invokevfinal(int byte_no);
-
- static void getfield_or_static(int byte_no, bool is_static);
+ address generate_return_entry_for(TosState state, int step);
diff --git a/src/share/vm/memory/dump.cpp b/src/share/vm/memory/dump.cpp
--- a/src/share/vm/memory/dump.cpp
+++ b/src/share/vm/memory/dump.cpp
@@ -7131,597 +4332,6 @@ diff --git a/src/share/vm/memory/dump.cp
GenCollectedHeap* gch = GenCollectedHeap::heap();
// At this point, many classes have been loaded.
-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);
- 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();
- }
-
-
-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
-@@ -411,16 +411,16 @@
- // 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) {
-- int i = -1;
-- if (uncached || cache() == NULL) {
-- i = which;
-- } else {
-+ int i = which;
-+ if (!uncached && cache() != NULL) {
- // change byte-ordering and go via cache
-- i = cache()->entry_at(Bytes::swap_u2(which))->constant_pool_index();
-+ i = map_instruction_operand_to_index(which);
- }
- 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 @@
- void constantPoolCacheKlass::oop_copy_contents(PSPromotionManager* pm,
- oop obj) {
- assert(obj->is_constantPoolCache(), "should be constant pool");
-+ if (InvokeDynamic) {
-+ constantPoolCacheOop cache = (constantPoolCacheOop)obj;
-+ // during a scavenge, it is safe to inspect my pool, since it is perm
-+ constantPoolOop pool = cache->constant_pool();
-+ assert(pool->is_constantPool(), "should be constant pool");
-+ if (pool->has_invokedynamic()) {
-+ for (int i = 0; i < cache->length(); i++) {
-+ ConstantPoolCacheEntry* e = cache->entry_at(i);
-+ oop* p = (oop*)&e->_f1;
-+ if (e->is_secondary_entry()) {
-+ if (PSScavenge::should_scavenge(p))
-+ pm->claim_or_forward_breadth(p);
-+ assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)),
-+ "no live oops here");
-+ }
-+ }
-+ }
-+ }
- }
-
- void constantPoolCacheKlass::oop_push_contents(PSPromotionManager* pm,
- oop obj) {
- assert(obj->is_constantPoolCache(), "should be constant pool");
-+ if (InvokeDynamic) {
-+ constantPoolCacheOop cache = (constantPoolCacheOop)obj;
-+ // during a scavenge, it is safe to inspect my pool, since it is perm
-+ constantPoolOop pool = cache->constant_pool();
-+ assert(pool->is_constantPool(), "should be constant pool");
-+ if (pool->has_invokedynamic()) {
-+ for (int i = 0; i < cache->length(); i++) {
-+ ConstantPoolCacheEntry* e = cache->entry_at(i);
-+ oop* p = (oop*)&e->_f1;
-+ if (e->is_secondary_entry()) {
-+ if (PSScavenge::should_scavenge(p))
-+ pm->claim_or_forward_depth(p);
-+ assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)),
-+ "no live oops here");
-+ }
-+ }
-+ }
-+ }
- }
-
- int
-diff --git a/src/share/vm/oops/cpCacheOop.cpp b/src/share/vm/oops/cpCacheOop.cpp
---- a/src/share/vm/oops/cpCacheOop.cpp
-+++ b/src/share/vm/oops/cpCacheOop.cpp
-@@ -29,8 +29,18 @@
- // Implememtation of ConstantPoolCacheEntry
-
- void ConstantPoolCacheEntry::set_initial_state(int index) {
-- assert(0 <= index && index < 0x10000, "sanity check");
-+ if (constantPoolCacheOopDesc::is_secondary_index(index)) {
-+ // Hack: The rewriter is trying to say that this entry itself
-+ // will be a secondary entry.
-+ int main_index = constantPoolCacheOopDesc::decode_secondary_index(index);
-+ assert(0 <= main_index && main_index < 0x10000, "sanity check");
-+ _indices = (main_index << 16);
-+ assert(main_entry_index() == main_index, "");
-+ return;
-+ }
-+ assert(0 < index && index < 0x10000, "sanity check");
- _indices = index;
-+ assert(constant_pool_index() == index, "");
- }
-
-
-@@ -136,6 +146,7 @@
- int byte_no = -1;
- bool needs_vfinal_flag = false;
- switch (invoke_code) {
-+ case Bytecodes::_invokedynamic:
- 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);
-+}
-+
-+
-+void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, int index) {
-+ methodOop method = (methodOop) java_dyn_impl_DynCallSite::vmref(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");
-+ param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic
-+ if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) {
-+ // racing threads might be trying to install their own favorites
-+ set_f1(call_site());
-+ }
-+ set_f2(index);
-+ 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);
- }
-
-
-@@ -392,7 +420,11 @@
- // print separator
- if (index == 0) tty->print_cr(" -------------");
- // print entry
-- tty->print_cr("%3d (%08x) [%02x|%02x|%5d]", index, this, bytecode_2(), bytecode_1(), constant_pool_index());
-+ tty->print_cr("%3d (%08x) ", index, this);
-+ if (is_secondary_entry())
-+ tty->print_cr("[%5d|secondary]", main_entry_index());
-+ else
-+ tty->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
- tty->print_cr(" [ %08x]", (address)(oop)_f1);
- tty->print_cr(" [ %08x]", _f2);
- tty->print_cr(" [ %08x]", _flags);
-diff --git a/src/share/vm/oops/cpCacheOop.hpp b/src/share/vm/oops/cpCacheOop.hpp
---- a/src/share/vm/oops/cpCacheOop.hpp
-+++ b/src/share/vm/oops/cpCacheOop.hpp
-@@ -89,6 +89,8 @@
- // _f1 = method for all but virtual calls, unused by virtual calls
- // (note: for interface calls, which are essentially virtual,
- // contains klassOop for the corresponding interface.
-+// for invokedynamic (a variant of invokeiterface), f1 contains
-+// the CallSite object for the invocation
- // _f2 = method/vtable index for virtual calls only, unused by all other
- // calls. The vf flag indicates this is a method pointer not an
- // index.
-@@ -108,6 +110,8 @@
-
- class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
- friend class VMStructs;
-+ friend class constantPoolCacheKlass;
-+
- private:
- volatile intx _indices; // constant pool index & rewrite bytecodes
- volatile oop _f1; // entry specific oop field
-@@ -175,6 +179,11 @@
- int index // Method index into interface
- );
-
-+ void set_dynamic_call(
-+ Handle call_site, // Resolved java.dyn.CallSite (f1)
-+ int index // index (unused f2)
-+ );
-+
- void set_parameter_size(int value) {
- assert(parameter_size() == 0 || parameter_size() == value,
- "size must not change");
-@@ -216,7 +225,11 @@
- }
-
- // Accessors
-- int constant_pool_index() const { return _indices & 0xFFFF; }
-+ bool is_secondary_entry() const { return (_indices & 0xFFFF) == 0; }
-+ int constant_pool_index() const { assert((_indices & 0xFFFF) != 0, "must be main entry");
-+ return (_indices & 0xFFFF); }
-+ int main_entry_index() const { assert((_indices & 0xFFFF) == 0, "must be secondary entry");
-+ return ((uintx)_indices >> 16); }
- 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 @@
- // Initialization
- void initialize(intArray& inverse_index_map);
-
-+ // Secondary indexes.
-+ // They must look completely different from normal indexes.
-+ // The main reason is that byte swapping is sometimes done on normal indexes.
-+ // Also, it is helpful for debugging to tell the two apart.
-+ static bool is_secondary_index(int i) { return (i < 0); }
-+ static int decode_secondary_index(int i) { assert(is_secondary_index(i), ""); return ~i; }
-+ static int encode_secondary_index(int i) { assert(!is_secondary_index(i), ""); return ~i; }
-+
- // Accessors
- void set_constant_pool(constantPoolOop pool) { oop_store_without_check((oop*)&_constant_pool, (oop)pool); }
- constantPoolOop constant_pool() const { return _constant_pool; }
- ConstantPoolCacheEntry* entry_at(int i) const { assert(0 <= i && i < length(), "index out of bounds"); return base() + i; }
-+ ConstantPoolCacheEntry* main_entry_at(int i) const {
-+ ConstantPoolCacheEntry* e;
-+ if (is_secondary_index(i)) {
-+ // run through an extra level of indirection:
-+ i = decode_secondary_index(i);
-+ e = entry_at(i);
-+ i = e->main_entry_index();
-+ }
-+ e = entry_at(i);
-+ assert(!e->is_secondary_entry(), "only one level of indirection");
-+ return e;
-+ }
-
- // Code generation
- static ByteSize base_offset() { return in_ByteSize(sizeof(constantPoolCacheOopDesc)); }
-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
-@@ -1265,7 +1265,7 @@
- case Bytecodes::_invokespecial:
- case Bytecodes::_invokestatic:
- case Bytecodes::_invokeinterface:
-- int idx = currentBC->get_index_big();
-+ int idx = currentBC->get_index_int();
- constantPoolOop cp = method()->constants();
- int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);
- int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);
-@@ -1296,7 +1296,7 @@
- case Bytecodes::_invokespecial:
- case Bytecodes::_invokestatic:
- case Bytecodes::_invokeinterface:
-- int idx = currentBC->get_index_big();
-+ int idx = currentBC->get_index_int();
- constantPoolOop cp = method()->constants();
- int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);
- int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);
-@@ -1568,7 +1568,7 @@
- case Bytecodes::_invokevirtual:
- case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break;
- case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break;
-- case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break;
-+ case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_int(), itr->bci()); break;
- 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
-@@ -1973,9 +1973,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 {
-@@ -1996,7 +1998,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();
-@@ -2004,22 +2006,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();
- }
- }
-@@ -2028,6 +2030,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 @@
- klassOop _implementors[implementors_limit];
- // Generic signature, or null if none.
- symbolOop _generic_signature;
-+ // invokedynamic bootstrap method (a java.dyn.MethodHandle)
-+ oop _bootstrap_method;
- // 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 @@
- u2 method_index) { _enclosing_method_class_index = class_index;
- _enclosing_method_method_index = method_index; }
-
-+ // JSR 292 support
-+ oop bootstrap_method() const { return _bootstrap_method; }
-+ void set_bootstrap_method(oop mh) { oop_store(&_bootstrap_method, mh); }
-+
- // jmethodID support
- static jmethodID get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
- jmethodID new_id, jmethodID* new_jmeths);
-@@ -715,6 +721,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;}
-+ oop* adr_bootstrap_method() const { return (oop*)&this->_bootstrap_method;}
- oop* adr_methods_jmethod_ids() const { return (oop*)&this->_methods_jmethod_ids;}
- oop* adr_methods_cached_itable_indices() const { return (oop*)&this->_methods_cached_itable_indices;}
- oop* adr_class_annotations() const { return (oop*)&this->_class_annotations;}
-diff --git a/src/share/vm/oops/instanceKlassKlass.cpp b/src/share/vm/oops/instanceKlassKlass.cpp
---- a/src/share/vm/oops/instanceKlassKlass.cpp
-+++ b/src/share/vm/oops/instanceKlassKlass.cpp
-@@ -84,6 +84,7 @@
- MarkSweep::mark_and_push(ik->adr_host_klass());
- MarkSweep::mark_and_push(ik->adr_signers());
- MarkSweep::mark_and_push(ik->adr_generic_signature());
-+ MarkSweep::mark_and_push(ik->adr_bootstrap_method());
- MarkSweep::mark_and_push(ik->adr_class_annotations());
- MarkSweep::mark_and_push(ik->adr_fields_annotations());
- MarkSweep::mark_and_push(ik->adr_methods_annotations());
-@@ -124,6 +125,7 @@
- PSParallelCompact::mark_and_push(cm, ik->adr_host_klass());
- PSParallelCompact::mark_and_push(cm, ik->adr_signers());
- PSParallelCompact::mark_and_push(cm, ik->adr_generic_signature());
-+ PSParallelCompact::mark_and_push(cm, ik->adr_bootstrap_method());
- PSParallelCompact::mark_and_push(cm, ik->adr_class_annotations());
- PSParallelCompact::mark_and_push(cm, ik->adr_fields_annotations());
- PSParallelCompact::mark_and_push(cm, ik->adr_methods_annotations());
-@@ -170,6 +172,7 @@
- blk->do_oop(&ik->adr_implementors()[i]);
- }
- blk->do_oop(ik->adr_generic_signature());
-+ blk->do_oop(ik->adr_bootstrap_method());
- blk->do_oop(ik->adr_class_annotations());
- blk->do_oop(ik->adr_fields_annotations());
- blk->do_oop(ik->adr_methods_annotations());
-@@ -230,6 +233,8 @@
- }
- adr = ik->adr_generic_signature();
- if (mr.contains(adr)) blk->do_oop(adr);
-+ adr = ik->adr_bootstrap_method();
-+ if (mr.contains(adr)) blk->do_oop(adr);
- adr = ik->adr_class_annotations();
- if (mr.contains(adr)) blk->do_oop(adr);
- adr = ik->adr_fields_annotations();
-@@ -274,6 +279,7 @@
- MarkSweep::adjust_pointer(&ik->adr_implementors()[i]);
- }
- MarkSweep::adjust_pointer(ik->adr_generic_signature());
-+ MarkSweep::adjust_pointer(ik->adr_bootstrap_method());
- MarkSweep::adjust_pointer(ik->adr_class_annotations());
- MarkSweep::adjust_pointer(ik->adr_fields_annotations());
- MarkSweep::adjust_pointer(ik->adr_methods_annotations());
-@@ -454,6 +460,7 @@
- ik->set_breakpoints(NULL);
- ik->init_previous_versions();
- ik->set_generic_signature(NULL);
-+ ik->set_bootstrap_method(NULL);
- 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();
- } // 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/klassVtable.cpp b/src/share/vm/oops/klassVtable.cpp
--- a/src/share/vm/oops/klassVtable.cpp
+++ b/src/share/vm/oops/klassVtable.cpp
@@ -7821,18 +4431,16 @@ diff --git a/src/share/vm/oops/methodOop
set_native_function(
SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
!native_bind_event_is_interesting);
-@@ -781,6 +785,140 @@
-
+@@ -782,6 +786,100 @@
// caching this method should be just fine
return false;
-+}
+ }
+
+// Constant pool structure for invoke methods:
+enum {
+ _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
+};
+
@@ -7841,43 +4449,6 @@ diff --git a/src/share/vm/oops/methodOop
+ oop mt = constants()->resolved_string_at(_imcp_method_type_value);
+ assert(mt->klass() == SystemDictionary::java_dyn_MethodType_klass(), "");
+ return mt;
-+}
-+
-+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);
+}
+
+jint* methodOopDesc::method_type_pointer_chase() {
@@ -7897,8 +4468,7 @@ diff --git a/src/share/vm/oops/methodOop
+ Handle method_type, TRAPS) {
+ methodHandle empty;
+
-+ assert(holder() == SystemDictionary::java_dyn_MethodHandle_klass() ||
-+ holder() == SystemDictionary::java_dyn_Dynamic_klass(),
++ assert(holder() == SystemDictionary::java_dyn_MethodHandle_klass(),
+ "must be a JSR 292 magic type");
+
+ if (TraceMethodHandles) {
@@ -7915,7 +4485,6 @@ diff --git a/src/share/vm/oops/methodOop
+ 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:
@@ -7927,7 +4496,6 @@ diff --git a/src/share/vm/oops/methodOop
+ 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);
@@ -7959,13 +4527,15 @@ diff --git a/src/share/vm/oops/methodOop
+ m->print_on(tty);
+
+ return m;
- }
-
-
++}
++
+
+
+ methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
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
-@@ -519,6 +519,27 @@
+@@ -519,6 +519,17 @@
// Reflection support
bool is_overridden_in(klassOop k) const;
@@ -7979,17 +4549,7 @@ diff --git a/src/share/vm/oops/methodOop
+ 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 InvokeDynamic ? 2 : 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 int extra_stack() { return MethodHandles ? 2 : 0; }
// RedefineClasses() support:
bool is_old() const { return access_flags().is_old(); }
void set_is_old() { _access_flags.set_is_old(); }
@@ -8060,81 +4620,11 @@ diff --git a/src/share/vm/oops/oop.inlin
inline int oopDesc::size_given_klass(Klass* klass) {
int lh = klass->layout_helper();
int s = lh >> LogHeapWordSize; // deliver size scaled by wordSize
-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
-@@ -326,7 +326,7 @@
- // stricter than callee_holder->is_initialized()
- ciBytecodeStream iter(caller_method);
- iter.force_bci(caller_bci);
-- int index = iter.get_index_big();
-+ int index = iter.get_index_int();
- if( !caller_method->is_klass_loaded(index, true) ) {
- return false;
- }
-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;
-+ }
-+ 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;
- }
-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
-@@ -662,12 +662,21 @@
- case Bytecodes::_invokeinterface :
- 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);
-+ if (is_invokedynamic)
-+ cpci = Bytes::get_native_u4(bcp+1);
- // cache cannot be pre-fetched since some classes won't have it yet
- ConstantPoolCacheEntry* entry =
-- mh->constants()->cache()->entry_at(Bytes::get_native_u2(bcp+1));
-+ mh->constants()->cache()->main_entry_at(cpci);
- int i = entry->constant_pool_index();
- assert(i < mh->constants()->length(), "sanity check");
- Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering
-+ if (is_invokedynamic) {
-+ ArgumentSizeComputer size_it(mh->constants()->uncached_signature_ref_at(i));
-+ *(p+3) = (unsigned char)(size_it.size() + 1);
-+ *(p+4) = 0;
-+ }
- break;
- }
- }
-diff --git a/src/share/vm/prims/methodComparator.cpp b/src/share/vm/prims/methodComparator.cpp
---- a/src/share/vm/prims/methodComparator.cpp
-+++ b/src/share/vm/prims/methodComparator.cpp
-@@ -148,8 +148,8 @@
- case Bytecodes::_invokespecial : // fall through
- case Bytecodes::_invokestatic : // fall through
- case Bytecodes::_invokeinterface : {
-- u2 cpci_old = _s_old->get_index_big();
-- u2 cpci_new = _s_new->get_index_big();
-+ u2 cpci_old = _s_old->get_index_int();
-+ u2 cpci_new = _s_new->get_index_int();
- // Check if the names of classes, field/method names and signatures at these indexes
- // are the same. Indices which are really into constantpool cache (rather than constant
- // pool itself) are accepted by the constantpool query routines below.
diff --git a/src/share/vm/prims/methodHandles.cpp b/src/share/vm/prims/methodHandles.cpp
new file mode 100644
--- /dev/null
+++ b/src/share/vm/prims/methodHandles.cpp
-@@ -0,0 +1,674 @@
+@@ -0,0 +1,662 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -8750,16 +5240,6 @@ new file mode 100644
+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())
-+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "call site");
-+ java_dyn_impl_DynCallSite::set_target(site_oop, JNIHandles::resolve(target_jh));
-+}
-+JVM_END
-+
-+
+/// JVM_RegisterMethodHandleMethods
+
+#define ADR "J"
@@ -8777,7 +5257,6 @@ new file mode 100644
+#define DMH DYNI"DMH;"
+#define MT DYNP"MethodType;"
+#define MTFM DYNI"MTForm;"
-+#define DCST DYNI"DynCallSite;"
+
+#define CC (char*) /*cast a literal from (const char*)*/
+#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
@@ -8789,8 +5268,7 @@ new file mode 100644
+ {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"linkCallSite", CC"("DCST MH")V", FN_PTR(MH_linkCallSite)}
++ {CC"getVMRef", CC"("MH")"OBJ, FN_PTR(MH_vmref)}
+};
+
+
@@ -9036,16 +5514,10 @@ diff --git a/src/share/vm/runtime/argume
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
-@@ -2508,6 +2508,19 @@
+@@ -2508,6 +2508,13 @@
}
#endif // PRODUCT
-+ if (InvokeDynamic && !MethodHandles) {
-+ if (!FLAG_IS_DEFAULT(MethodHandles)) {
-+ warning("forcing MethodHandles true to support InvokeDynamic");
-+ }
-+ MethodHandles = true;
-+ }
+ if (MethodHandles && !AnonymousClasses) {
+ if (!FLAG_IS_DEFAULT(AnonymousClasses)) {
+ warning("forcing AnonymousClasses true to support MethodHandles");
@@ -9059,7 +5531,7 @@ diff --git a/src/share/vm/runtime/global
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
-@@ -3184,6 +3184,18 @@
+@@ -3184,6 +3184,12 @@
product(bool, AnonymousClasses, false, \
"support sun.misc.Unsafe.defineAnonymousClass") \
\
@@ -9068,12 +5540,6 @@ diff --git a/src/share/vm/runtime/global
+ \
+ develop(bool, TraceMethodHandles, false, \
+ "trace internal method handle operations") \
-+ \
-+ product(bool, InvokeDynamic, false, \
-+ "recognize the invokedynamic instruction") \
-+ \
-+ develop(bool, TraceInvokeDynamic, false, \
-+ "trace internal invoke dynamic operations") \
+ \
product(bool, TaggedStackInterpreter, false, \
"Insert tags in interpreter execution stack for oopmap generaion")\
@@ -9099,10 +5565,12 @@ 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
-@@ -643,48 +643,6 @@
+@@ -641,48 +641,6 @@
+ JRT_ENTRY(void, SharedRuntime::yield_all(JavaThread* thread, int attempts))
+ os::yield_all(attempts);
JRT_END
-
-
+-
+-
-// ---------------------------------------------------------------------------------------------------------
-// Non-product code
-#ifndef PRODUCT
@@ -9143,35 +5611,17 @@ diff --git a/src/share/vm/runtime/shared
-}
-
-#endif // PRODUCT
--
--
+
+
JRT_ENTRY_NO_ASYNC(void, SharedRuntime::register_finalizer(JavaThread* thread, oopDesc* obj))
- assert(obj->is_oop(), "must be a valid oop");
- assert(obj->klass()->klass_part()->has_finalizer(), "shouldn't be here otherwise");
-@@ -781,6 +739,7 @@
- // Find bytecode
- Bytecode_invoke* bytecode = Bytecode_invoke_at(caller, bci);
- bc = bytecode->adjusted_invoke_code();
-+ // @@@ what about tail calls?
- int bytecode_index = bytecode->index();
-
- // Find receiver for non-static call
-@@ -816,6 +775,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");
- 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()) {
-@@ -1481,9 +1441,72 @@
+@@ -1481,9 +1439,72 @@
return generate_class_cast_message(objName, targetKlass->external_name());
}
+char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
+ oopDesc* required,
+ oopDesc* actual) {
-+ assert(InvokeDynamic, "");
++ assert(MethodHandles, "");
+ oop singleKlass = wrong_method_type_is_for_single_argument(thread, required);
+ if (singleKlass != NULL) {
+ const char* objName = "argument or return value";
@@ -9475,41 +5925,6 @@ diff --git a/src/share/vm/utilities/debu
}
-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
-@@ -574,7 +574,7 @@
- inline TosState as_TosState(BasicType type) {
- switch (type) {
- case T_BYTE : return btos;
-- case T_BOOLEAN: return btos;
-+ case T_BOOLEAN: return btos; // FIXME: Add ztos
- case T_CHAR : return ctos;
- case T_SHORT : return stos;
- case T_INT : return itos;
-@@ -586,6 +586,22 @@
- case T_OBJECT : return atos;
- }
- return ilgl;
-+}
-+
-+inline BasicType as_BasicType(TosState state) {
-+ switch (state) {
-+ //case ztos: return T_BOOLEAN;//FIXME
-+ case btos : return T_BYTE;
-+ case ctos : return T_CHAR;
-+ case stos : return T_SHORT;
-+ case itos : return T_INT;
-+ case ltos : return T_LONG;
-+ case ftos : return T_FLOAT;
-+ case dtos : return T_DOUBLE;
-+ case atos : return T_ARRAY;
-+ case vtos : return T_VOID;
-+ }
-+ return T_ILLEGAL;
- }
-
-
diff --git a/src/share/vm/utilities/growableArray.hpp b/src/share/vm/utilities/growableArray.hpp
--- a/src/share/vm/utilities/growableArray.hpp
+++ b/src/share/vm/utilities/growableArray.hpp
--- a/series Mon Sep 01 15:49:33 2008 -0700
+++ b/series Mon Sep 01 22:35:12 2008 -0700
@@ -1,6 +1,6 @@ anonk.patch #-/anonk #+jdk7-b
anonk.patch #-/anonk #+jdk7-b30
meth.patch #-/meth #+jdk7-b30
-annot.patch #-/annot #+jdk7-b30
-#indy.patch #-/indy #+jdk7-b30 #-buildable
+indy.patch #-/indy #+jdk7-b30
+annot.patch #-/annot #+jdk7-b30 #-testable
#inti.patch #-/inti #+jdk7-b30 #-buildable
callcc.patch #-/callcc #+jdk7-b30 #-testable
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/indy.patch Mon Sep 01 22:35:12 2008 -0700
@@ -0,0 +1,3781 @@
+diff --git a/src/cpu/sparc/vm/interp_masm_sparc.cpp b/src/cpu/sparc/vm/interp_masm_sparc.cpp
+--- a/src/cpu/sparc/vm/interp_masm_sparc.cpp
++++ b/src/cpu/sparc/vm/interp_masm_sparc.cpp
+@@ -831,10 +831,26 @@
+ }
+
+
+-void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset) {
++void InterpreterMacroAssembler::get_index_at_bcp(Register Rtmp, Register Rdst,
++ int bcp_offset, bool giant_index) {
++ assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
++ if (!giant_index) {
++ get_2_byte_integer_at_bcp(bcp_offset, Rtmp, Rdst, Unsigned);
++ } else {
++ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
++ 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
++ }
++}
++
++
++void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register tmp,
++ int bcp_offset, bool giant_index) {
+ assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
+ assert_different_registers(cache, tmp);
+ assert_not_delayed();
++ assert(!giant_index,"NYI");
+ 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
+@@ -843,10 +859,12 @@
+ }
+
+
+-void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) {
++void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
++ int bcp_offset, bool giant_index) {
+ assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
+ assert_different_registers(cache, tmp);
+ assert_not_delayed();
++ assert(!giant_index,"NYI");
+ 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 @@
+ // Count a virtual call in the bytecodes.
+
+ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
+- Register scratch) {
++ Register scratch,
++ bool receiver_can_be_null) {
+ if (ProfileInterpreter) {
+ Label profile_continue;
+
+diff --git a/src/cpu/sparc/vm/interp_masm_sparc.hpp b/src/cpu/sparc/vm/interp_masm_sparc.hpp
+--- a/src/cpu/sparc/vm/interp_masm_sparc.hpp
++++ b/src/cpu/sparc/vm/interp_masm_sparc.hpp
+@@ -191,8 +191,9 @@
+ Register Rdst,
+ setCCOrNot should_set_CC = dont_set_CC );
+
+- void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset);
+- void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset);
++ void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
++ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
++ void get_index_at_bcp(Register Rtmp, Register Rdst, int bcp_offset, bool giant_index = false);
+
+
+ // common code
+@@ -304,7 +305,7 @@
+ void profile_not_taken_branch(Register scratch);
+ void profile_call(Register scratch);
+ void profile_final_call(Register scratch);
+- void profile_virtual_call(Register receiver, Register scratch);
++ void profile_virtual_call(Register receiver, Register scratch, bool receiver_can_be_null = false);
+ void profile_ret(TosState state, Register return_bci, Register scratch);
+ void profile_null_seen(Register scratch);
+ void profile_typecheck(Register klass, Register scratch);
+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 @@
+ }
+
+
+-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 (unbox) {
++ incoming_state = atos;
++ }
++ } else {
++ assert(!unbox, "old behavior");
++ }
++
+ address compiled_entry = __ pc();
+ Label cont;
+
+@@ -175,7 +184,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.
+
+- if( state == ltos ) {
++ if( incoming_state == ltos ) {
+ __ srl (G1, 0,O1);
+ __ srlx(G1,32,O0);
+ }
+@@ -192,16 +201,42 @@
+
+ __ mov(Llast_SP, SP); // Remove any adapter added stack space.
+
++ if (unbox && state != atos) {
++ // cast and unbox
++ __ unimplemented();
++ }
+
+ const Register cache = G3_scratch;
+ const Register size = G1_scratch;
++ Label L_got_cache, L_giant_index;
++ if (InvokeDynamic) {
++ __ ldub(Lbcp, 0, size);
++ __ cmp(size, Bytecodes::_invokedynamic);
++ __ br(Assembler::equal, false, Assembler::pn, L_giant_index);
++ __ delayed()->nop();
++ }
+ __ get_cache_and_index_at_bcp(cache, G1_scratch, 1);
++ ////__ get_cache_and_index_at_bcp(cache, G1_scratch, 1, false);
++ __ bind(L_got_cache);
++ if (unbox && state == atos) {
++ // insert a casting conversion, to keep verifier sane
++ __ unimplemented();
++ }
+ __ 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
+ __ add(Lesp, size, Lesp); // pop arguments
+ __ dispatch_next(state, step);
++
++ // out of the main line of code...
++ if (InvokeDynamic) {
++ __ 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
+@@ -3053,6 +3053,20 @@
+ }
+
+
++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");
++ return;
++ }
++
++ __ stop("invokedynamic NYI");
++}
++
++
+ //----------------------------------------------------------------------------------------------------
+ // Allocation
+
+diff --git a/src/cpu/x86/vm/interp_masm_x86_32.cpp b/src/cpu/x86/vm/interp_masm_x86_32.cpp
+--- a/src/cpu/x86/vm/interp_masm_x86_32.cpp
++++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp
+@@ -188,20 +188,33 @@
+ }
+
+
+-void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset) {
++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));
++ } else {
++ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
++ movl(reg, Address(rsi, bcp_offset));
++ assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
++ notl(reg); // convert to plain index
++ }
++}
++
++
++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));
++ get_cache_index_at_bcp(index, bcp_offset, giant_index);
+ movl(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
+ assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
+ shll(index, 2); // convert from field index to ConstantPoolCacheEntry index
+ }
+
+
+-void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) {
+- assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
++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));
++ 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
+@@ -1241,7 +1254,9 @@
+ }
+
+
+-void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp, Register reg2) {
++void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp,
++ Register reg2,
++ bool receiver_can_be_null) {
+ if (ProfileInterpreter) {
+ Label profile_continue;
+
+@@ -1251,8 +1266,15 @@
+ // We are making a call. Increment the count.
+ increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
+
++ Label skip_receiver_profile;
++ if (receiver_can_be_null) {
++ testptr(receiver, receiver);
++ jcc(Assembler::zero, skip_receiver_profile);
++ }
++
+ // Record the receiver type.
+ record_klass_in_profile(receiver, mdp, reg2);
++ bind(skip_receiver_profile);
+
+ // The method data pointer needs to be updated to reflect the new target.
+ update_mdp_by_constant(mdp,
+diff --git a/src/cpu/x86/vm/interp_masm_x86_32.hpp b/src/cpu/x86/vm/interp_masm_x86_32.hpp
+--- a/src/cpu/x86/vm/interp_masm_x86_32.hpp
++++ b/src/cpu/x86/vm/interp_masm_x86_32.hpp
+@@ -76,8 +76,9 @@
+ void get_cpool_and_tags(Register cpool, Register tags) { get_constant_pool(cpool); movl(tags, Address(cpool, constantPoolOopDesc::tags_offset_in_bytes()));
+ }
+ void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
+- void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset);
+- void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset);
++ void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, bool giant_index = false);
++ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
++ void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false);
+
+ // Expression stack
+ void f2ieee(); // truncate ftos to 32bits
+@@ -226,7 +227,8 @@
+ void profile_not_taken_branch(Register mdp);
+ void profile_call(Register mdp);
+ void profile_final_call(Register mdp);
+- void profile_virtual_call(Register receiver, Register mdp, Register scratch2);
++ void profile_virtual_call(Register receiver, Register mdp, Register scratch2,
++ bool receiver_can_be_null = false);
+ void profile_ret(Register return_bci, Register mdp);
+ void profile_null_seen(Register mdp);
+ void profile_typecheck(Register mdp, Register klass, Register scratch);
+diff --git a/src/cpu/x86/vm/interp_masm_x86_64.cpp b/src/cpu/x86/vm/interp_masm_x86_64.cpp
+--- a/src/cpu/x86/vm/interp_masm_x86_64.cpp
++++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp
+@@ -186,12 +186,27 @@
+ }
+
+
++void InterpreterMacroAssembler::get_cache_index_at_bcp(Register index,
++ int bcp_offset,
++ 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));
++ } else {
++ assert(InvokeDynamic, "giant index used only for InvokeDynamic");
++ movl(index, Address(r13, bcp_offset));
++ assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
++ notl(index); // convert to plain index
++ }
++}
++
++
+ void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache,
+ Register index,
+- int bcp_offset) {
+- assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
++ int bcp_offset,
++ bool giant_index) {
+ assert(cache != index, "must use different registers");
+- load_unsigned_word(index, Address(r13, bcp_offset));
++ get_cache_index_at_bcp(index, bcp_offset, giant_index);
+ movq(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
+ assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
+ // convert from field index to ConstantPoolCacheEntry index
+@@ -201,10 +216,10 @@
+
+ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
+ Register tmp,
+- int bcp_offset) {
+- assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
++ int bcp_offset,
++ bool giant_index) {
+ assert(cache != tmp, "must use different register");
+- load_unsigned_word(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
+@@ -1281,7 +1296,8 @@
+
+ void InterpreterMacroAssembler::profile_virtual_call(Register receiver,
+ Register mdp,
+- Register reg2) {
++ Register reg2,
++ bool receiver_can_be_null) {
+ if (ProfileInterpreter) {
+ Label profile_continue;
+
+@@ -1291,8 +1307,15 @@
+ // We are making a call. Increment the count.
+ increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
+
++ Label skip_receiver_profile;
++ if (receiver_can_be_null) {
++ testptr(receiver, receiver);
++ jcc(Assembler::zero, skip_receiver_profile);
++ }
++
+ // Record the receiver type.
+ record_klass_in_profile(receiver, mdp, reg2);
++ bind(skip_receiver_profile);
+
+ // The method data pointer needs to be updated to reflect the new target.
+ update_mdp_by_constant(mdp,
+diff --git a/src/cpu/x86/vm/interp_masm_x86_64.hpp b/src/cpu/x86/vm/interp_masm_x86_64.hpp
+--- a/src/cpu/x86/vm/interp_masm_x86_64.hpp
++++ b/src/cpu/x86/vm/interp_masm_x86_64.hpp
+@@ -94,9 +94,10 @@
+
+ void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
+ void get_cache_and_index_at_bcp(Register cache, Register index,
+- int bcp_offset);
++ int bcp_offset, bool giant_index = false);
+ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
+- int bcp_offset);
++ int bcp_offset, bool giant_index = false);
++ void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false);
+
+ void pop_ptr(Register r = rax);
+ void pop_i(Register r = rax);
+@@ -232,7 +233,8 @@
+ void profile_call(Register mdp);
+ void profile_final_call(Register mdp);
+ void profile_virtual_call(Register receiver, Register mdp,
+- Register scratch2);
++ Register scratch2,
++ bool receiver_can_be_null = false);
+ void profile_ret(Register return_bci, Register mdp);
+ void profile_null_seen(Register mdp);
+ void profile_typecheck(Register mdp, Register klass, Register scratch);
+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 @@
+ }
+
+
+-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 (unbox) {
++ incoming_state = atos;
++ }
++ } else {
++ assert(!unbox, "old behavior");
++ }
++
+ Label interpreter_entry;
+ address compiled_entry = __ pc();
+
+ #ifdef COMPILER2
+ // The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases
+- if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) {
++ if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) {
+ for (int i = 1; i < 8; i++) {
+ __ ffree(i);
+ }
+@@ -180,7 +189,7 @@
+ __ empty_FPU_stack();
+ }
+ #endif
+- if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) {
++ if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) {
+ __ MacroAssembler::verify_FPU(1, "generate_return_entry_for compiled");
+ } else {
+ __ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled");
+@@ -196,12 +205,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.
+- if (state == ftos && UseSSE >= 1) {
++ if (incoming_state == ftos && UseSSE >= 1) {
+ __ subl(rsp, wordSize);
+ __ movflt(Address(rsp, 0), xmm0);
+ __ fld_s(Address(rsp, 0));
+ __ addl(rsp, wordSize);
+- } else if (state == dtos && UseSSE >= 2) {
++ } else if (incoming_state == dtos && UseSSE >= 2) {
+ __ subl(rsp, 2*wordSize);
+ __ movdbl(Address(rsp, 0), xmm0);
+ __ fld_d(Address(rsp, 0));
+@@ -217,13 +226,116 @@
+
+ __ restore_bcp();
+ __ restore_locals();
+- __ get_cache_and_index_at_bcp(rbx, rcx, 1);
++
++ Label L_fail;
++
++ if (unbox && state != atos) {
++ // cast and unbox
++ BasicType type = as_BasicType(state);
++ if (type == T_BYTE) type = T_BOOLEAN; // FIXME
++ KlassHandle boxk = KlassHandles::box_klass(type);
++ __ mov32(rbx, ExternalAddress((address) boxk.raw_value()));
++ __ testl(rax, rax);
++ Label L_got_value, L_get_value;
++ // convert nulls to zeroes (avoid NPEs here)
++ if (!(type == T_FLOAT || type == T_DOUBLE)) {
++ // if rax already contains zero bits, forge ahead
++ __ jcc(Assembler::zero, L_got_value);
++ } else {
++ __ jcc(Assembler::notZero, L_get_value);
++ __ fldz();
++ __ jmp(L_got_value);
++ }
++ __ bind(L_get_value);
++ __ cmp32(rbx, Address(rax, oopDesc::klass_offset_in_bytes()));
++ __ jcc(Assembler::notEqual, L_fail);
++ int offset = java_lang_boxing_object::value_offset_in_bytes(type);
++ // 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;
++ // 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;
++ default: ShouldNotReachHere();
++ }
++ __ bind(L_got_value);
++
++ // put FPU results into xmm0, as above:
++ if (state == ftos && UseSSE >= 1) {
++ __ subl(rsp, wordSize);
++ __ movflt(Address(rsp, 0), xmm0);
++ __ fld_s(Address(rsp, 0));
++ __ addl(rsp, wordSize);
++ } else if (state == dtos && UseSSE >= 2) {
++ __ subl(rsp, 2*wordSize);
++ __ movdbl(Address(rsp, 0), xmm0);
++ __ fld_d(Address(rsp, 0));
++ __ addl(rsp, 2*wordSize);
++ }
++ }
++
++ Label L_got_cache, L_giant_index;
++ if (InvokeDynamic) {
++ __ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic);
++ __ jcc(Assembler::equal, L_giant_index);
++ }
++ __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
++ __ bind(L_got_cache);
++ if (unbox && state == atos) {
++ // insert a casting conversion, to keep verifier sane
++ Label L_ok, L_ok_pops;
++ __ 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(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(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);
++ __ jmp(L_fail);
++
++ __ bind(L_ok_pops);
++ // restore pushed temp regs:
++ __ pop(rcx);
++ __ pop(rbx);
++ __ pop(rax);
++ __ bind(L_ok);
++ }
+ __ movl(rbx, Address(rbx, rcx,
+ Address::times_4, constantPoolCacheOopDesc::base_offset() +
+ ConstantPoolCacheEntry::flags_offset()));
+ __ andl(rbx, 0xFF);
+ __ leal(rsp, Address(rsp, rbx, Interpreter::stackElementScale()));
+ __ dispatch_next(state, step);
++
++ // out of the main line of code...
++ if (InvokeDynamic) {
++ __ bind(L_giant_index);
++ __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
++ __ jmp(L_got_cache);
++
++ if (unbox) {
++ __ bind(L_fail);
++ __ push(rbx); // missed klass (required)
++ __ push(rax); // bad object (actual)
++ __ movptr(rdx, ExternalAddress((address) &Interpreter::_throw_WrongMethodType_entry));
++ __ call(rdx);
++ }
++ }
++
+ return entry;
+ }
+
+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
+@@ -174,7 +174,17 @@
+
+
+ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
+- int step) {
++ int step,
++ bool unbox) {
++ TosState incoming_state = state;
++ if (InvokeDynamic) {
++ if (unbox) {
++ incoming_state = atos;
++ }
++ Unimplemented();
++ } else {
++ assert(!unbox, "old behavior");
++ }
+
+ // amd64 doesn't need to do anything special about compiled returns
+ // to the interpreter so the code that exists on x86 to place a sentinel
+@@ -189,7 +199,13 @@
+
+ __ restore_bcp();
+ __ restore_locals();
+- __ get_cache_and_index_at_bcp(rbx, rcx, 1);
++ Label L_got_cache, L_giant_index;
++ if (InvokeDynamic) {
++ __ cmpb(Address(r13, 0), Bytecodes::_invokedynamic);
++ __ jcc(Assembler::equal, L_giant_index);
++ }
++ __ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
++ __ bind(L_got_cache);
+ __ movl(rbx, Address(rbx, rcx,
+ Address::times_8,
+ in_bytes(constantPoolCacheOopDesc::base_offset()) +
+@@ -198,6 +214,12 @@
+ if (TaggedStackInterpreter) __ shll(rbx, 1); // 2 slots per parameter.
+ __ leaq(rsp, Address(rsp, rbx, Address::times_8));
+ __ dispatch_next(state, step);
++
++ if (InvokeDynamic) {
++ __ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
++ __ jmp(L_got_cache);
++ }
++
+ return entry;
+ }
+
+diff --git a/src/cpu/x86/vm/templateTable_x86_32.cpp b/src/cpu/x86/vm/templateTable_x86_32.cpp
+--- a/src/cpu/x86/vm/templateTable_x86_32.cpp
++++ b/src/cpu/x86/vm/templateTable_x86_32.cpp
+@@ -132,12 +132,12 @@
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, rsi, bc);
+ #ifndef ASSERT
+ __ jmpb(patch_done);
++#else
++ __ jmp(patch_done);
++#endif
+ __ bind(fast_patch);
+ }
+-#else
+- __ jmp(patch_done);
+- __ bind(fast_patch);
+- }
++#ifdef ASSERT
+ Label okay;
+ __ load_unsigned_byte(scratch, at_bcp(0));
+ __ cmpl(scratch, (int)Bytecodes::java_code(bytecode));
+@@ -2015,6 +2015,7 @@
+
+ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) {
+ assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
++ bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
+
+ Register temp = rbx;
+
+@@ -2022,13 +2023,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()));
+- __ shrl(temp, shift_count);
+- // have we resolved this bytecode?
+- __ andl(temp, 0xFF);
+- __ cmpl(temp, (int)bytecode());
+- __ jcc(Assembler::equal, resolved);
++ __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
++ if (is_invokedynamic) {
++ // we are resolved if the f1 field contains a non-null CallSite object
++ __ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
++ __ jcc(Assembler::notEqual, resolved);
++ } else {
++ __ movl(temp, Address(Rcache, index, Address::times_4, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
++ __ shrl(temp, shift_count);
++ // have we resolved this bytecode?
++ __ andl(temp, 0xFF);
++ __ cmpl(temp, (int)bytecode());
++ __ jcc(Assembler::equal, resolved);
++ }
+
+ // resolve first time through
+ address entry;
+@@ -2041,12 +2048,13 @@
+ case Bytecodes::_invokespecial : // fall through
+ case Bytecodes::_invokestatic : // fall through
+ case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
++ case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
+ default : ShouldNotReachHere(); break;
+ }
+ __ movl(temp, (int)bytecode());
+ __ call_VM(noreg, entry, temp);
+ // Update registers with resolved info
+- __ get_cache_and_index_at_bcp(Rcache, index, 1);
++ __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
+ __ bind(resolved);
+ }
+
+@@ -2761,9 +2769,14 @@
+ }
+
+
+-void TemplateTable::prepare_invoke(Register method, Register index, int byte_no, Bytecodes::Code code) {
++void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) {
++ bool neg_byte_no = (byte_no < 0);
++ if (neg_byte_no) byte_no = -byte_no;
++
+ // determine flags
++ Bytecodes::Code code = bytecode();
+ const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
++ const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
+ const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
+ const bool is_invokespecial = code == Bytecodes::_invokespecial;
+ const bool load_receiver = code != Bytecodes::_invokestatic;
+@@ -2773,6 +2786,9 @@
+ const Register recv = rcx;
+ 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();
+@@ -2784,8 +2800,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)));
+- __ verify_oop(recv);
++ Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1));
++ if (is_invokedynamic) {
++ __ lea(recv, recv_addr);
++ } else {
++ __ movptr(recv, recv_addr);
++ __ verify_oop(recv);
++ }
+ }
+
+ // do null check if needed
+@@ -2802,11 +2823,14 @@
+ // Make sure we don't need to mask flags for tosBits after the above shift
+ 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));
++ {
++ address table =
++ (is_invdyn_bootstrap)
++ ? (address)Interpreter::return_5_unbox_addrs_by_index_table()
++ : (is_invokeinterface || is_invokedynamic)
++ ? (address)Interpreter::return_5_addrs_by_index_table()
++ : (address)Interpreter::return_3_addrs_by_index_table();
++ __ movl(flags, Address(noreg, flags, Address::times_4, (int)table));
+ }
+
+ // push return address
+@@ -2868,7 +2892,7 @@
+
+ void TemplateTable::invokevirtual(int byte_no) {
+ transition(vtos, vtos);
+- prepare_invoke(rbx, noreg, byte_no, bytecode());
++ prepare_invoke(rbx, noreg, byte_no);
+
+ // rbx,: index
+ // rcx: receiver
+@@ -2880,7 +2904,7 @@
+
+ void TemplateTable::invokespecial(int byte_no) {
+ transition(vtos, vtos);
+- prepare_invoke(rbx, noreg, byte_no, bytecode());
++ prepare_invoke(rbx, noreg, byte_no);
+ // do the call
+ __ verify_oop(rbx);
+ __ profile_call(rax);
+@@ -2890,7 +2914,7 @@
+
+ void TemplateTable::invokestatic(int byte_no) {
+ transition(vtos, vtos);
+- prepare_invoke(rbx, noreg, byte_no, bytecode());
++ prepare_invoke(rbx, noreg, byte_no);
+ // do the call
+ __ verify_oop(rbx);
+ __ profile_call(rax);
+@@ -2906,7 +2930,7 @@
+
+ void TemplateTable::invokeinterface(int byte_no) {
+ transition(vtos, vtos);
+- prepare_invoke(rax, rbx, byte_no, bytecode());
++ prepare_invoke(rax, rbx, byte_no);
+
+ // rax,: Interface
+ // rbx,: index
+@@ -3056,6 +3080,79 @@
+ // rcx: receiver
+ // rbx,: methodOop
+ __ jump_from_interpreted(rbx, rdx);
++}
++
++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");
++ return;
++ }
++
++ prepare_invoke(rax, rbx, byte_no);
++
++ // rax: CallSite object (f1)
++ // rbx: unused (f2)
++ // rcx: receiver address
++ // rdx: flags (unused)
++
++ if (ProfileInterpreter) {
++ Label L;
++ __ movl(rdx, Address(rcx, 0));
++ __ testl(rdx, rdx);
++ __ jcc(Assembler::zero, L);
++
++ // Get receiver klass into rdx
++ __ movl(rdx, Address(rdx, oopDesc::klass_offset_in_bytes()));
++ __ verify_oop(rdx);
++ __ bind(L);
++
++ // profile this call
++ __ profile_virtual_call(rdx, rsi, rdi, true);
++ }
++
++ Label handle_unlinked_site;
++ __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_impl_DynCallSite::target_offset_in_bytes, rcx)));
++ __ testptr(rcx, rcx);
++ __ jcc(Assembler::zero, handle_unlinked_site);
++
++ __ prepare_to_jump_from_interpreted();
++ __ jump_to_method_handle_entry(rcx, rdx);
++
++ // Initial calls come here...
++ __ bind(handle_unlinked_site);
++ __ pop(rcx); // remove return address pushed by prepare_invoke
++
++ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic);
++ // squish stacked arguments together on stack, preceded by call site
++ // return bootstrap method as a handle in rcx
++ __ restore_bcp(); // rsi must be correct for call_VM
++ __ call_VM(rax, entry, rax);
++ __ movl(rdi, rax); // protect MH from prepare_invoke
++
++ // recompute return address
++ __ restore_bcp(); // rsi must be correct for prepare_invoke
++ prepare_invoke(rax, rbx, -byte_no);
++ // rax: CallSite object (f1)
++ // rbx: unused (f2)
++ // rcx: receiver address (now holds arglist)
++ // rdx: flags
++
++ // save SP now, before we add the bootstrap call to the stack
++ __ prepare_to_jump_from_interpreted();
++
++ // let's play adapter
++ __ pop(rbx); // return value
++ __ push(rdi); // boot MH
++ __ push(rax); // call site
++ __ movptr(rcx, Address(rcx, 0));
++ __ push(rcx); // arglist
++ __ push(rbx); // return value
++ __ mov(rcx, rdi);
++ __ jump_to_method_handle_entry(rcx, rdx);
+ }
+
+ //----------------------------------------------------------------------------------------------------
+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
+@@ -22,8 +22,7 @@
+ *
+ */
+
+- static void prepare_invoke(Register method, Register index, int byte_no,
+- Bytecodes::Code code);
++ static void prepare_invoke(Register method, Register index, int byte_no);
+ static void invokevirtual_helper(Register index, Register recv,
+ Register flags);
+ static void volatile_barrier( );
+diff --git a/src/cpu/x86/vm/templateTable_x86_64.cpp b/src/cpu/x86/vm/templateTable_x86_64.cpp
+--- a/src/cpu/x86/vm/templateTable_x86_64.cpp
++++ b/src/cpu/x86/vm/templateTable_x86_64.cpp
+@@ -144,12 +144,12 @@
+ scratch, r13, bc);
+ #ifndef ASSERT
+ __ jmpb(patch_done);
++#else
++ __ jmp(patch_done);
++#endif
+ __ bind(fast_patch);
+ }
+-#else
+- __ jmp(patch_done);
+- __ bind(fast_patch);
+- }
++#ifdef ASSERT
+ Label okay;
+ __ load_unsigned_byte(scratch, at_bcp(0));
+ __ cmpl(scratch, (int) Bytecodes::java_code(bytecode));
+@@ -1989,6 +1989,7 @@
+ Register Rcache,
+ Register index) {
+ assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
++ bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
+
+ const Register temp = rbx;
+ assert_different_registers(Rcache, index, temp);
+@@ -1996,15 +1997,24 @@
+ 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_8,
+- constantPoolCacheOopDesc::base_offset() +
+- ConstantPoolCacheEntry::indices_offset()));
+- __ shrl(temp, shift_count);
+- // have we resolved this bytecode?
+- __ andl(temp, 0xFF);
+- __ cmpl(temp, (int) bytecode());
+- __ jcc(Assembler::equal, resolved);
++ if (is_invokedynamic) {
++ // we are resolved if the f1 field contains a non-null CallSite object
++ __ cmpptr(Address(Rcache,
++ index, Address::times_ptr,
++ constantPoolCacheOopDesc::base_offset() +
++ ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
++ __ jcc(Assembler::notEqual, resolved);
++ } else {
++ __ 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);
++ __ cmpl(temp, (int) bytecode());
++ __ jcc(Assembler::equal, resolved);
++ }
+
+ // resolve first time through
+ address entry;
+@@ -2021,6 +2031,9 @@
+ case Bytecodes::_invokeinterface:
+ entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
+ break;
++ case Bytecodes::_invokedynamic:
++ entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
++ break;
+ default:
+ ShouldNotReachHere();
+ break;
+@@ -2029,7 +2042,7 @@
+ __ call_VM(noreg, entry, temp);
+
+ // Update registers with resolved info
+- __ get_cache_and_index_at_bcp(Rcache, index, 1);
++ __ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
+ __ bind(resolved);
+ }
+
+@@ -2764,10 +2777,14 @@
+
+ void TemplateTable::prepare_invoke(Register method,
+ Register index,
+- int byte_no,
+- Bytecodes::Code code) {
++ int byte_no) {
++ bool neg_byte_no = (byte_no < 0);
++ if (neg_byte_no) byte_no = -byte_no;
++
+ // determine flags
++ Bytecodes::Code code = bytecode();
+ const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
++ const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
+ const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
+ const bool is_invokespecial = code == Bytecodes::_invokespecial;
+ const bool load_receiver = code != Bytecodes::_invokestatic;
+@@ -2777,6 +2794,9 @@
+ const Register recv = rcx;
+ 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();
+@@ -2788,9 +2808,14 @@
+ __ movl(recv, flags);
+ __ andl(recv, 0xFF);
+ if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
+- __ movq(recv, Address(rsp, recv, Address::times_8,
+- -Interpreter::expr_offset_in_bytes(1)));
+- __ verify_oop(recv);
++ Address recv_addr(rsp, recv, Address::times_8,
++ -Interpreter::expr_offset_in_bytes(1));
++ if (is_invokedynamic) {
++ __ lea(recv, recv_addr);
++ } else {
++ __ movptr(recv, recv_addr);
++ __ verify_oop(recv);
++ }
+ }
+
+ // do null check if needed
+@@ -2808,10 +2833,15 @@
+ ConstantPoolCacheEntry::verify_tosBits();
+ // load return address
+ {
+- 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));
++ address table_addr =
++ (is_invdyn_bootstrap)
++ ? (address)Interpreter::return_5_unbox_addrs_by_index_table()
++ : (is_invokeinterface || is_invokedynamic)
++ ? (address)Interpreter::return_5_addrs_by_index_table()
++ : (address)Interpreter::return_3_addrs_by_index_table();
++ ExternalAddress table(table_addr);
++ __ lea(rscratch1, table);
++ __ movptr(flags, Address(rscratch1, flags, Address::times_ptr));
+ }
+
+ // push return address
+@@ -2877,7 +2907,7 @@
+
+ void TemplateTable::invokevirtual(int byte_no) {
+ transition(vtos, vtos);
+- prepare_invoke(rbx, noreg, byte_no, bytecode());
++ prepare_invoke(rbx, noreg, byte_no);
+
+ // rbx: index
+ // rcx: receiver
+@@ -2889,7 +2919,7 @@
+
+ void TemplateTable::invokespecial(int byte_no) {
+ transition(vtos, vtos);
+- prepare_invoke(rbx, noreg, byte_no, bytecode());
++ prepare_invoke(rbx, noreg, byte_no);
+ // do the call
+ __ verify_oop(rbx);
+ __ profile_call(rax);
+@@ -2899,7 +2929,7 @@
+
+ void TemplateTable::invokestatic(int byte_no) {
+ transition(vtos, vtos);
+- prepare_invoke(rbx, noreg, byte_no, bytecode());
++ prepare_invoke(rbx, noreg, byte_no);
+ // do the call
+ __ verify_oop(rbx);
+ __ profile_call(rax);
+@@ -2913,7 +2943,7 @@
+
+ void TemplateTable::invokeinterface(int byte_no) {
+ transition(vtos, vtos);
+- prepare_invoke(rax, rbx, byte_no, bytecode());
++ prepare_invoke(rax, rbx, byte_no);
+
+ // rax: Interface
+ // rbx: index
+@@ -3080,6 +3110,79 @@
+ // rcx: receiver
+ // rbx: methodOop
+ __ jump_from_interpreted(rbx, rdx);
++}
++
++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");
++ return;
++ }
++
++ prepare_invoke(rax, rbx, byte_no);
++
++ // rax: CallSite object (f1)
++ // rbx: unused (f2)
++ // rcx: receiver address
++ // rdx: flags (unused)
++
++ if (ProfileInterpreter) {
++ Label L;
++ __ movl(rdx, Address(rcx, 0));
++ __ testl(rdx, rdx);
++ __ jcc(Assembler::zero, L);
++
++ // Get receiver klass into rdx
++ __ movl(rdx, Address(rdx, oopDesc::klass_offset_in_bytes()));
++ __ verify_oop(rdx);
++ __ bind(L);
++
++ // profile this call
++ __ profile_virtual_call(rdx, r13, r14, true);
++ }
++
++ Label handle_unlinked_site;
++ __ movptr(rcx, Address(rax, __ delayed_value(java_dyn_impl_DynCallSite::target_offset_in_bytes, rcx)));
++ __ testptr(rcx, rcx);
++ __ jcc(Assembler::zero, handle_unlinked_site);
++
++ __ prepare_to_jump_from_interpreted();
++ __ jump_to_method_handle_entry(rcx, rdx);
++
++ // Initial calls come here...
++ __ bind(handle_unlinked_site);
++ __ pop(rcx); // remove return address pushed by prepare_invoke
++
++ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic);
++ // squish stacked arguments together on stack, preceded by call site
++ // return bootstrap method as a handle in rcx
++ __ restore_bcp(); // rsi must be correct for call_VM
++ __ call_VM(rax, entry, rax);
++ __ movl(rdi, rax); // protect MH from prepare_invoke
++
++ // recompute return address
++ __ restore_bcp(); // rsi must be correct for prepare_invoke
++ prepare_invoke(rax, rbx, -byte_no);
++ // rax: CallSite object (f1)
++ // rbx: unused (f2)
++ // rcx: receiver address (now holds arglist)
++ // rdx: flags
++
++ // save SP now, before we add the bootstrap call to the stack
++ __ prepare_to_jump_from_interpreted();
++
++ // let's play adapter
++ __ pop(rbx); // return value
++ __ push(rdi); // boot MH
++ __ push(rax); // call site
++ __ movptr(rcx, Address(rcx, 0));
++ __ push(rcx); // arglist
++ __ push(rbx); // return value
++ __ mov(rcx, rdi);
++ __ jump_to_method_handle_entry(rcx, rdx);
+ }
+
+ //-----------------------------------------------------------------------------
+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
+@@ -22,8 +22,7 @@
+ *
+ */
+
+- static void prepare_invoke(Register method, Register index, int byte_no,
+- Bytecodes::Code code);
++ static void prepare_invoke(Register method, Register index, int byte_no);
+ static void invokevirtual_helper(Register index, Register recv,
+ Register flags);
+ static void volatile_barrier(Assembler::Membar_mask_bits order_constraint);
+diff --git a/src/share/vm/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) {
+ code = Bytecodes::_invokespecial;
++ }
++
++ if (InvokeDynamic && 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 @@
+ case Bytecodes::_invokespecial : // fall through
+ case Bytecodes::_invokestatic : // fall through
+ case Bytecodes::_invokeinterface: invoke(code); break;
+- case Bytecodes::_xxxunusedxxx : ShouldNotReachHere(); break;
+ case Bytecodes::_new : new_instance(s.get_index_big()); break;
+ case Bytecodes::_newarray : new_type_array(); break;
+ case Bytecodes::_anewarray : new_object_array(); break;
+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();
+ }
+ }
+- break;
+- case Bytecodes::_xxxunusedxxx:
+- ShouldNotReachHere();
+ 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; }
+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
+@@ -303,7 +303,7 @@
+ int ciBytecodeStream::get_method_index() {
+ switch (cur_bc()) {
+ case Bytecodes::_invokeinterface:
+- return Bytes::get_Java_u2(_pc-4);
++ return get_index_int();
+ case Bytecodes::_invokevirtual:
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokestatic:
+diff --git a/src/share/vm/ci/ciStreams.hpp b/src/share/vm/ci/ciStreams.hpp
+--- a/src/share/vm/ci/ciStreams.hpp
++++ b/src/share/vm/ci/ciStreams.hpp
+@@ -91,11 +91,13 @@
+ _end = _start + max;
+ }
+
+- address cur_bcp() { return _bc_start; } // Returns bcp to current instruction
++ address cur_bcp() const { return _bc_start; } // Returns bcp to current instruction
+ int next_bci() const { return _pc -_start; }
+ int cur_bci() const { return _bc_start - _start; }
++ int instruction_size() const { return _pc - _bc_start; }
+
+ Bytecodes::Code cur_bc() const{ return check_java(_bc); }
++ Bytecodes::Code raw_cur_bc() const { return Bytecodes::raw_code_at(cur_bcp()); }
+ 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 @@
+ return check_java(_bc);
+ }
+
+- bool is_wide() { return ( _pc == _was_wide ); }
++ bool is_wide() const { return ( _pc == _was_wide ); }
+
+ // Get a byte index following this bytecode.
+ // If prefixed with a wide bytecode, get a wide index.
+ int get_index() const {
++ assert_index_size(is_wide() ? 2 : 1);
+ return (_pc == _was_wide) // was widened?
+ ? Bytes::get_Java_u2(_bc_start+2) // yes, return wide index
+ : _bc_start[1]; // no, return narrow index
+ }
+
+- // Set a byte index following this bytecode.
+- // If prefixed with a wide bytecode, get a wide index.
+- void put_index(int idx) {
+- if (_pc == _was_wide) // was widened?
+- Bytes::put_Java_u2(_bc_start+2,idx); // yes, set wide index
+- else
+- _bc_start[1]=idx; // no, set narrow index
++ // Get 2-byte index (getfield/putstatic/etc)
++ int get_index_big() const {
++ assert_index_size(2);
++ return Bytes::get_Java_u2(_bc_start+1);
+ }
+
+- // Get 2-byte index (getfield/putstatic/etc)
+- int get_index_big() const { return Bytes::get_Java_u2(_bc_start+1); }
++ // Get 2-byte index (or 4-byte, for invokedynamic)
++ int get_index_int() const {
++ return has_giant_index() ? get_index_giant() : get_index_big();
++ }
++
++ // Get 4-byte index, for invokedynamic.
++ int get_index_giant() const {
++ assert_index_size(4);
++ return Bytes::get_native_u4(_bc_start+1);
++ }
++
++ bool has_giant_index() const { return (raw_cur_bc() == Bytecodes::_invokedynamic); }
+
+ // 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]); }
+@@ -225,6 +232,22 @@
+ ciKlass* get_declared_method_holder();
+ int get_method_holder_index();
+ int get_method_signature_index();
++
++ private:
++ void assert_index_size(int required_size) const {
++#ifdef ASSERT
++ int isize = instruction_size() - (is_wide() ? 1 : 0) - 1;
++ if (isize == 2 && raw_cur_bc() == Bytecodes::_iinc)
++ isize = 1;
++ else if (isize <= 2)
++ ; // no change
++ else if (has_giant_index