--- a/indy.compiler.patch Sat Jun 20 23:56:24 2009 -0700
+++ b/indy.compiler.patch Tue Jun 23 00:28:51 2009 -0700
@@ -1,3 +1,226 @@ diff --git a/src/share/vm/ci/ciCPCache.c
+diff --git a/src/cpu/x86/vm/frame_x86.cpp b/src/cpu/x86/vm/frame_x86.cpp
+--- a/src/cpu/x86/vm/frame_x86.cpp
++++ b/src/cpu/x86/vm/frame_x86.cpp
+@@ -307,6 +307,13 @@
+ }
+ #endif // CC_INTERP
+
++static bool is_method_handle_return(address sender_pc) {
++ u1* pc = (u1*) sender_pc;
++ if (pc[0] == (u1)Assembler::REX)
++ pc++;
++ return (pc[0] == 0x8B && pc[1] == (0xC0 | rsp->encoding() << 3 | rbp->encoding()));
++}
++
+ frame frame::sender_for_entry_frame(RegisterMap* map) const {
+ assert(map != NULL, "map must be set");
+ // Java frame called from C; skip all C frames and return top C
+@@ -331,6 +338,10 @@
+ // This is the sp before any possible extension (adapter/locals).
+ intptr_t* unextended_sp = interpreter_frame_sender_sp();
+
++ address sender_pc = this->sender_pc();
++ if (is_method_handle_return(sender_pc))
++ unextended_sp = (intptr_t*) at(link_offset);
++
+ // The interpreter and compiler(s) always save EBP/RBP in a known
+ // location on entry. We must record where that location is
+ // so this if EBP/RBP was live on callout from c2 we can find
+@@ -353,7 +364,7 @@
+ #endif // AMD64
+ }
+ #endif /* COMPILER2 */
+- return frame(sp, unextended_sp, link(), sender_pc());
++ return frame(sp, unextended_sp, link(), sender_pc);
+ }
+
+
+@@ -376,6 +387,14 @@
+
+ intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset);
+
++ intptr_t* unextended_sp = sender_sp;
++ // If we are returning to a compiled method handle call site,
++ // the saved_fp will in fact be a saved value of the unextended SP.
++ // The simplest way to tell whether we are returning to such a call
++ // site is as follows:
++ if (is_method_handle_return(sender_pc))
++ unextended_sp = saved_fp;
++
+ if (map->update_map()) {
+ // Tell GC to use argument oopmaps for some runtime stubs that need it.
+ // For C1, the runtime stub might not have oop maps, so set this flag
+@@ -400,7 +419,7 @@
+ }
+
+ assert(sender_sp != sp(), "must have changed");
+- return frame(sender_sp, saved_fp, sender_pc);
++ return frame(sender_sp, unextended_sp, saved_fp, sender_pc);
+ }
+
+ frame frame::sender(RegisterMap* map) const {
+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
+@@ -1489,7 +1489,10 @@
+
+ if (interpreter_frame != NULL) {
+ #ifdef ASSERT
+- assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
++ if (!EnableMethodHandles)
++ // @@@ FIXME: Should we correct interpreter_frame_sender_sp in the calling sequences?
++ // Probably, since deoptimization doesn't work yet.
++ assert(caller->unextended_sp() == interpreter_frame->interpreter_frame_sender_sp(), "Frame not properly walkable");
+ assert(caller->sp() == interpreter_frame->sender_sp(), "Frame not properly walkable(2)");
+ #endif
+
+diff --git a/src/cpu/x86/vm/x86_32.ad b/src/cpu/x86/vm/x86_32.ad
+--- a/src/cpu/x86/vm/x86_32.ad
++++ b/src/cpu/x86/vm/x86_32.ad
+@@ -268,22 +268,36 @@
+ static jlong *float_signflip_pool = double_quadword(&fp_signmask_pool[3*2], CONST64(0x8000000080000000), CONST64(0x8000000080000000));
+ static jlong *double_signflip_pool = double_quadword(&fp_signmask_pool[4*2], CONST64(0x8000000000000000), CONST64(0x8000000000000000));
+
++// Offset hacking within calls.
++static int pre_call_FPU_size() {
++ if (Compile::current()->in_24_bit_fp_mode())
++ return 6; // fldcw
++ return 0;
++}
++
++static int preserve_SP_size() {
++ return LP64_ONLY(1 +) 2; // [rex,] op, rm(reg/reg)
++}
++
+ // !!!!! Special hack to get all type of calls to specify the byte offset
+ // from the start of the call to the point where the return address
+ // will point.
+ int MachCallStaticJavaNode::ret_addr_offset() {
+- return 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 5 bytes from start of call to where return address points
++ int offset = 5 + pre_call_FPU_size(); // 5 bytes from start of call to where return address points
++ if (_method_handle_invoke)
++ offset += preserve_SP_size();
++ return offset;
+ }
+
+ int MachCallDynamicJavaNode::ret_addr_offset() {
+- return 10 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0); // 10 bytes from start of call to where return address points
++ return 10 + pre_call_FPU_size(); // 10 bytes from start of call to where return address points
+ }
+
+ static int sizeof_FFree_Float_Stack_All = -1;
+
+ int MachCallRuntimeNode::ret_addr_offset() {
+ assert(sizeof_FFree_Float_Stack_All != -1, "must have been emitted already");
+- return sizeof_FFree_Float_Stack_All + 5 + (Compile::current()->in_24_bit_fp_mode() ? 6 : 0);
++ return sizeof_FFree_Float_Stack_All + 5 + pre_call_FPU_size();
+ }
+
+ // Indicate if the safepoint node needs the polling page as an input.
+@@ -299,8 +313,16 @@
+ // The address of the call instruction needs to be 4-byte aligned to
+ // ensure that it does not span a cache line so that it can be patched.
+ int CallStaticJavaDirectNode::compute_padding(int current_offset) const {
+- if (Compile::current()->in_24_bit_fp_mode())
+- current_offset += 6; // skip fldcw in pre_call_FPU, if any
++ current_offset += pre_call_FPU_size(); // skip fldcw, if any
++ current_offset += 1; // skip call opcode byte
++ return round_to(current_offset, alignment_required()) - current_offset;
++}
++
++// The address of the call instruction needs to be 4-byte aligned to
++// ensure that it does not span a cache line so that it can be patched.
++int CallStaticJavaHandleNode::compute_padding(int current_offset) const {
++ current_offset += pre_call_FPU_size(); // skip fldcw, if any
++ current_offset += preserve_SP_size(); // skip mov rbp, rsp
+ current_offset += 1; // skip call opcode byte
+ return round_to(current_offset, alignment_required()) - current_offset;
+ }
+@@ -308,8 +330,7 @@
+ // The address of the call instruction needs to be 4-byte aligned to
+ // ensure that it does not span a cache line so that it can be patched.
+ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
+- if (Compile::current()->in_24_bit_fp_mode())
+- current_offset += 6; // skip fldcw in pre_call_FPU, if any
++ current_offset += pre_call_FPU_size(); // skip fldcw, if any
+ current_offset += 5; // skip MOV instruction
+ current_offset += 1; // skip call opcode byte
+ return round_to(current_offset, alignment_required()) - current_offset;
+@@ -1765,10 +1786,13 @@
+
+ enc_class pre_call_FPU %{
+ // If method sets FPU control word restore it here
++ debug_only(int off0 = cbuf.code_size());
+ if( Compile::current()->in_24_bit_fp_mode() ) {
+ MacroAssembler masm(&cbuf);
+ masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std()));
+ }
++ debug_only(int off1 = cbuf.code_size());
++ assert(off1 - off0 == pre_call_FPU_size(), "correct size prediction");
+ %}
+
+ enc_class post_call_FPU %{
+@@ -1779,6 +1803,21 @@
+ }
+ %}
+
++ enc_class preserve_SP %{
++ debug_only(int off0 = cbuf.code_size());
++ MacroAssembler _masm(&cbuf);
++ // RBP is preserved across all calls, even compiled calls.
++ // Use it to preserve RSP in places where the callee might change the SP.
++ __ movptr(rbp, rsp);
++ debug_only(int off1 = cbuf.code_size());
++ assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
++ %}
++
++ enc_class restore_SP %{
++ MacroAssembler _masm(&cbuf);
++ __ movptr(rsp, rbp);
++ %}
++
+ enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL
+ // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
+ // who we intended to call.
+@@ -13495,6 +13534,7 @@
+ // compute_padding() functions will have to be adjusted.
+ instruct CallStaticJavaDirect(method meth) %{
+ match(CallStaticJava);
++ predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
+ effect(USE meth);
+
+ ins_cost(300);
+@@ -13509,6 +13549,30 @@
+ ins_alignment(4);
+ %}
+
++// Call Java Static Instruction (method handle version)
++// Note: If this code changes, the corresponding ret_addr_offset() and
++// compute_padding() functions will have to be adjusted.
++instruct CallStaticJavaHandle(method meth, eBPRegP ebp) %{
++ match(CallStaticJava);
++ predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
++ effect(USE meth, KILL ebp);
++ // EBP is saved by all callees (for interpreter stack correction).
++ // We use it here for a similar purpose, in {preserve,restore}_SP.
++
++ ins_cost(300);
++ format %{ "CALL,static/MethodHandle " %}
++ opcode(0xE8); /* E8 cd */
++ ins_encode( pre_call_FPU,
++ preserve_SP,
++ Java_Static_Call( meth ),
++ restore_SP,
++ call_epilog,
++ post_call_FPU );
++ ins_pipe( pipe_slow );
++ ins_pc_relative(1);
++ ins_alignment(4);
++%}
++
+ // Call Java Dynamic Instruction
+ // Note: If this code changes, the corresponding ret_addr_offset() and
+ // compute_padding() functions will have to be adjusted.
diff --git a/src/share/vm/ci/ciCPCache.cpp b/src/share/vm/ci/ciCPCache.cpp
new file mode 100644
--- /dev/null
@@ -123,7 +346,7 @@ diff --git a/src/share/vm/ci/ciEnv.cpp b
diff --git a/src/share/vm/ci/ciEnv.cpp b/src/share/vm/ci/ciEnv.cpp
--- a/src/share/vm/ci/ciEnv.cpp
+++ b/src/share/vm/ci/ciEnv.cpp
-@@ -41,6 +41,7 @@ ciObjArrayKlassKlass* ciEnv::_obj_array
+@@ -41,6 +41,7 @@
ciInstanceKlass* ciEnv::_ArrayStoreException;
ciInstanceKlass* ciEnv::_Class;
ciInstanceKlass* ciEnv::_ClassCastException;
@@ -131,7 +354,7 @@ diff --git a/src/share/vm/ci/ciEnv.cpp b
ciInstanceKlass* ciEnv::_Object;
ciInstanceKlass* ciEnv::_Throwable;
ciInstanceKlass* ciEnv::_Thread;
-@@ -687,6 +688,32 @@ ciMethod* ciEnv::get_method_by_index_imp
+@@ -687,6 +688,32 @@
// ------------------------------------------------------------------
@@ -164,7 +387,7 @@ diff --git a/src/share/vm/ci/ciEnv.cpp b
// ciEnv::get_instance_klass_for_declared_method_holder
ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) {
// For the case of <array>.clone(), the method holder can be a ciArrayKlass
-@@ -708,15 +735,18 @@ ciInstanceKlass* ciEnv::get_instance_kla
+@@ -708,15 +735,18 @@
}
@@ -189,7 +412,7 @@ diff --git a/src/share/vm/ci/ciEnv.hpp b
diff --git a/src/share/vm/ci/ciEnv.hpp b/src/share/vm/ci/ciEnv.hpp
--- a/src/share/vm/ci/ciEnv.hpp
+++ b/src/share/vm/ci/ciEnv.hpp
-@@ -65,6 +65,7 @@ private:
+@@ -65,6 +65,7 @@
static ciInstanceKlass* _ArrayStoreException;
static ciInstanceKlass* _Class;
static ciInstanceKlass* _ClassCastException;
@@ -197,7 +420,7 @@ diff --git a/src/share/vm/ci/ciEnv.hpp b
static ciInstanceKlass* _Object;
static ciInstanceKlass* _Throwable;
static ciInstanceKlass* _Thread;
-@@ -133,6 +134,8 @@ private:
+@@ -133,6 +134,8 @@
int field_index);
ciMethod* get_method_by_index_impl(ciInstanceKlass* loading_klass,
int method_index, Bytecodes::Code bc);
@@ -206,7 +429,7 @@ diff --git a/src/share/vm/ci/ciEnv.hpp b
// Helper methods
bool check_klass_accessibility(ciKlass* accessing_klass,
-@@ -166,6 +169,11 @@ private:
+@@ -166,6 +169,11 @@
return _factory->get_unloaded_method(holder, name, signature);
}
@@ -218,7 +441,7 @@ diff --git a/src/share/vm/ci/ciEnv.hpp b
// Get a ciKlass representing an unloaded klass.
// Ensures uniqueness of the result.
ciKlass* get_unloaded_klass(ciKlass* accessing_klass,
-@@ -269,6 +277,9 @@ public:
+@@ -269,6 +277,9 @@
ciInstanceKlass* ClassCastException_klass() {
return _ClassCastException;
}
@@ -231,7 +454,7 @@ diff --git a/src/share/vm/ci/ciMethod.cp
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
-@@ -131,6 +131,47 @@ ciMethod::ciMethod(ciInstanceKlass* hold
+@@ -131,6 +131,47 @@
// ------------------------------------------------------------------
@@ -279,7 +502,7 @@ diff --git a/src/share/vm/ci/ciMethod.cp
// ciMethod::load_code
//
// Load the bytecodes and exception handler table for this method.
-@@ -677,7 +718,7 @@ int ciMethod::scale_count(int count, flo
+@@ -677,7 +718,7 @@
// ------------------------------------------------------------------
// invokedynamic support
//
@@ -291,7 +514,7 @@ 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
-@@ -75,6 +75,7 @@ class ciMethod : public ciObject {
+@@ -75,6 +75,7 @@
ciMethod(methodHandle h_m);
ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature);
@@ -299,7 +522,7 @@ diff --git a/src/share/vm/ci/ciMethod.hp
methodOop get_methodOop() const {
methodOop m = (methodOop)get_oop();
-@@ -207,7 +208,7 @@ class ciMethod : public ciObject {
+@@ -207,7 +208,7 @@
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
@@ -311,7 +534,7 @@ diff --git a/src/share/vm/ci/ciObject.hp
diff --git a/src/share/vm/ci/ciObject.hpp b/src/share/vm/ci/ciObject.hpp
--- a/src/share/vm/ci/ciObject.hpp
+++ b/src/share/vm/ci/ciObject.hpp
-@@ -113,6 +113,7 @@ public:
+@@ -113,6 +113,7 @@
// What kind of ciObject is this?
virtual bool is_null_object() const { return false; }
@@ -319,7 +542,7 @@ diff --git a/src/share/vm/ci/ciObject.hp
virtual bool is_instance() { return false; }
virtual bool is_method() { return false; }
virtual bool is_method_data() { return false; }
-@@ -167,6 +168,10 @@ public:
+@@ -167,6 +168,10 @@
assert(is_null_object(), "bad cast");
return (ciNullObject*)this;
}
@@ -333,7 +556,7 @@ diff --git a/src/share/vm/ci/ciObjectFac
diff --git a/src/share/vm/ci/ciObjectFactory.cpp b/src/share/vm/ci/ciObjectFactory.cpp
--- a/src/share/vm/ci/ciObjectFactory.cpp
+++ b/src/share/vm/ci/ciObjectFactory.cpp
-@@ -153,6 +153,10 @@ void ciObjectFactory::init_shared_object
+@@ -153,6 +153,10 @@
ciEnv::_ClassCastException =
get(SystemDictionary::ClassCastException_klass())
->as_instance_klass();
@@ -344,7 +567,7 @@ diff --git a/src/share/vm/ci/ciObjectFac
ciEnv::_Object =
get(SystemDictionary::object_klass())
->as_instance_klass();
-@@ -329,6 +333,9 @@ ciObject* ciObjectFactory::create_new_ob
+@@ -329,6 +333,9 @@
} else if (o->is_typeArray()) {
typeArrayHandle h_ta(THREAD, (typeArrayOop)o);
return new (arena()) ciTypeArray(h_ta);
@@ -354,7 +577,7 @@ diff --git a/src/share/vm/ci/ciObjectFac
}
// The oop is of some type not supported by the compiler interface.
-@@ -368,6 +375,44 @@ ciMethod* ciObjectFactory::get_unloaded_
+@@ -368,6 +375,44 @@
}
//------------------------------------------------------------------
@@ -402,7 +625,7 @@ diff --git a/src/share/vm/ci/ciObjectFac
diff --git a/src/share/vm/ci/ciObjectFactory.hpp b/src/share/vm/ci/ciObjectFactory.hpp
--- a/src/share/vm/ci/ciObjectFactory.hpp
+++ b/src/share/vm/ci/ciObjectFactory.hpp
-@@ -93,6 +93,9 @@ public:
+@@ -93,6 +93,9 @@
ciSymbol* name,
ciSymbol* signature);
@@ -415,7 +638,7 @@ diff --git a/src/share/vm/ci/ciStreams.c
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
-@@ -321,7 +321,7 @@ int ciBytecodeStream::get_method_index()
+@@ -321,7 +321,7 @@
//
// If this is a method invocation bytecode, get the invoked method.
ciMethod* ciBytecodeStream::get_method(bool& will_link) {
@@ -424,7 +647,7 @@ diff --git a/src/share/vm/ci/ciStreams.c
will_link = m->is_loaded();
return m;
}
-@@ -339,9 +339,9 @@ ciMethod* ciBytecodeStream::get_method(b
+@@ -339,9 +339,9 @@
// for checking linkability when retrieving the associated method.
ciKlass* ciBytecodeStream::get_declared_method_holder() {
bool ignore;
@@ -436,7 +659,7 @@ diff --git a/src/share/vm/ci/ciStreams.c
return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore);
}
-@@ -370,3 +370,14 @@ int ciBytecodeStream::get_method_signatu
+@@ -370,3 +370,14 @@
int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
return cpool->signature_ref_index_at(name_and_type_index);
}
@@ -454,7 +677,7 @@ diff --git a/src/share/vm/ci/ciStreams.h
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
-@@ -232,6 +232,8 @@ public:
+@@ -232,6 +232,8 @@
int get_method_holder_index();
int get_method_signature_index();
@@ -466,7 +689,7 @@ diff --git a/src/share/vm/ci/ciTypeFlow.
diff --git a/src/share/vm/ci/ciTypeFlow.cpp b/src/share/vm/ci/ciTypeFlow.cpp
--- a/src/share/vm/ci/ciTypeFlow.cpp
+++ b/src/share/vm/ci/ciTypeFlow.cpp
-@@ -1292,8 +1292,8 @@ bool ciTypeFlow::StateVector::apply_one_
+@@ -1292,8 +1292,8 @@
case Bytecodes::_invokeinterface: do_invoke(str, true); break;
case Bytecodes::_invokespecial: do_invoke(str, true); break;
case Bytecodes::_invokestatic: do_invoke(str, false); break;
@@ -479,7 +702,7 @@ diff --git a/src/share/vm/classfile/syst
diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp
--- a/src/share/vm/classfile/systemDictionary.cpp
+++ b/src/share/vm/classfile/systemDictionary.cpp
-@@ -1952,7 +1952,7 @@ void SystemDictionary::initialize_preloa
+@@ -1952,7 +1952,7 @@
scan = WKID(meth_group_end+1);
}
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
@@ -488,10 +711,19 @@ diff --git a/src/share/vm/classfile/syst
initialize_wk_klasses_until(indy_group_start, scan, CHECK);
if (EnableInvokeDynamic) {
initialize_wk_klasses_through(indy_group_start, scan, CHECK);
+@@ -2308,6 +2308,8 @@
+ SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
+ if (spe == NULL || spe->property_oop() == NULL) {
+ // Must create lots of stuff here, but outside of the SystemDictionary lock.
++ if (THREAD->is_Compiler_thread())
++ return NULL; // do not attempt from within compiler
+ Handle mt = compute_method_handle_type(signature(),
+ class_loader, protection_domain,
+ CHECK_NULL);
diff --git a/src/share/vm/classfile/systemDictionary.hpp b/src/share/vm/classfile/systemDictionary.hpp
--- a/src/share/vm/classfile/systemDictionary.hpp
+++ b/src/share/vm/classfile/systemDictionary.hpp
-@@ -144,9 +144,9 @@ class SymbolPropertyTable;
+@@ -144,9 +144,9 @@
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
template(Linkage_klass, java_dyn_Linkage, Opt) \
template(CallSite_klass, java_dyn_CallSite, Opt) \
@@ -519,7 +751,7 @@ diff --git a/src/share/vm/compiler/metho
diff --git a/src/share/vm/compiler/methodLiveness.cpp b/src/share/vm/compiler/methodLiveness.cpp
--- a/src/share/vm/compiler/methodLiveness.cpp
+++ b/src/share/vm/compiler/methodLiveness.cpp
-@@ -782,6 +782,7 @@ void MethodLiveness::BasicBlock::compute
+@@ -782,6 +782,7 @@
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
case Bytecodes::_invokeinterface:
@@ -530,7 +762,7 @@ diff --git a/src/share/vm/includeDB_comp
diff --git a/src/share/vm/includeDB_compiler2 b/src/share/vm/includeDB_compiler2
--- a/src/share/vm/includeDB_compiler2
+++ b/src/share/vm/includeDB_compiler2
-@@ -154,6 +154,7 @@ callGenerator.cpp
+@@ -154,6 +154,7 @@
callGenerator.cpp cfgnode.hpp
callGenerator.cpp compileLog.hpp
callGenerator.cpp connode.hpp
@@ -541,7 +773,7 @@ diff --git a/src/share/vm/includeDB_core
diff --git a/src/share/vm/includeDB_core b/src/share/vm/includeDB_core
--- a/src/share/vm/includeDB_core
+++ b/src/share/vm/includeDB_core
-@@ -532,6 +532,12 @@ ciConstantPoolCache.cpp
+@@ -532,6 +532,12 @@
ciConstantPoolCache.hpp growableArray.hpp
ciConstantPoolCache.hpp resourceArea.hpp
@@ -554,7 +786,7 @@ diff --git a/src/share/vm/includeDB_core
ciEnv.cpp allocation.inline.hpp
ciEnv.cpp ciConstant.hpp
ciEnv.cpp ciEnv.hpp
-@@ -755,6 +761,7 @@ ciObject.hpp
+@@ -755,6 +761,7 @@
ciObject.hpp jniHandles.hpp
ciObjectFactory.cpp allocation.inline.hpp
@@ -565,7 +797,7 @@ diff --git a/src/share/vm/interpreter/by
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
-@@ -102,7 +102,9 @@ methodHandle Bytecode_invoke::static_tar
+@@ -102,7 +102,9 @@
KlassHandle resolved_klass;
constantPoolHandle constants(THREAD, _method->constants());
@@ -579,7 +811,7 @@ diff --git a/src/share/vm/interpreter/by
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
-@@ -210,7 +210,8 @@ class Bytecode_invoke: public ResourceOb
+@@ -210,7 +210,8 @@
bool is_valid() const { return is_invokeinterface() ||
is_invokevirtual() ||
is_invokestatic() ||
@@ -592,7 +824,7 @@ diff --git a/src/share/vm/interpreter/by
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
-@@ -357,7 +357,7 @@ void Bytecodes::initialize() {
+@@ -357,7 +357,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);
@@ -604,7 +836,22 @@ diff --git a/src/share/vm/interpreter/li
diff --git a/src/share/vm/interpreter/linkResolver.cpp b/src/share/vm/interpreter/linkResolver.cpp
--- a/src/share/vm/interpreter/linkResolver.cpp
+++ b/src/share/vm/interpreter/linkResolver.cpp
-@@ -223,6 +223,21 @@ void LinkResolver::resolve_method(method
+@@ -82,6 +82,14 @@
+ // don't force compilation, resolve was on behalf of compiler
+ return;
+ }
++ if (instanceKlass::cast(selected_method->method_holder())->is_not_initialized()) {
++ // Do not force compilation of methods in uninitialized classes.
++ // Note that doing this would throw an assert later,
++ // in CompileBroker::compile_method.
++ // We sometimes use the link resolver to do reflective lookups
++ // even before classes are initialized.
++ return;
++ }
+ CompileBroker::compile_method(selected_method, InvocationEntryBci,
+ methodHandle(), 0, "mustBeCompiled", CHECK);
+ }
+@@ -223,6 +231,21 @@
resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
}
@@ -629,7 +876,7 @@ diff --git a/src/share/vm/interpreter/li
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
-@@ -133,6 +133,7 @@ class LinkResolver: AllStatic {
+@@ -133,6 +133,7 @@
// static resolving for all calls except interface calls
static void resolve_method (methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS);
@@ -640,7 +887,7 @@ diff --git a/src/share/vm/oops/cpCacheOo
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
-@@ -251,6 +251,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_C
+@@ -251,6 +251,7 @@
// Code generation support
static WordSize size() { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); }
@@ -658,7 +905,16 @@ diff --git a/src/share/vm/opto/callGener
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
-@@ -135,6 +135,68 @@ JVMState* DirectCallGenerator::generate(
+@@ -127,6 +127,8 @@
+ }
+ // Mark the call node as virtual, sort of:
+ call->set_optimized_virtual(true);
++ if (method()->is_method_handle_invoke())
++ call->set_method_handle_invoke(true);
+ }
+ kit.set_arguments_for_java_call(call);
+ kit.set_edges_for_java_call(call);
+@@ -135,6 +137,71 @@
return kit.transfer_exceptions_into_jvms();
}
@@ -684,6 +940,7 @@ diff --git a/src/share/vm/opto/callGener
+ ciMethod* caller_method = jvms->method();
+ ciBytecodeStream str(caller_method);
+ str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
++ assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!");
+ ciCPCache* cpcache = str.get_cpcache();
+
+ // Get the offset of the CallSite from the constant pool cache
@@ -706,6 +963,8 @@ diff --git a/src/share/vm/opto/callGener
+ CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), stub, method(), kit.bci());
+ // invokedynamic is treated as an optimized invokevirtual.
+ call->set_optimized_virtual(true);
++ // Take extra care (in the presence of argument motion) not to trash the SP:
++ call->set_method_handle_invoke(true);
+
+ // Pass the MethodHandle as first argument and shift the other
+ // arguments.
@@ -727,7 +986,7 @@ diff --git a/src/share/vm/opto/callGener
class VirtualCallGenerator : public CallGenerator {
private:
int _vtable_index;
-@@ -149,8 +211,6 @@ public:
+@@ -149,8 +216,6 @@
virtual JVMState* generate(JVMState* jvms);
};
@@ -736,7 +995,7 @@ diff --git a/src/share/vm/opto/callGener
JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
GraphKit kit(jvms);
Node* receiver = kit.argument(0);
-@@ -243,6 +303,11 @@ CallGenerator* CallGenerator::for_direct
+@@ -243,8 +308,14 @@
return new DirectCallGenerator(m);
}
@@ -747,11 +1006,14 @@ diff --git a/src/share/vm/opto/callGener
+
CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
assert(!m->is_static(), "for_virtual_call mismatch");
++ assert(!m->is_method_handle_invoke(), "should be a direct call");
return new VirtualCallGenerator(m, vtable_index);
+ }
+
diff --git a/src/share/vm/opto/callGenerator.hpp b/src/share/vm/opto/callGenerator.hpp
--- a/src/share/vm/opto/callGenerator.hpp
+++ b/src/share/vm/opto/callGenerator.hpp
-@@ -93,6 +93,7 @@ class CallGenerator : public ResourceObj
+@@ -93,6 +93,7 @@
// How to generate vanilla out-of-line call sites:
static CallGenerator* for_direct_call(ciMethod* m); // static, special
@@ -759,19 +1021,52 @@ diff --git a/src/share/vm/opto/callGener
static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
// How to make a call but defer the decision whether to inline or not.
+diff --git a/src/share/vm/opto/callnode.hpp b/src/share/vm/opto/callnode.hpp
+--- a/src/share/vm/opto/callnode.hpp
++++ b/src/share/vm/opto/callnode.hpp
+@@ -526,12 +526,15 @@
+ virtual uint size_of() const; // Size is bigger
+
+ bool _optimized_virtual;
++ bool _method_handle_invoke;
+ ciMethod* _method; // Method being direct called
+ public:
+ const int _bci; // Byte Code Index of call byte code
+ CallJavaNode(const TypeFunc* tf , address addr, ciMethod* method, int bci)
+ : CallNode(tf, addr, TypePtr::BOTTOM),
+- _method(method), _bci(bci), _optimized_virtual(false)
++ _method(method), _bci(bci),
++ _optimized_virtual(false),
++ _method_handle_invoke(false)
+ {
+ init_class_id(Class_CallJava);
+ }
+@@ -541,6 +544,8 @@
+ void set_method(ciMethod *m) { _method = m; }
+ void set_optimized_virtual(bool f) { _optimized_virtual = f; }
+ bool is_optimized_virtual() const { return _optimized_virtual; }
++ void set_method_handle_invoke(bool f) { _method_handle_invoke = f; }
++ bool is_method_handle_invoke() const { return _method_handle_invoke; }
+
+ #ifndef PRODUCT
+ virtual void dump_spec(outputStream *st) const;
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
-@@ -222,6 +222,8 @@ CallGenerator* Compile::call_generator(c
+@@ -222,6 +222,12 @@
// Use a more generic tactic, like a simple call.
if (call_is_virtual) {
return CallGenerator::for_virtual_call(call_method, vtable_index);
+ } else if (call_method->is_method_handle_invoke()) {
-+ return CallGenerator::for_dynamic_call(call_method);
++ if (jvms->method()->java_code_at_bci(jvms->bci()) == Bytecodes::_invokedynamic)
++ return CallGenerator::for_dynamic_call(call_method);
++ else
++ // %%% if the target MH is a compile-time constant, we should try to inline it
++ return CallGenerator::for_direct_call(call_method);
} else {
// Class Hierarchy Analysis or Type Profile reveals a unique target,
// or it is a static or special call.
-@@ -240,7 +242,7 @@ bool Parse::can_not_compile_call_site(ci
+@@ -240,7 +246,7 @@
// Interface classes can be loaded & linked and never get around to
// being initialized. Uncommon-trap for not-initialized static or
// v-calls. Let interface calls happen.
@@ -780,7 +1075,7 @@ diff --git a/src/share/vm/opto/doCall.cp
if (!holder_klass->is_initialized() &&
!holder_klass->is_interface()) {
uncommon_trap(Deoptimization::Reason_uninitialized,
-@@ -248,14 +250,6 @@ bool Parse::can_not_compile_call_site(ci
+@@ -248,14 +254,6 @@
holder_klass);
return true;
}
@@ -795,29 +1090,37 @@ diff --git a/src/share/vm/opto/doCall.cp
assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility");
return false;
-@@ -282,7 +276,8 @@ void Parse::do_call() {
+@@ -274,6 +272,7 @@
+ bool is_virtual = bc() == Bytecodes::_invokevirtual;
+ bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface;
+ bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial;
++ bool is_invokedynamic = bc() == Bytecodes::_invokedynamic;
+
+ // Find target being called
+ bool will_link;
+@@ -282,7 +281,8 @@
ciKlass* holder = iter().get_declared_method_holder();
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
- int nargs = dest_method->arg_size();
+ int nargs = dest_method->arg_size();
-+ if (bc() == Bytecodes::_invokedynamic) nargs -= 1;
++ if (is_invokedynamic) nargs -= 1;
// uncommon-trap when callee is unloaded, uninitialized or will not link
// bailout when too many arguments for register representation
-@@ -296,7 +291,7 @@ void Parse::do_call() {
+@@ -296,7 +296,7 @@
return;
}
assert(holder_klass->is_loaded(), "");
- assert(dest_method->is_static() == !has_receiver, "must match bc");
-+ assert((dest_method->is_static() || bc() == Bytecodes::_invokedynamic) == !has_receiver , "must match bc");
++ assert((dest_method->is_static() || is_invokedynamic) == !has_receiver , "must match bc");
// Note: this takes into account invokeinterface of methods declared in java/lang/Object,
// which should be invokevirtuals but according to the VM spec may be invokeinterfaces
assert(holder_klass->is_interface() || holder_klass->super() == NULL || (bc() != Bytecodes::_invokeinterface), "must match bc");
diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp
--- a/src/share/vm/opto/graphKit.cpp
+++ b/src/share/vm/opto/graphKit.cpp
-@@ -950,14 +950,13 @@ bool GraphKit::compute_stack_effects(int
+@@ -950,14 +950,19 @@
case Bytecodes::_invokedynamic:
case Bytecodes::_invokeinterface:
{
@@ -827,17 +1130,69 @@ diff --git a/src/share/vm/opto/graphKit.
iter.reset_to_bci(bci());
iter.next();
ciMethod* method = iter.get_method(ignore);
-- inputs = method->arg_size_no_receiver();
+ inputs = method->arg_size_no_receiver();
- if (!is_static) inputs += 1;
-+ inputs = method->arg_size();
-+ if (code == Bytecodes::_invokedynamic) inputs -= 1;
++ // Add a receiver argument, maybe:
++ if (code != Bytecodes::_invokestatic &&
++ code != Bytecodes::_invokedynamic)
++ inputs += 1;
++ // (Do not use ciMethod::arg_size(), because
++ // it might be an unloaded method, which doesn't
++ // know whether it is static or not.)
int size = method->return_type()->size();
depth = size - inputs;
}
+diff --git a/src/share/vm/opto/machnode.hpp b/src/share/vm/opto/machnode.hpp
+--- a/src/share/vm/opto/machnode.hpp
++++ b/src/share/vm/opto/machnode.hpp
+@@ -662,6 +662,7 @@
+ ciMethod* _method; // Method being direct called
+ int _bci; // Byte Code index of call byte code
+ bool _optimized_virtual; // Tells if node is a static call or an optimized virtual
++ bool _method_handle_invoke; // Tells if the call has to preserve SP
+ MachCallJavaNode() : MachCallNode() {
+ init_class_id(Class_MachCallJava);
+ }
+diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp
+--- a/src/share/vm/opto/matcher.cpp
++++ b/src/share/vm/opto/matcher.cpp
+@@ -985,6 +985,7 @@
+ CallNode *call;
+ const TypeTuple *domain;
+ ciMethod* method = NULL;
++ bool is_method_handle_invoke = false; // for special kill effects
+ if( sfpt->is_Call() ) {
+ call = sfpt->as_Call();
+ domain = call->tf()->domain();
+@@ -1009,6 +1010,8 @@
+ mcall_java->_method = method;
+ mcall_java->_bci = call_java->_bci;
+ mcall_java->_optimized_virtual = call_java->is_optimized_virtual();
++ is_method_handle_invoke = call_java->is_method_handle_invoke();
++ mcall_java->_method_handle_invoke = is_method_handle_invoke;
+ if( mcall_java->is_MachCallStaticJava() )
+ mcall_java->as_MachCallStaticJava()->_name =
+ call_java->as_CallStaticJava()->_name;
+@@ -1122,6 +1125,15 @@
+ mcall->_argsize = out_arg_limit_per_call - begin_out_arg_area;
+ }
+
++ if (is_method_handle_invoke) {
++ // Kill some extra stack space in case method handles want to do
++ // a little in-place argument insertion.
++ int regs_per_word = NOT_LP64(1) LP64_ONLY(2); // %%% make a global const!
++ out_arg_limit_per_call += MethodHandlePushLimit * regs_per_word;
++ // Do not update mcall->_argsize because (a) the extra space is not
++ // pushed as arguments and (b) _argsize is dead (not used anywhere).
++ }
++
+ // Compute the max stack slot killed by any call. These will not be
+ // available for debug info, and will be used to adjust FIRST_STACK_mask
+ // after all call sites have been visited.
diff --git a/src/share/vm/opto/type.cpp b/src/share/vm/opto/type.cpp
--- a/src/share/vm/opto/type.cpp
+++ b/src/share/vm/opto/type.cpp
-@@ -2391,7 +2391,7 @@ const TypeOopPtr* TypeOopPtr::make_from_
+@@ -2391,7 +2391,7 @@
//------------------------------make_from_constant-----------------------------
// Make a java pointer from an oop constant
const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o) {
@@ -846,7 +1201,7 @@ diff --git a/src/share/vm/opto/type.cpp
// Treat much like a typeArray of bytes, like below, but fake the type...
assert(o->has_encoding(), "must be a perm space object");
const Type* etype = (Type*)get_const_basic_type(T_BYTE);
-@@ -3903,7 +3903,7 @@ const TypeFunc *TypeFunc::make(ciMethod*
+@@ -3903,7 +3903,7 @@
const TypeFunc* tf = C->last_tf(method); // check cache
if (tf != NULL) return tf; // The hit rate here is almost 50%.
const TypeTuple *domain;
@@ -858,7 +1213,7 @@ 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
-@@ -801,7 +801,7 @@ Handle SharedRuntime::find_callee_info_h
+@@ -801,7 +801,7 @@
#ifdef ASSERT
// Check that the receiver klass is of the right subtype and that it is initialized for virtual calls
@@ -870,7 +1225,7 @@ diff --git a/src/share/vm/runtime/thread
diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
--- a/src/share/vm/runtime/thread.cpp
+++ b/src/share/vm/runtime/thread.cpp
-@@ -3050,6 +3050,12 @@ jint Threads::create_vm(JavaVMInitArgs*
+@@ -3050,6 +3050,12 @@
warning("java.lang.ArithmeticException has not been initialized");
warning("java.lang.StackOverflowError has not been initialized");
}