--- a/meth.patch Wed Feb 11 16:06:06 2009 -0800
+++ b/meth.patch Sat Mar 21 23:46:04 2009 -0700
@@ -1,431 +1,16 @@ diff --git a/src/cpu/sparc/vm/assembler_
-diff --git a/src/cpu/sparc/vm/assembler_sparc.cpp b/src/cpu/sparc/vm/assembler_sparc.cpp
---- a/src/cpu/sparc/vm/assembler_sparc.cpp
-+++ b/src/cpu/sparc/vm/assembler_sparc.cpp
-@@ -2615,6 +2615,100 @@
- }
- }
-
-+RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
-+ Register tmp,
-+ int offset) {
-+ intptr_t value = *delayed_value_addr;
-+ if (value != 0)
-+ return value + offset;
-+
-+ // load indirectly to solve generation ordering problem
-+ Address a(tmp, (address) delayed_value_addr);
-+ load_ptr_contents(a, tmp);
-+
-+#ifdef ASSERT
-+ tst(tmp);
-+ breakpoint_trap(zero, xcc);
-+#endif
-+
-+ if (offset != 0)
-+ add(tmp, offset, tmp);
-+
-+ return tmp;
-+}
-+
-+
-+void MacroAssembler::lookup_interface_method(Register recv_klass,
-+ Register intf_klass,
-+ RegisterConstant itable_index,
-+ Register method_result,
-+ Register scan_temp,
-+ Label& L_no_such_interface) {
-+ Unimplemented();
-+}
-+
-+
-+// Test sub_klass against super_klass.
-+// Fall through on failure, but branch to L_success if there is a match.
-+// Use up the given temp_reg, but don't kill any other register.
-+// Update the sub's secondary super cache if necesary.
-+void MacroAssembler::check_klass_subtype(Register sub_klass,
-+ Register super_klass,
-+ Register temp_reg,
-+ Label& L_success) {
-+ Unimplemented();
-+}
-+
-+
-+void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg,
-+ Register temp_reg,
-+ Label& wrong_method_type) {
-+ assert_different_registers(mtype_reg, mh_reg, temp_reg);
-+ // compare method type against that of the receiver
-+ RegisterConstant mhtype_offset = delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg);
-+ ld_ptr(mh_reg, mhtype_offset, temp_reg);
-+ cmp(temp_reg, mtype_reg);
-+ br(Assembler::notEqual, false, Assembler::pn, wrong_method_type);
-+ delayed()->nop();
-+}
-+
-+
-+void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
-+ assert(mh_reg == G3_method_handle, "caller must put MH object in G3");
-+ assert_different_registers(mh_reg, temp_reg);
-+
-+ // pick out the interpreted side of the handler
-+ ld_ptr(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg), temp_reg);
-+
-+ // off we go...
-+ ld_ptr(temp_reg, MethodEntry::from_interpreted_entry_offset_in_bytes(), temp_reg);
-+ jmp(temp_reg, 0);
-+
-+ // for the various stubs which take control at this point,
-+ // see MethodHandles::generate_method_handle_stub
-+}
-+
-+RegisterConstant MacroAssembler::argument_offset(RegisterConstant arg_slot,
-+ int extra_slot_offset) {
-+ // cf. TemplateTable::prepare_invoke(), if (load_receiver).
-+ int stackElementSize = Interpreter::stackElementWords() * wordSize;
-+ int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
-+ int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
-+ assert(offset1 - offset == stackElementSize, "correct arithmetic");
-+ if (arg_slot.is_constant()) {
-+ offset += arg_slot.as_constant() * stackElementSize;
-+ return offset;
-+ } else {
-+ Register temp = arg_slot.as_register();
-+ sll_ptr(temp, exact_log2(stackElementSize), temp);
-+ if (offset != 0)
-+ add(temp, offset, temp);
-+ return temp;
-+ }
-+}
-+
-+
-+
- void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
- Register temp_reg,
- Label& done, Label* slow_case,
-diff --git a/src/cpu/sparc/vm/assembler_sparc.hpp b/src/cpu/sparc/vm/assembler_sparc.hpp
---- a/src/cpu/sparc/vm/assembler_sparc.hpp
-+++ b/src/cpu/sparc/vm/assembler_sparc.hpp
-@@ -84,6 +84,10 @@
-
- REGISTER_DECLARATION(Register, Gtemp , G5);
-
-+// JSR 292 fixed register usages:
-+REGISTER_DECLARATION(Register, G5_method_type , G5);
-+REGISTER_DECLARATION(Register, G3_method_handle , G3);
-+
- // The compiler requires that G5_megamorphic_method is G5_inline_cache_klass,
- // because a single patchable "set" instruction (NativeMovConstReg,
- // or NativeMovConstPatching for compiler1) instruction
-@@ -91,9 +95,13 @@
- // call site is an inline cache or is megamorphic. See the function
- // CompiledIC::set_to_megamorphic.
- //
--// On the other hand, G5_inline_cache_klass must differ from G5_method,
--// because both registers are needed for an inline cache that calls
--// an interpreted method.
-+// If a inline cache targets an interpreted method, then the
-+// G5 register will be used twice during the call. First,
-+// the call site will be patched to load a compiledICHolder
-+// into G5. (This is an ordered pair of ic_klass, method.)
-+// The c2i adapter will first check the ic_klass, then load
-+// G5_method with the method part of the pair just before
-+// jumping into the interpreter.
- //
- // Note that G5_method is only the method-self for the interpreter,
- // and is logically unrelated to G5_megamorphic_method.
-@@ -259,6 +267,27 @@
-
- #endif
-
-+// A union type for code which has to assemble both constant and non-constant operands.
-+class RegisterConstant VALUE_OBJ_CLASS_SPEC {
-+ private:
-+ Register _r;
-+ intptr_t _c;
-+
-+ public:
-+ RegisterConstant(): _r(noreg), _c(0) {}
-+ RegisterConstant(Register r): _r(r), _c(0) {}
-+ RegisterConstant(intptr_t c): _r(noreg), _c(c) {}
-+
-+ Register as_register() const { assert(is_register(),""); return _r; }
-+ intptr_t as_constant() const { assert(is_constant(),""); return _c; }
-+
-+ Register register_or_noreg() const { return _r; }
-+ intptr_t constant_or_zero() const { return _c; }
-+
-+ bool is_register() const { return _r != noreg; }
-+ bool is_constant() const { return _r == noreg; }
-+};
-+
- // Address is an abstraction used to represent a memory location.
- //
- // Note: A register location is represented via a Register, not
-@@ -1082,8 +1111,10 @@
- inline void add( Register s1, Register s2, Register d );
- inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none);
- inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec);
-+ inline void add( Register s1, RegisterConstant s2, Register d, int offset = 0);
- inline void add( const Address& a, Register d, int offset = 0);
-
-+
- void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
- void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
- void addc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | rs2(s2) ); }
-@@ -1298,6 +1329,11 @@
- inline void ld( const Address& a, Register d, int offset = 0 );
- inline void ldd( const Address& a, Register d, int offset = 0 );
-
-+ inline void ld( Register s1, RegisterConstant s2, Register d );
-+ inline void lduw( Register s1, RegisterConstant s2, Register d );
-+ inline void ldsw( Register s1, RegisterConstant s2, Register d );
-+ inline void ldx( Register s1, RegisterConstant s2, Register d );
-+
- // pp 177
-
- void ldsba( Register s1, Register s2, int ia, Register d ) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
-@@ -1518,6 +1554,9 @@
- inline void st( Register d, const Address& a, int offset = 0 );
- inline void std( Register d, const Address& a, int offset = 0 );
-
-+ inline void st( Register d, Register s1, RegisterConstant s2 );
-+ inline void stx( Register d, Register s1, RegisterConstant s2 );
-+
- // pp 177
-
- void stba( Register d, Register s1, Register s2, int ia ) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
-@@ -1906,6 +1945,7 @@
- inline void store_ptr_contents( Register s, Address& a, int offset = 0 );
- inline void jumpl_to( Address& a, Register d, int offset = 0 );
- inline void jump_to( Address& a, int offset = 0 );
-+ inline void jump_indirect_to( Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0 );
-
- // ring buffer traceable jumps
-
-@@ -1940,9 +1980,11 @@
- // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's
- inline void ld_ptr( Register s1, Register s2, Register d );
- inline void ld_ptr( Register s1, int simm13a, Register d);
-+ inline void ld_ptr( Register s1, RegisterConstant s2, Register d );
- inline void ld_ptr( const Address& a, Register d, int offset = 0 );
- inline void st_ptr( Register d, Register s1, Register s2 );
- inline void st_ptr( Register d, Register s1, int simm13a);
-+ inline void st_ptr( Register d, Register s1, RegisterConstant s2 );
- inline void st_ptr( Register d, const Address& a, int offset = 0 );
-
- // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's
-@@ -2267,6 +2309,43 @@
- );
- void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
-
-+ // small bootstrap problems
-+ RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp,
-+ int offset = 0);
-+ RegisterConstant delayed_value(int(*value_fn)(), Register tmp,
-+ int offset = 0) {
-+ return delayed_value(delayed_value_addr(value_fn), tmp, offset);
-+ }
-+ RegisterConstant delayed_value(address(*value_fn)(), Register tmp,
-+ int offset = 0) {
-+ return delayed_value((intptr_t*) delayed_value_addr(value_fn), tmp, offset);
-+ }
-+
-+ // interface method calling
-+ void lookup_interface_method(Register recv_klass,
-+ Register intf_klass,
-+ RegisterConstant itable_index,
-+ Register method_result,
-+ Register scan_temp,
-+ Label& no_such_interface);
-+
-+ // method handles (JSR 292)
-+ void check_method_handle_type(Register mtype_reg, Register mh_reg,
-+ Register temp_reg,
-+ Label& wrong_method_type);
-+ void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
-+ // offset relative to Gargs of argument at tos[arg_slot].
-+ // (arg_slot == 0 means the last argument, not the first).
-+ RegisterConstant argument_offset(RegisterConstant arg_slot,
-+ int extra_slot_offset = 0);
-+
-+ // klass type checking (falls through on failure)
-+ void check_klass_subtype(Register sub_klass,
-+ Register super_klass,
-+ Register temp_reg,
-+ Label& L_success);
-+
-+
- // Stack overflow checking
-
- // Note: this clobbers G3_scratch
-diff --git a/src/cpu/sparc/vm/assembler_sparc.inline.hpp b/src/cpu/sparc/vm/assembler_sparc.inline.hpp
---- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp
-+++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp
-@@ -143,6 +143,29 @@
- inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); }
- #endif
-
-+inline void Assembler::ld( Register s1, RegisterConstant s2, Register d) {
-+ if (s2.is_register()) ld(s1, s2.as_register(), d);
-+ else ld(s1, s2.as_constant(), d);
-+}
-+inline void Assembler::ldsw( Register s1, RegisterConstant s2, Register d) {
-+ if (s2.is_register()) ldsw(s1, s2.as_register(), d);
-+ else ldsw(s1, s2.as_constant(), d);
-+}
-+inline void Assembler::lduw( Register s1, RegisterConstant s2, Register d) {
-+ if (s2.is_register()) ldsw(s1, s2.as_register(), d);
-+ else ldsw(s1, s2.as_constant(), d);
-+}
-+inline void Assembler::ldx( Register s1, RegisterConstant s2, Register d) {
-+ if (s2.is_register()) ldx(s1, s2.as_register(), d);
-+ else ldx(s1, s2.as_constant(), d);
-+}
-+
-+// form effective addresses this way:
-+inline void Assembler::add( Register s1, RegisterConstant s2, Register d, int offset) {
-+ if (s2.is_register()) add(s1, s2.as_register(), d);
-+ else { add(s1, s2.as_constant() + offset, d); offset = 0; }
-+ if (offset != 0) add(d, offset, d);
-+}
-
- inline void Assembler::ld( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ld( a.base(), a.disp() + offset, d ); }
- inline void Assembler::ldsb( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsb( a.base(), a.disp() + offset, d ); }
-@@ -200,6 +223,15 @@
- inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); }
- inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); }
-
-+inline void Assembler::st( Register d, Register s1, RegisterConstant s2) {
-+ if (s2.is_register()) st(d, s1, s2.as_register());
-+ else st(d, s1, s2.as_constant());
-+}
-+inline void Assembler::stx( Register d, Register s1, RegisterConstant s2) {
-+ if (s2.is_register()) stx(d, s1, s2.as_register());
-+ else stx(d, s1, s2.as_constant());
-+}
-+
- inline void Assembler::stb( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stb( d, a.base(), a.disp() + offset); }
- inline void Assembler::sth( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); sth( d, a.base(), a.disp() + offset); }
- inline void Assembler::stw( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stw( d, a.base(), a.disp() + offset); }
-@@ -244,6 +276,14 @@
- #endif
- }
-
-+inline void MacroAssembler::ld_ptr( Register s1, RegisterConstant s2, Register d ) {
-+#ifdef _LP64
-+ Assembler::ldx( s1, s2, d);
-+#else
-+ Assembler::ld( s1, s2, d);
-+#endif
-+}
-+
- inline void MacroAssembler::ld_ptr( const Address& a, Register d, int offset ) {
- #ifdef _LP64
- Assembler::ldx( a, d, offset );
-@@ -268,6 +308,14 @@
- #endif
- }
-
-+inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterConstant s2 ) {
-+#ifdef _LP64
-+ Assembler::stx( d, s1, s2);
-+#else
-+ Assembler::st( d, s1, s2);
-+#endif
-+}
-+
- inline void MacroAssembler::st_ptr( Register d, const Address& a, int offset) {
- #ifdef _LP64
- Assembler::stx( d, a, offset);
-@@ -570,6 +618,15 @@
- }
-
-
-+inline void MacroAssembler::jump_indirect_to( Address& a, Register temp,
-+ int ld_offset, int jmp_offset ) {
-+ assert_not_delayed();
-+ //sethi(a); // sethi is caller responsibility for this one
-+ ld_ptr(a, temp, ld_offset);
-+ jmp(temp, jmp_offset);
-+}
-+
-+
- inline void MacroAssembler::set_oop( jobject obj, Register d ) {
- set_oop(allocate_oop_address(obj, d));
- }
-diff --git a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
---- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
-+++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp
-@@ -1017,6 +1017,7 @@
- const int slop_factor = 2*wordSize;
-
- const int fixed_size = ((sizeof(BytecodeInterpreter) + slop_factor) >> LogBytesPerWord) + // what is the slop factor?
-+ 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
-
-@@ -1163,6 +1164,8 @@
- __ st_ptr(O2, XXX_STATE(_stack)); // PREPUSH
-
- __ lduh(max_stack, O3); // Full size expression stack
-+ if (MethodHandle)
-+ __ 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
-@@ -2017,7 +2020,9 @@
-
- const int fixed_size = sizeof(BytecodeInterpreter)/wordSize + // interpreter state object
- frame::memory_parameter_word_sp_offset; // register save area + param window
-- return (round_to(max_stack +
-+ const int extra_stack = methodOopDesc::extra_stack();
-+ return (round_to(max_stack +
-+ extra_stack +
- slop_factor +
- fixed_size +
- monitor_size +
-@@ -2104,7 +2109,8 @@
- // Need +1 here because stack_base points to the word just above the first expr stack entry
- // and stack_limit is supposed to point to the word just below the last expr stack entry.
- // See generate_compute_interpreter_state.
-- to_fill->_stack_limit = stack_base - (method->max_stack() + 1);
-+ int extra_stack = methodOopDesc::extra_stack();
-+ to_fill->_stack_limit = stack_base - (method->max_stack() + 1 + extra_stack);
- to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
-
- // sparc specific
-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
-@@ -29,6 +29,7 @@
- address generate_normal_entry(bool synchronized);
- address generate_native_entry(bool synchronized);
- address generate_abstract_entry(void);
-+ address generate_method_handle_entry(void);
- address generate_math_entry(AbstractInterpreter::MethodKind kind);
- address generate_empty_entry(void);
- address generate_accessor_entry(void);
+changes entrained after 6655638 appear in meth.patch proper
+
diff --git a/src/cpu/sparc/vm/interpreter_sparc.cpp b/src/cpu/sparc/vm/interpreter_sparc.cpp
--- a/src/cpu/sparc/vm/interpreter_sparc.cpp
+++ b/src/cpu/sparc/vm/interpreter_sparc.cpp
-@@ -235,6 +235,37 @@
- }
-
-
-+#ifdef ASSERT
-+address last_WrongMethodType_caller;
-+#endif //ASSERT
-+
-+
-+// Method handle invoker
-+// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
-+address InterpreterGenerator::generate_method_handle_entry(void) {
-+ if (!MethodHandleSupport) {
-+ return generate_abstract_entry();
-+ }
+@@ -242,7 +242,21 @@
+ if (!EnableMethodHandles) {
+ return generate_abstract_entry();
+ }
+- return generate_abstract_entry(); //6815692//
++#error remove everywhere: //6815692//
+
+ // incoming registers: O0 (mh), G5 (mtype), O1... (args)
-+ Register G5_mtype = G5_inline_cache_reg;
+ Register O0_recv = O0;
+
+ Label wrong_method_type;
@@ -433,94 +18,23 @@ diff --git a/src/cpu/sparc/vm/interprete
+
+ __ bind(wrong_method_type);
+ __ mov(O0_recv, O1); // bad mh (actual)
-+ __ mov(G5_mtype, O0); // missed mtype (required)
++ __ mov(G5_method_type, O0); // missed mtype (required)
+ DEBUG_ONLY(__ get_pc(O2));
+ __ throw_if_not_x(Assembler::never, Interpreter::_throw_WrongMethodType_entry, G3_scratch);
+
+ return entry_point;
-+}
-+
-+
-+
-+
- //----------------------------------------------------------------------------------------------------
- // Entry points & stack frame layout
- //
-@@ -364,6 +395,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;
-+ case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
- case Interpreter::java_lang_math_sin : break;
- case Interpreter::java_lang_math_cos : break;
- case Interpreter::java_lang_math_tan : break;
+ }
+
+
diff --git a/src/cpu/sparc/vm/methodHandles_sparc.cpp b/src/cpu/sparc/vm/methodHandles_sparc.cpp
-new file mode 100644
---- /dev/null
+--- a/src/cpu/sparc/vm/methodHandles_sparc.cpp
+++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp
-@@ -0,0 +1,443 @@
-+/*
-+ * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ *
-+ * This code is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 only, as
-+ * published by the Free Software Foundation.
-+ *
-+ * This code is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+ * version 2 for more details (a copy is included in the LICENSE file that
-+ * accompanied this code).
-+ *
-+ * You should have received a copy of the GNU General Public License version
-+ * 2 along with this work; if not, write to the Free Software Foundation,
-+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-+ * CA 95054 USA or visit www.sun.com if you need additional information or
-+ * have any questions.
-+ *
-+ */
-+
-+#include "incls/_precompiled.incl"
-+#include "incls/_methodHandles_sparc.cpp.incl"
-+
-+#define __ _masm->
-+
-+address MethodEntry::start_compiled_entry(MacroAssembler* _masm,
-+ address interpreted_entry) {
-+ __ align(wordSize);
-+ address target = __ pc() + sizeof(Data);
-+ while (__ pc() < target) {
-+ __ nop();
-+ __ align(wordSize);
-+ }
-+
-+ MethodEntry* me = (MethodEntry*) __ pc();
-+ me->set_end_address(__ pc()); // set a temporary end_address
-+ me->set_from_interpreted_entry(interpreted_entry);
-+ me->set_type_checking_entry(NULL);
-+
-+ return (address) me;
-+}
-+
-+MethodEntry* MethodEntry::finish_compiled_entry(MacroAssembler* _masm,
-+ address start_addr) {
-+ MethodEntry* me = (MethodEntry*) start_addr;
-+ assert(me->end_address() == start_addr, "valid ME");
-+
-+ // Fill in the real end_address:
-+ __ align(wordSize);
-+ me->set_end_address(__ pc());
-+
-+ return me;
-+}
-+
-+
-+// Code generation
-+address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm,
-+ Label& wrong_method_type) {
+@@ -60,12 +60,385 @@
+ // Code generation
+ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm,
+ Label& wrong_method_type) {
+- ShouldNotReachHere(); //NYI, 6815692
+- return NULL;
+ // I5_savedSP: sender SP (must preserve)
+ // G4 (Gargs): incoming argument list (must preserve)
+ // G5_method: invoke methodOop; becomes method type.
@@ -536,7 +50,7 @@ new file mode 100644
+ // fetch the MethodType from the method handle into G5_method_type
+ {
+ Register tem = G5_method;
-+ for (int* pchase = methodOopDesc::method_type_pointer_chase(); (*pchase) != -1; pchase++) {
++ for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) {
+ __ ld_ptr(tem, *pchase, G5_method_type);
+ tem = G5_method_type; // yes, it's the same register...
+ }
@@ -560,23 +74,24 @@ new file mode 100644
+ __ ba(false, wrong_method_type);
+ __ delayed()->nop();
+
-+ address me_cookie = MethodEntry::start_compiled_entry(_masm, wmt_jump_addr);
++ address me_cookie = MethodHandleEntry::start_compiled_entry(_masm, wmt_jump_addr);
+ __ unimplemented("compiled _wrong_method_type NYI"); // %%% FIXME
-+ init_entry(_wrong_method_type, MethodEntry::finish_compiled_entry(_masm, me_cookie));
++ init_entry(_wrong_method_type, MethodHandleEntry::finish_compiled_entry(_masm, me_cookie));
+
+ return entry_point;
-+}
-+
-+// Generate an "entry" field for a method handle.
-+// This determines how the method handle will respond to calls.
-+void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
+ }
+
+ // Generate an "entry" field for a method handle.
+ // This determines how the method handle will respond to calls.
+ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
+- ShouldNotReachHere(); //NYI, 6815692
++ ShouldNotReachHere();
++#if 0
+ // Here is the register state during an interpreted call,
+ // as set up by generate_method_handle_interpreter_entry():
+ // - G5: garbage temp (was MethodHandle.invoke methodOop, unused)
+ // - O0: receiver method handle
-+ // - rax: method handle type (already checked at call site, then unused)
-+ // - rsi: sender SP (must preserve)
-+ // - rdx: garbage temp, can blow away
++ // - I5_savedSP: sender SP (must preserve)
+
+ Register O0_argslot = O0;
+ Register O1_scratch = O1;
@@ -607,7 +122,7 @@ new file mode 100644
+ __ bind(wrong_method_type);
+ Address wmt_entry(O1_scratch, (address) &_entries[_wrong_method_type]);
+ __ load_ptr_contents(wmt_entry, O1_scratch);
-+ Address wmt_fie(O1_scratch, 0, MethodEntry::from_interpreted_entry_offset_in_bytes());
++ Address wmt_fie(O1_scratch, 0, MethodHandleEntry::from_interpreted_entry_offset_in_bytes());
+ __ jump_indirect_to(wmt_fie, O1_scratch);
+ __ delayed()->nop();
+
@@ -773,7 +288,7 @@ new file mode 100644
+ // 'argslot' is number of slots to drop
+ // this is also the rightmost (shallowest) kept argument slot
+ __ lduw(G3_mh_vmargslot, O0_argslot);
-+ RegisterConstant arg = __ argument_offset(O0_argslot);
++ RegisterOrConstant arg = __ argument_offset(O0_argslot);
+ __ add(Gargs, arg, Gargs); // pop some arguments
+ }
+
@@ -798,7 +313,7 @@ new file mode 100644
+ __ lduw(G3_mh_vmargslot, O0_argslot);
+ if (ak == _adapt_extend_zero || ak == _adapt_extend_sign)
+ __ lduw(G3_mh_vmindex, G5_index);
-+ RegisterConstant arg = __ argument_offset(O0_argslot);
++ RegisterOrConstant arg = __ argument_offset(O0_argslot);
+
+ // get the new MH:
+ __ ld_ptr(G3_amh_target, G3_method_handle);
@@ -846,7 +361,7 @@ new file mode 100644
+ // check an argument, or perform a simple in-place conversion,
+ // before jumping to the next layer of MH:
+ __ lduw(G3_mh_vmargslot, O0_argslot);
-+ RegisterConstant arg = __ argument_offset(O0_argslot);
++ RegisterOrConstant arg = __ argument_offset(O0_argslot);
+
+ // What class are we casting to?
+ __ ld_ptr(G3_mh_vmref, G5_klass);
@@ -876,7 +391,7 @@ new file mode 100644
+
+ Address wmt_entry(O1_scratch, (address) &_entries[_wrong_method_type]);
+ __ load_ptr_contents(wmt_entry, O1_scratch);
-+ Address wmt_fie(O1_scratch, 0, MethodEntry::from_interpreted_entry_offset_in_bytes());
++ Address wmt_fie(O1_scratch, 0, MethodHandleEntry::from_interpreted_entry_offset_in_bytes());
+ __ jump_indirect_to(wmt_fie, O1_scratch);
+
+ __ bind(done);
@@ -897,533 +412,31 @@ new file mode 100644
+ default: ShouldNotReachHere();
+ }
+
-+ address me_cookie = MethodEntry::start_compiled_entry(_masm, interp_entry);
++ address me_cookie = MethodHandleEntry::start_compiled_entry(_masm, interp_entry);
+ __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
+
-+ init_entry(ek, MethodEntry::finish_compiled_entry(_masm, me_cookie));
-+}
-diff --git a/src/cpu/sparc/vm/register_definitions_sparc.cpp b/src/cpu/sparc/vm/register_definitions_sparc.cpp
---- a/src/cpu/sparc/vm/register_definitions_sparc.cpp
-+++ b/src/cpu/sparc/vm/register_definitions_sparc.cpp
-@@ -142,6 +142,8 @@
- REGISTER_DEFINITION(Register, G3_scratch);
- REGISTER_DEFINITION(Register, G4_scratch);
- REGISTER_DEFINITION(Register, Gtemp);
-+REGISTER_DEFINITION(Register, G5_method_type);
-+REGISTER_DEFINITION(Register, G3_method_handle);
- REGISTER_DEFINITION(Register, Lentry_args);
-
- #ifdef CC_INTERP
-diff --git a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
---- a/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
-+++ b/src/cpu/sparc/vm/sharedRuntime_sparc.cpp
-@@ -937,12 +937,12 @@
- // Inputs:
- // G2_thread - TLS
- // G5_method - Method oop
-- // O0 - Flag telling us to restore SP from O5
-- // O4_args - Pointer to interpreter's args
-- // O5 - Caller's saved SP, to be restored if needed
-+ // G4 (Gargs) - Pointer to interpreter's args
-+ // O0..O4 - free for scratch
-+ // O5_savedSP - Caller's saved SP, to be restored if needed
- // O6 - Current SP!
- // O7 - Valid return address
-- // L0-L7, I0-I7 - Caller's temps (no frame pushed yet)
-+ // L0-L7, I0-I7 - Caller's temps (no frame pushed yet)
-
- // Outputs:
- // G2_thread - TLS
-@@ -954,7 +954,7 @@
- // F0-F7 - more outgoing args
-
-
-- // O4 is about to get loaded up with compiled callee's args
-+ // Gargs is the incoming argument base, and also an outgoing argument.
- __ sub(Gargs, BytesPerWord, Gargs);
-
- #ifdef ASSERT
-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 @@
++ init_entry(ek, MethodHandleEntry::finish_compiled_entry(_masm, me_cookie));
++#endif
}
-
-
-+#ifdef ASSERT
-+address last_WrongMethodType_caller;
-+#endif //ASSERT
-+
-+// Arguments are: required type in G5_method_type, and
-+// failing object (or NULL) in G3_method_handle.
-+// In the debug build, the caller should put his own PC in G1.
-+address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
-+ address entry = __ pc();
-+#ifdef ASSERT
-+ Address last_caller_addr(O3, (address)&last_WrongMethodType_caller);
-+ __ sethi(last_caller_addr);
-+ __ st_ptr(G1, last_caller_addr);
-+#endif //ASSERT
-+ // expression stack must be empty before entering the VM if an exception
-+ // happened
-+ __ empty_expression_stack();
-+ // load exception object
-+ __ call_VM(Oexception,
-+ CAST_FROM_FN_PTR(address,
-+ 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
-@@ -448,6 +476,7 @@
-
- const int extra_space =
- rounded_vm_local_words + // frame local scratch space
-+ 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 +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);
-- const int max_stack_words = max_stack * Interpreter::stackElementWords();
-+ const int extra_stack = methodOopDesc::extra_stack();
-+ const int max_stack_words = (max_stack + extra_stack) * Interpreter::stackElementWords();
- return (round_to((max_stack_words
- + rounded_vm_local_words
- + frame::memory_parameter_word_sp_offset), WordsPerLong)
-diff --git a/src/cpu/x86/vm/assembler_x86.cpp b/src/cpu/x86/vm/assembler_x86.cpp
---- a/src/cpu/x86/vm/assembler_x86.cpp
-+++ b/src/cpu/x86/vm/assembler_x86.cpp
-@@ -6244,6 +6244,28 @@
- return off;
- }
-
-+void MacroAssembler::load_sized_value(Register dst, Address src,
-+ int size_in_bytes, bool is_signed) {
-+ switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
-+#ifndef _LP64
-+ // For case 8, caller is responsible for manually loading
-+ // the high word into another register.
-+ case ~8: // fall through:
-+ case 8: movl( dst, src ); break;
-+#else
-+ case ~8: // fall through:
-+ case 8: movq( dst, src ); break;
-+#endif
-+ case ~4: // fall through:
-+ case 4: movl( dst, src ); break;
-+ case ~2: load_signed_word( dst, src ); break;
-+ case 2: load_unsigned_word( dst, src ); break;
-+ case ~1: load_signed_byte( dst, src ); break;
-+ case 1: load_unsigned_byte( dst, src ); break;
-+ default: ShouldNotReachHere();
-+ }
-+}
-+
- void MacroAssembler::mov32(AddressLiteral dst, Register src) {
- if (reachable(dst)) {
- movl(as_Address(dst), src);
-@@ -7094,6 +7116,241 @@
- }
-
-
-+RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, Register tmp) {
-+ intptr_t value = *delayed_value_addr;
-+ if (value != 0)
-+ return value;
-+ movptr(tmp, ExternalAddress((address) delayed_value_addr));
-+#ifdef ASSERT
-+ Label L;
-+ testl(tmp, tmp);
-+ jccb(Assembler::notZero, L);
-+ hlt();
-+ bind(L);
-+#endif
-+ return tmp;
-+}
-+
-+
-+void MacroAssembler::lookup_interface_method(Register recv_klass,
-+ Register intf_klass,
-+ RegisterConstant itable_index,
-+ Register method_result,
-+ Register scan_temp,
-+ Label& L_no_such_interface) {
-+ assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
-+ assert(itable_index.is_constant() || itable_index.as_register() == method_result,
-+ "caller must use same register for non-constant itable index as for method");
-+
-+ // Compute start of first itableOffsetEntry (which is at the end of the vtable)
-+ int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
-+ int scan_step = itableOffsetEntry::size() * wordSize;
-+ int vte_size = vtableEntry::size() * wordSize;
-+ Address::ScaleFactor times_vte_scale = Address::times_ptr;
-+ assert(vte_size == wordSize, "else adjust times_vte_scale");
-+
-+ movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize));
-+ lea( scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base));
-+ if (HeapWordsPerLong > 1) {
-+ // Round up to align_object_offset boundary
-+ round_to(scan_temp, BytesPerLong);
-+ }
-+
-+ // Adjust recv_klass by scaled itable_index, so we can free itable_index.
-+ assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
-+ lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr));
-+
-+ // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
-+ // if (scan->interface() == intf) {
-+ // result = (klass + scan->offset() + itable_index);
-+ // }
-+ // }
-+ Label search, found_method;
-+
-+ for (int peel = 1; peel >= 0; peel--) {
-+ movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes()));
-+ cmpptr(intf_klass, method_result);
-+ jccb(Assembler::notEqual, search);
-+
-+ // Got a hit.
-+ movl(method_result, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
-+ movptr(method_result, Address(recv_klass, method_result, Address::times_1));
-+
-+ if (!peel) break;
-+ jmp(found_method);
-+
-+ bind(search);
-+ // Check that the previous entry is non-null. A null entry means that
-+ // the reciever class doesn't implement the interface, and wasn't the
-+ // same as when the caller was compiled.
-+ testptr(method_result, method_result);
-+ jcc(Assembler::zero, L_no_such_interface);
-+ addptr(scan_temp, scan_step);
-+ }
-+
-+ bind(found_method);
-+}
-+
-+
-+// Test sub_klass against super_klass.
-+// Fall through on failure, but branch to L_success if there is a match.
-+// Use up the given temp_reg, but don't kill any other register.
-+// Update the sub's secondary super cache if necesary.
-+void MacroAssembler::check_klass_subtype(Register sub_klass,
-+ Register super_klass,
-+ Register temp_reg,
-+ Label& L_success) {
-+ Label L_failure; // fallthrough label
-+
-+ assert_different_registers(sub_klass, super_klass, temp_reg);
-+
-+ // a couple of useful fields in sub_klass:
-+ int ss_offset = (klassOopDesc::header_size() * HeapWordSize +
-+ Klass::secondary_supers_offset_in_bytes());
-+ int sc_offset = (klassOopDesc::header_size() * HeapWordSize +
-+ Klass::secondary_super_cache_offset_in_bytes());
-+ Address secondary_supers_addr(sub_klass, ss_offset);
-+ Address super_cache_addr( sub_klass, sc_offset);
-+
-+ int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
-+ Klass::super_check_offset_offset_in_bytes());
-+ Address super_check_offset_addr(super_klass, sco_offset);
-+
-+ // if the pointers are equal, we are done (e.g., String[] elements)
-+ cmpptr(sub_klass, super_klass);
-+ jcc(Assembler::equal, L_success);
-+
-+ // check the supertype display:
-+ movl(temp_reg, super_check_offset_addr);
-+ Address super_check_addr(sub_klass, temp_reg, Address::times_1, 0);
-+ cmpptr(super_klass, super_check_addr); // load displayed supertype
-+ jcc(Assembler::equal, L_success);
-+
-+ // if it was a primary super, we can just fail immediately
-+ cmpl(temp_reg, sc_offset);
-+ jcc(Assembler::notEqual, L_failure);
-+
-+ // Now do a linear scan of the secondary super-klass chain.
-+ // This code is rarely used, so simplicity is a virtue here.
-+ {
-+ // The repne_scan instruction uses fixed registers, which we must spill.
-+ // Don't bother to figure out pre-existing connections with the input regs.
-+ push(rax);
-+ push(rcx);
-+ push(rdi);
-+ push(super_klass);
-+
-+ movptr(rdi, secondary_supers_addr);
-+ // Load the array length.
-+ movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
-+ // Skip to start of data.
-+ addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
-+ // Scan rcx words at [edi] for occurance of rax,
-+ // Set NZ/Z based on last compare
-+ pop(rax); // super_klass value, even if it was in rdi or rcx
-+
-+
-+#ifdef _LP64
-+ // This part is tricky, as values in supers array could be 32 or 64 bit wide
-+ // and we store values in objArrays always encoded, thus we need to encode
-+ // the value of rax before repne. Note that rax is dead after the repne.
-+ if (UseCompressedOops) {
-+ encode_heap_oop_not_null(rax);
-+ repne_scanl();
-+ } else
-+#endif // _LP64
-+ repne_scan();
-+
-+ // Unspill the temp. registers:
-+ pop(rdi);
-+ pop(rcx);
-+ pop(rax);
-+ }
-+ jcc(Assembler::notEqual, L_failure);
-+
-+ // Success. Cache the super we found and proceed in triumph.
-+ movptr(super_cache_addr, super_klass);
-+
-+ jmp(L_success);
-+
-+ // Fall through on failure!
-+ bind(L_failure);
-+}
-+
-+
-+// registers on entry:
-+// - rax ('check' register): required MethodType
-+// - rcx: method handle
-+// - rdx, rsi, or ?: killable temp
-+void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg,
-+ Register temp_reg,
-+ Label& wrong_method_type) {
-+ if (UseCompressedOops) unimplemented(); // field accesses must decode
-+ // compare method type against that of the receiver
-+ cmpptr(mtype_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
-+ jcc(Assembler::notEqual, wrong_method_type);
-+}
-+
-+
-+void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg,
-+ Register temp_reg) {
-+ if (UseCompressedOops) unimplemented(); // field accesses must decode
-+ // load mh.type.form.vmslots
-+ if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) {
-+ // hoist vmslots into every mh to avoid dependent load chain
-+ movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)));
-+ } else {
-+ Register temp2_reg = vmslots_reg;
-+ movptr(temp2_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
-+ movptr(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)));
-+ movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)));
-+ }
-+}
-+
-+
-+// registers on entry:
-+// - rcx: method handle
-+// - rdx: killable temp (interpreted only)
-+// - rax: killable temp (compiled only)
-+void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
-+ assert(mh_reg == rcx, "caller must put MH object in rcx");
-+ assert_different_registers(mh_reg, temp_reg);
-+
-+ if (UseCompressedOops) unimplemented(); // field accesses must decode
-+
-+ // pick out the interpreted side of the handler
-+ movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg)));
-+
-+ // off we go...
-+ jmp(Address(temp_reg, MethodEntry::from_interpreted_entry_offset_in_bytes()));
-+
-+ // for the various stubs which take control at this point,
-+ // see MethodHandles::generate_method_handle_stub
-+}
-+
-+
-+Address MacroAssembler::argument_address(RegisterConstant arg_slot,
-+ int extra_slot_offset) {
-+ // cf. TemplateTable::prepare_invoke(), if (load_receiver).
-+ int stackElementSize = Interpreter::stackElementSize();
-+ int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
-+#ifdef ASSERT
-+ int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
-+ assert(offset1 - offset == stackElementSize, "correct arithmetic");
-+#endif
-+ Register scale_reg = noreg;
-+ Address::ScaleFactor scale_factor = Address::no_scale;
-+ if (arg_slot.is_constant()) {
-+ offset += arg_slot.as_constant() * stackElementSize;
-+ } else {
-+ scale_reg = arg_slot.as_register();
-+ scale_factor = Address::times(stackElementSize);
-+ }
-+ offset += wordSize; // return PC is on stack
-+ return Address(rsp, scale_reg, scale_factor, offset);
-+}
-+
-+
- void MacroAssembler::verify_oop_addr(Address addr, const char* s) {
- if (!VerifyOops) return;
-
-diff --git a/src/cpu/x86/vm/assembler_x86.hpp b/src/cpu/x86/vm/assembler_x86.hpp
---- a/src/cpu/x86/vm/assembler_x86.hpp
-+++ b/src/cpu/x86/vm/assembler_x86.hpp
-@@ -135,6 +135,27 @@
-
- #endif // _LP64
-
-+// A union type for code which has to assemble both constant and non-constant operands.
-+class RegisterConstant VALUE_OBJ_CLASS_SPEC {
-+ private:
-+ Register _r;
-+ intptr_t _c;
-+
-+ public:
-+ RegisterConstant(): _r(noreg), _c(0) {}
-+ RegisterConstant(Register r): _r(r), _c(0) {}
-+ RegisterConstant(intptr_t c): _r(noreg), _c(c) {}
-+
-+ Register as_register() const { assert(is_register(),""); return _r; }
-+ intptr_t as_constant() const { assert(is_constant(),""); return _c; }
-+
-+ Register register_or_noreg() const { return _r; }
-+ intptr_t constant_or_zero() const { return _c; }
-+
-+ bool is_register() const { return _r != noreg; }
-+ bool is_constant() const { return _r == noreg; }
-+};
-+
- // Address is an abstraction used to represent a memory location
- // using any of the amd64 addressing modes with one object.
- //
-@@ -154,6 +175,14 @@
- times_ptr = LP64_ONLY(times_8) NOT_LP64(times_4)
- };
-
-+ static ScaleFactor times(int size) {
-+ assert(size >= 1 && size <= 8 && is_power_of_2(size), "bad scale size");
-+ if (size == 8) return times_8;
-+ if (size == 4) return times_4;
-+ if (size == 2) return times_2;
-+ return times_1;
-+ }
-+
- private:
- Register _base;
- Register _index;
-@@ -197,6 +226,22 @@
- "inconsistent address");
+diff --git a/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
+--- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp
++++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp
+@@ -2887,6 +2887,16 @@
+
+ // arraycopy stubs used by compilers
+ generate_arraycopy_stubs();
++
++ // generic method handle stubs
++ if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) {
++ for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
++ ek < MethodHandles::_EK_LIMIT;
++ ek = MethodHandles::EntryKind(1 + (int)ek)) {
++ StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
++ MethodHandles::generate_method_handle_stub(_masm, ek);
++ }
++ }
}
-+ Address(Register base, RegisterConstant index, ScaleFactor scale = times_1, int disp = 0)
-+ : _base (base),
-+ _index(index.register_or_noreg()),
-+ _scale(scale),
-+ _disp (disp + (index.constant_or_zero() * scale_size(scale))) {
-+ if (!index.is_register()) scale = Address::no_scale;
-+ assert(!_index->is_valid() == (scale == Address::no_scale),
-+ "inconsistent address");
-+ }
-+
-+ Address plus_disp(int disp) {
-+ Address result = (*this);
-+ result._disp += disp;
-+ return result;
-+ }
-+
- // The following two overloads are used in connection with the
- // ByteSize type (see sizes.hpp). They simplify the use of
- // ByteSize'd arguments in assembly code. Note that their equivalent
-@@ -224,6 +269,17 @@
- assert(!index->is_valid() == (scale == Address::no_scale),
- "inconsistent address");
- }
-+
-+ Address(Register base, RegisterConstant index, ScaleFactor scale, ByteSize disp)
-+ : _base (base),
-+ _index(index.register_or_noreg()),
-+ _scale(scale),
-+ _disp (in_bytes(disp) + (index.constant_or_zero() * scale_size(scale))) {
-+ if (!index.is_register()) scale = Address::no_scale;
-+ assert(!_index->is_valid() == (scale == Address::no_scale),
-+ "inconsistent address");
-+ }
-+
- #endif // ASSERT
-
- // accessors
-@@ -240,6 +296,14 @@
-
- static Address make_array(ArrayAddress);
-
-+ static int scale_size(ScaleFactor scale) {
-+ assert(scale != no_scale, "");
-+ assert(((1 << (int)times_1) == 1 &&
-+ (1 << (int)times_2) == 2 &&
-+ (1 << (int)times_4) == 4 &&
-+ (1 << (int)times_8) == 8), "");
-+ return (1 << (int)scale);
-+ }
-
- private:
- bool base_needs_rex() const {
-@@ -1404,6 +1468,9 @@
- // Support for sign-extension (hi:lo = extend_sign(lo))
- void extend_sign(Register hi, Register lo);
-
-+ // Loading values by size and signed-ness
-+ void load_sized_value(Register dst, Address src, int size_in_bytes, bool is_signed);
-+
- // Support for inc/dec with optimal instruction selection depending on value
-
- void increment(Register reg, int value = 1) { LP64_ONLY(incrementq(reg, value)) NOT_LP64(incrementl(reg, value)) ; }
-@@ -1721,6 +1788,39 @@
- );
- void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
-
-+ // small bootstrap problems
-+ RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp);
-+ RegisterConstant delayed_value(int(*value_fn)(), Register tmp) {
-+ return delayed_value(delayed_value_addr(value_fn), tmp);
-+ }
-+ RegisterConstant delayed_value(address(*value_fn)(), Register tmp) {
-+ return delayed_value((intptr_t*) delayed_value_addr(value_fn), tmp);
-+ }
-+
-+ // interface method calling
-+ void lookup_interface_method(Register recv_klass,
-+ Register intf_klass,
-+ RegisterConstant itable_index,
-+ Register method_result,
-+ Register scan_temp,
-+ Label& no_such_interface);
-+
-+ // method handles (JSR 292)
-+ void check_method_handle_type(Register mtype_reg, Register mh_reg,
-+ Register temp_reg,
-+ Label& wrong_method_type);
-+ void load_method_handle_vmslots(Register vmslots_reg, Register mh_reg,
-+ Register temp_reg);
-+ void jump_to_method_handle_entry(Register mh_reg, Register temp_reg);
-+ Address argument_address(RegisterConstant arg_slot, int extra_slot_offset = 0);
-+
-+
-+ // klass type checking (falls through on failure)
-+ void check_klass_subtype(Register sub_klass,
-+ Register super_klass,
-+ Register temp_reg,
-+ Label& L_success);
-+
- //----
- void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
diff --git a/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp b/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp
--- a/src/cpu/x86/vm/cppInterpreterGenerator_x86.hpp
@@ -1436,1386 +449,68 @@ diff --git a/src/cpu/x86/vm/cppInterpret
address generate_math_entry(AbstractInterpreter::MethodKind kind);
address generate_empty_entry(void);
address generate_accessor_entry(void);
-diff --git a/src/cpu/x86/vm/cppInterpreter_x86.cpp b/src/cpu/x86/vm/cppInterpreter_x86.cpp
---- a/src/cpu/x86/vm/cppInterpreter_x86.cpp
-+++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp
-@@ -513,10 +513,11 @@
- // compute full expression stack limit
-
- const Address size_of_stack (rbx, methodOopDesc::max_stack_offset());
-+ const int extra_stack = methodOopDesc::extra_stack() * Interpreter::stackElementSize;
- __ load_unsigned_word(rdx, size_of_stack); // get size of expression stack in words
- __ negptr(rdx); // so we can subtract in next step
- // Allocate expression stack
-- __ lea(rsp, Address(rsp, rdx, Address::times_ptr));
-+ __ lea(rsp, Address(rsp, rdx, Address::times_ptr, -extra_stack));
- __ movptr(STATE(_stack_limit), rsp);
- }
-
-@@ -659,8 +660,9 @@
- // Always give one monitor to allow us to start interp if sync method.
- // Any additional monitors need a check when moving the expression stack
- const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize;
-+ const int extra_stack = methodOopDesc::extra_stack() * Interpreter::stackElementSize;
- __ load_unsigned_word(rax, size_of_stack); // get size of expression stack in words
-- __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor));
-+ __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), extra_stack + one_monitor));
- __ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
-
- #ifdef ASSERT
-@@ -2185,6 +2187,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;
-+ case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
-
- case Interpreter::java_lang_math_sin : // fall thru
- case Interpreter::java_lang_math_cos : // fall thru
-@@ -2224,7 +2227,8 @@
- const int overhead_size = sizeof(BytecodeInterpreter)/wordSize +
- ( frame::sender_sp_offset - frame::link_offset) + 2;
-
-- const int method_stack = (method->max_locals() + method->max_stack()) *
-+ const int extra_stack = methodOopDesc::extra_stack();
-+ const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
- Interpreter::stackElementWords();
- return overhead_size + method_stack + stub_code;
- }
-@@ -2289,7 +2293,8 @@
- // Need +1 here because stack_base points to the word just above the first expr stack entry
- // and stack_limit is supposed to point to the word just below the last expr stack entry.
- // See generate_compute_interpreter_state.
-- to_fill->_stack_limit = stack_base - (method->max_stack() + 1);
-+ int extra_stack = methodOopDesc::extra_stack();
-+ to_fill->_stack_limit = stack_base - (method->max_stack() + extra_stack + 1);
- to_fill->_monitor_base = (BasicObjectLock*) monitor_base;
-
- to_fill->_self_link = to_fill;
-@@ -2335,7 +2340,8 @@
- monitor_size);
-
- // Now with full size expression stack
-- int full_frame_size = short_frame_size + method->max_stack() * BytesPerWord;
-+ int extra_stack = methodOopDesc::extra_stack();
-+ int full_frame_size = short_frame_size + (method->max_stack() + extra_stack) * BytesPerWord;
-
- // and now with only live portion of the expression stack
- short_frame_size = short_frame_size + tempcount * BytesPerWord;
-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
-@@ -586,13 +586,18 @@
- }
-
-
--// Jump to from_interpreted entry of a call unless single stepping is possible
--// in this thread in which case we must call the i2i entry
--void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
-+void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
- // set sender sp
- lea(rsi, Address(rsp, wordSize));
- // record last_sp
- movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), rsi);
-+}
-+
-+
-+// Jump to from_interpreted entry of a call unless single stepping is possible
-+// in this thread in which case we must call the i2i entry
-+void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
-+ prepare_to_jump_from_interpreted();
-
- if (JvmtiExport::can_post_interpreter_events()) {
- Label run_compiled_code;
-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
-@@ -161,6 +161,7 @@
-
-
- // jump to an invoked target
-+ void prepare_to_jump_from_interpreted();
- void jump_from_interpreted(Register method, Register temp);
-
- // Returning from interpreted functions
-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
-@@ -603,13 +603,18 @@
- MacroAssembler::call_VM_leaf_base(entry_point, 3);
- }
-
--// Jump to from_interpreted entry of a call unless single stepping is possible
--// in this thread in which case we must call the i2i entry
--void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
-+void InterpreterMacroAssembler::prepare_to_jump_from_interpreted() {
- // set sender sp
- lea(r13, Address(rsp, wordSize));
- // record last_sp
- movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), r13);
-+}
-+
-+
-+// Jump to from_interpreted entry of a call unless single stepping is possible
-+// in this thread in which case we must call the i2i entry
-+void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register temp) {
-+ prepare_to_jump_from_interpreted();
-
- if (JvmtiExport::can_post_interpreter_events()) {
- Label run_compiled_code;
-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
-@@ -176,6 +176,7 @@
- void dispatch_via (TosState state, address* table);
-
- // jump to an invoked target
-+ void prepare_to_jump_from_interpreted();
- void jump_from_interpreted(Register method, Register temp);
-
-
-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
-@@ -32,6 +32,7 @@
- address generate_normal_entry(bool synchronized);
- address generate_native_entry(bool synchronized);
- address generate_abstract_entry(void);
-+ address generate_method_handle_entry(void);
- address generate_math_entry(AbstractInterpreter::MethodKind kind);
- address generate_empty_entry(void);
- address generate_accessor_entry(void);
-diff --git a/src/cpu/x86/vm/interpreter_x86_32.cpp b/src/cpu/x86/vm/interpreter_x86_32.cpp
---- a/src/cpu/x86/vm/interpreter_x86_32.cpp
-+++ b/src/cpu/x86/vm/interpreter_x86_32.cpp
-@@ -201,11 +201,12 @@
- address entry_point = __ pc();
-
- // abstract method entry
-- // remove return address. Not really needed, since exception handling throws away expression stack
-- __ pop(rbx);
-
-- // adjust stack to what a normal return would do
-- __ mov(rsp, rsi);
-+ // pop return address, reset last_sp to NULL
-+ __ empty_expression_stack();
-+ __ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
-+ __ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
-+
- // throw exception
- __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
- // the call_VM checks for exception, so we should never return here.
-@@ -214,6 +215,31 @@
- return entry_point;
- }
-
-+
-+// Method handle invoker
-+// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
-+address InterpreterGenerator::generate_method_handle_entry(void) {
-+ if (!MethodHandleSupport) {
-+ return generate_abstract_entry();
-+ }
-+
-+ // incoming registers: rax, rcx
-+ Register rax_mtype = rax;
-+ Register rcx_recv = rcx;
-+
-+ Label wrong_method_type;
-+ address entry_point = MethodHandles::generate_method_handle_interpreter_entry(_masm, wrong_method_type);
-+
-+ __ bind(wrong_method_type);
-+ __ push(rax_mtype); // missed mtype (required)
-+ __ push(rcx_recv); // bad mh (actual)
-+ __ movptr(rdx, ExternalAddress((address) &Interpreter::_throw_WrongMethodType_entry));
-+ __ call(rdx);
-+
-+ return entry_point;
-+}
-+
-+
- // This method tells the deoptimizer how big an interpreted frame must be:
- int AbstractInterpreter::size_activation(methodOop method,
- int tempcount,
diff --git a/src/cpu/x86/vm/interpreter_x86_64.cpp b/src/cpu/x86/vm/interpreter_x86_64.cpp
--- a/src/cpu/x86/vm/interpreter_x86_64.cpp
+++ b/src/cpu/x86/vm/interpreter_x86_64.cpp
-@@ -294,6 +294,19 @@
+@@ -277,12 +277,11 @@
+ address entry_point = __ pc();
+
+ // abstract method entry
+- // remove return address. Not really needed, since exception
+- // handling throws away expression stack
+- __ pop(rbx);
+
+- // adjust stack to what a normal return would do
+- __ mov(rsp, r13);
++ // pop return address, reset last_sp to NULL
++ __ empty_expression_stack();
++ __ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
++ __ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
+
+ // throw exception
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address,
+@@ -300,7 +299,10 @@
+ if (!EnableMethodHandles) {
+ return generate_abstract_entry();
+ }
+- return generate_abstract_entry(); //6815692//
++
++ address entry_point = MethodHandles::generate_method_handle_interpreter_entry(_masm);
++
++ return entry_point;
}
-+// Method handle invoker
-+// Dispatch a method of the form java.dyn.MethodHandles::invoke(...)
-+address InterpreterGenerator::generate_method_handle_entry(void) {
-+ if (!MethodHandleSupport) {
-+ return generate_abstract_entry();
-+ }
-+
-+ address entry_point = __ pc();
-+ __ unimplemented();
-+ return entry_point;
-+}
-+
-+
- // Empty method, generate a very fast return.
-
- address InterpreterGenerator::generate_empty_entry(void) {
diff --git a/src/cpu/x86/vm/methodHandles_x86.cpp b/src/cpu/x86/vm/methodHandles_x86.cpp
-new file mode 100644
---- /dev/null
+--- a/src/cpu/x86/vm/methodHandles_x86.cpp
+++ b/src/cpu/x86/vm/methodHandles_x86.cpp
-@@ -0,0 +1,1132 @@
-+/*
-+ * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ *
-+ * This code is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 only, as
-+ * published by the Free Software Foundation.
-+ *
-+ * This code is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-+ * version 2 for more details (a copy is included in the LICENSE file that
-+ * accompanied this code).
-+ *
-+ * You should have received a copy of the GNU General Public License version
-+ * 2 along with this work; if not, write to the Free Software Foundation,
-+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
-+ * CA 95054 USA or visit www.sun.com if you need additional information or
-+ * have any questions.
-+ *
-+ */
-+
-+#include "incls/_precompiled.incl"
-+#include "incls/_methodHandles_x86.cpp.incl"
-+
-+#define __ _masm->
-+
-+address MethodEntry::start_compiled_entry(MacroAssembler* _masm,
-+ address interpreted_entry) {
-+ __ align(wordSize);
-+ address target = __ pc() + sizeof(Data);
-+ while (__ pc() < target) {
-+ __ nop();
-+ __ align(wordSize);
-+ }
-+
-+ MethodEntry* me = (MethodEntry*) __ pc();
-+ me->set_end_address(__ pc()); // set a temporary end_address
-+ me->set_from_interpreted_entry(interpreted_entry);
-+ me->set_type_checking_entry(NULL);
-+
-+ return (address) me;
-+}
-+
-+MethodEntry* MethodEntry::finish_compiled_entry(MacroAssembler* _masm,
-+ address start_addr) {
-+ MethodEntry* me = (MethodEntry*) start_addr;
-+ assert(me->end_address() == start_addr, "valid ME");
-+
-+ // Fill in the real end_address:
-+ __ align(wordSize);
-+ me->set_end_address(__ pc());
-+
-+ return me;
-+}
-+
-+#ifdef ASSERT
-+static void verify_argslot(MacroAssembler* _masm, Register rax_argslot,
-+ const char* error_message) {
-+ // Verify that argslot lies within (rsp, rbp].
-+ Label L_ok, L_bad;
-+ __ cmpptr(rax_argslot, rbp);
-+ __ jcc(Assembler::above, L_bad);
-+ __ cmpptr(rsp, rax_argslot);
-+ __ jcc(Assembler::below, L_ok);
-+ __ bind(L_bad);
-+ __ stop(error_message);
-+ __ bind(L_ok);
-+}
-+#endif
-+
-+
-+// Code generation
-+address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm,
-+ Label& wrong_method_type) {
-+ // rbx: methodOop
-+ // rcx: receiver method handle (must load from sp[MethodTypeForm.vmslots])
-+ // rsi: sender SP (must preserve)
-+ // rdx: garbage temp, blown away
-+
-+ Register rbx_method = rbx;
-+ Register rcx_recv = rcx;
-+ Register rax_mtype = rax;
-+ Register rdx_temp = rdx;
-+
-+ // here's where control starts out:
-+ __ align(CodeEntryAlignment);
-+ address entry_point = __ pc();
-+
-+ // fetch the MethodType from the method handle into rax (the 'check' register)
-+ {
-+ Register tem = rbx_method;
-+ for (int* pchase = methodOopDesc::method_type_pointer_chase(); (*pchase) != -1; pchase++) {
-+ __ movptr(rax_mtype, Address(tem, *pchase));
-+ tem = rax_mtype; // in case there is another indirection
-+ }
-+ }
-+ Register rbx_temp = rbx_method; // done with incoming methodOop
-+
-+ // given the MethodType, find out where the MH argument is buried
-+ __ movptr(rdx_temp, Address(rax_mtype,
-+ __ delayed_value(java_dyn_MethodType::form_offset_in_bytes, rbx_temp)));
-+ __ movl(rdx_temp, Address(rdx_temp,
-+ __ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, rbx_temp)));
-+ __ movptr(rcx_recv, __ argument_address(rdx_temp));
-+
-+ __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+
-+ // save away the wrong_method_type entry point
-+ address wmt_jump_addr = __ pc();
-+ __ jmp(wrong_method_type);
-+ __ hlt();
-+
-+ address me_cookie = MethodEntry::start_compiled_entry(_masm, wmt_jump_addr);
-+ __ unimplemented("compiled _wrong_method_type NYI"); // %%% FIXME
-+ init_entry(_wrong_method_type, MethodEntry::finish_compiled_entry(_masm, me_cookie));
-+
-+ return entry_point;
-+}
-+
-+// Helper to insert argument slots into the stack.
-+// arg_slots must be a multiple of stack_move_unit() and <= 0
-+void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
-+ RegisterConstant arg_slots,
-+ int arg_mask,
-+ Register rax_argslot,
-+ Register rbx_temp, Register rdx_temp) {
-+ assert_different_registers(rax_argslot, rbx_temp, rdx_temp,
-+ (!arg_slots.is_register() ? rsp : arg_slots.as_register()));
-+
-+ int constant_arg_slots = 0;
-+ if (arg_slots.is_constant()) {
-+ constant_arg_slots = arg_slots.as_constant() / stack_move_unit();
-+ } else {
-+ assert(arg_mask == _INSERT_NO_MASK,
-+ "cannot specify arg_mask with non-constant slot count");
-+#ifdef _LP64
-+ // clean high bits of stack motion register (was loaded as an int)
-+ __ movslq(arg_slots.as_register(), arg_slots.as_register());
-+#endif
-+ }
-+
-+#ifdef ASSERT
-+ verify_argslot(_masm, rax_argslot, "insertion point must fall within current frame");
-+ if (arg_slots.is_register()) {
-+ Label L_ok, L_bad;
-+ __ cmpptr(arg_slots.as_register(), NULL_WORD);
-+ __ jcc(Assembler::greater, L_bad);
-+ __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
-+ __ jcc(Assembler::zero, L_ok);
-+ __ bind(L_bad);
-+ __ stop("assert arg_slots <= 0 and clear low bits");
-+ __ bind(L_ok);
-+ } else {
-+ assert(arg_slots.as_constant() <= 0, "");
-+ assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
-+ }
-+#endif //ASSERT
-+
-+ // Make space on the stack for the inserted argument(s).
-+ // Then pull down everything shallower than rax_argslot.
-+ // The stacked return address gets pulled down with everything else.
-+ // That is, copy [rsp, argslot) downward by -size words. In pseudo-code:
-+ // rsp -= size;
-+ // for (rdx = rsp + size; rdx < argslot; rdx++)
-+ // rdx[-size] = rdx[0]
-+ // argslot -= size;
-+ __ mov(rdx_temp, rsp); // source pointer for copy
-+ __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
-+ {
-+ Label loop;
-+ __ bind(loop);
-+ // pull one word down each time through the loop
-+ __ movptr(rbx_temp, Address(rdx_temp, 0));
-+ __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
-+ __ addptr(rdx_temp, wordSize);
-+ __ cmpptr(rdx_temp, rax_argslot);
-+ __ jcc(Assembler::less, loop);
-+ }
-+
-+ // Now move the argslot down, to point to the opened-up space.
-+ __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
-+
-+ if (TaggedStackInterpreter) {
-+ int tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes();
-+ for (int slot = 0; slot < constant_arg_slots; slot++) {
-+ BasicType slot_type = ((arg_mask & (1 << slot)) == 0 ? T_OBJECT : T_INT);
-+ int slot_offset = Interpreter::stackElementSize() * slot;
-+ Address tag_addr(rax_argslot, slot_offset + tag_offset);
-+ __ movptr(tag_addr, frame::tag_for_basic_type(slot_type));
-+ }
-+ // Note that the new argument slots are tagged properly but contain
-+ // garbage at this point. The value portions must be initialized
-+ // by the caller. (Especially references!)
-+ }
-+}
-+
-+// Helper to remove argument slots from the stack.
-+// arg_slots must be a multiple of stack_move_unit() and >= 0
-+void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
-+ RegisterConstant arg_slots,
-+ Register rax_argslot,
-+ Register rbx_temp, Register rdx_temp) {
-+ assert_different_registers(rax_argslot, rbx_temp, rdx_temp,
-+ (!arg_slots.is_register() ? rsp : arg_slots.as_register()));
-+
-+#ifdef ASSERT
-+ {
-+ // Verify that [argslot..argslot+size) lies within (rsp, rbp).
-+ Label L_ok, L_bad;
-+ __ lea(rbx_temp, Address(rax_argslot, arg_slots, Address::times_ptr));
-+ __ cmpptr(rbx_temp, rbp);
-+ __ jcc(Assembler::above, L_bad);
-+ __ cmpptr(rsp, rax_argslot);
-+ __ jcc(Assembler::below, L_ok);
-+ __ bind(L_bad);
-+ __ stop("deleted argument(s) must fall within current frame");
-+ __ bind(L_ok);
-+ }
-+ if (arg_slots.is_register()) {
-+ Label L_ok, L_bad;
-+ __ cmpptr(arg_slots.as_register(), NULL_WORD);
-+ __ jcc(Assembler::less, L_bad);
-+ __ testl(arg_slots.as_register(), -stack_move_unit() - 1);
-+ __ jcc(Assembler::zero, L_ok);
-+ __ bind(L_bad);
-+ __ stop("assert arg_slots >= 0 and clear low bits");
-+ __ bind(L_ok);
-+ } else {
-+ assert(arg_slots.as_constant() >= 0, "");
-+ assert(arg_slots.as_constant() % -stack_move_unit() == 0, "");
-+ }
-+#endif //ASSERT
-+
-+#ifdef _LP64
-+ if (false) { // not needed, since register is positive
-+ // clean high bits of stack motion register (was loaded as an int)
-+ if (arg_slots.is_register())
-+ __ movslq(arg_slots.as_register(), arg_slots.as_register());
-+ }
-+#endif
-+
-+ // Pull up everything shallower than rax_argslot.
-+ // Then remove the excess space on the stack.
-+ // The stacked return address gets pulled up with everything else.
-+ // That is, copy [rsp, argslot) upward by size words. In pseudo-code:
-+ // for (rdx = argslot-1; rdx >= rsp; --rdx)
-+ // rdx[size] = rdx[0]
-+ // argslot += size;
-+ // rsp += size;
-+ __ lea(rdx_temp, Address(rax_argslot, -wordSize)); // source pointer for copy
-+ {
-+ Label loop;
-+ __ bind(loop);
-+ // pull one word up each time through the loop
-+ __ movptr(rbx_temp, Address(rdx_temp, 0));
-+ __ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
-+ __ addptr(rdx_temp, -wordSize);
-+ __ cmpptr(rdx_temp, rsp);
-+ __ jcc(Assembler::greaterEqual, loop);
-+ }
-+
-+ // Now move the argslot up, to point to the just-copied block.
-+ __ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
-+ // And adjust the argslot address to point at the deletion point.
-+ __ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
-+}
-+
-+#ifndef PRODUCT
-+void trace_method_handle_stub(const char* adaptername,
-+ oop mh,
-+ intptr_t* entry_sp,
-+ intptr_t* saved_sp) {
-+ // called as a leaf from native code: do not block the JVM!
-+ printf("MH %s %p %p %d\n", adaptername, mh, entry_sp, entry_sp - saved_sp);
-+}
-+#endif //PRODUCT
-+
-+// Generate an "entry" field for a method handle.
-+// This determines how the method handle will respond to calls.
-+void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
-+ // Here is the register state during an interpreted call,
-+ // as set up by generate_method_handle_interpreter_entry():
-+ // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused)
-+ // - rcx: receiver method handle
-+ // - rax: method handle type (already checked at call site, then unused)
-+ // - rsi: sender SP (must preserve)
-+ // - rdx: garbage temp, can blow away
-+
-+ Register rcx_recv = rcx;
-+ Register rax_argslot = rax;
-+ Register rbx_temp = rbx;
-+ Register rdx_temp = rdx;
-+
-+ guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
-+
-+ // some handy addresses
-+ Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() );
-+
-+ Address rcx_mh_vmtarget( rcx_recv, java_dyn_MethodHandle::vmtarget_offset_in_bytes() );
-+ Address rcx_dmh_vmindex( rcx_recv, impl_java_dyn_DirectMethodHandle::vmindex_offset_in_bytes() );
-+
-+ Address rcx_bmh_vmargslot( rcx_recv, impl_java_dyn_BoundMethodHandle::vmargslot_offset_in_bytes() );
-+ Address rcx_bmh_argument( rcx_recv, impl_java_dyn_BoundMethodHandle::argument_offset_in_bytes() );
-+
-+ Address rcx_amh_vmargslot( rcx_recv, impl_java_dyn_AdapterMethodHandle::vmargslot_offset_in_bytes() );
-+ Address rcx_amh_argument( rcx_recv, impl_java_dyn_AdapterMethodHandle::argument_offset_in_bytes() );
-+ Address rcx_amh_conversion( rcx_recv, impl_java_dyn_AdapterMethodHandle::conversion_offset_in_bytes() );
-+ Address vmarg; // __ argument_address(vmargslot)
-+
-+ int tag_offset = -1;
-+ if (TaggedStackInterpreter) {
-+ tag_offset = Interpreter::tag_offset_in_bytes() - Interpreter::value_offset_in_bytes();
-+ assert(tag_offset = wordSize, "stack grows as expected");
-+ }
-+
-+ if (have_entry(ek)) {
-+ __ nop(); // empty stubs make SG sick
-+ return;
-+ }
-+
-+ address interp_entry = __ pc();
-+ if (UseCompressedOops) __ unimplemented("UseCompressedOops");
-+
-+ AdapterKind ak = _adapt_retype_only;
-+ if ((int)ek > (int)_adapter_mh_first)
-+ ak = AdapterKind((int)ek - (int)_adapter_mh_first);
-+
-+#ifndef PRODUCT
-+ if (TraceMethodHandles) {
-+ __ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi);
-+ __ lea(rax, Address(rsp, wordSize*6)); // entry_sp
-+ // arguments:
-+ __ push(rsi); // saved_sp
-+ __ push(rax); // entry_sp
-+ __ push(rcx); // mh
-+ __ push(rcx);
-+ __ movptr(Address(rsp, 0), (intptr_t)entry_name(ek));
-+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 4);
-+ __ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax);
-+ }
-+#endif //PRODUCT
-+
-+ switch ((int) ek) {
-+ case _check_mtype:
-+ {
-+ // this stub is special, because it requires a live mtype argument
-+ Register rax_mtype = rax;
-+
-+ Label wrong_method_type;
-+ __ bind(wrong_method_type);
-+ __ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type]));
-+ __ jmp(Address(rdx_temp, MethodEntry::from_interpreted_entry_offset_in_bytes()));
-+ __ hlt();
-+
-+ interp_entry = __ pc();
-+ __ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type);
-+ // now rax_mtype is dead; subsequent stubs will use it as a temp
-+
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ break;
-+
-+ case _invokestatic_mh:
-+ case _invokespecial_mh:
-+ {
-+ Register rbx_method = rbx_temp;
-+ __ movptr(rbx_method, rcx_mh_vmtarget); // target is a methodOop
-+ __ verify_oop(rbx_method);
-+ // same as TemplateTable::invokestatic or invokespecial,
-+ // minus the CP setup and profiling:
-+ if (ek == _invokespecial_mh) {
-+ // Must load & check the first argument before entering the target method.
-+ __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp);
-+ __ movptr(rcx_recv, __ argument_address(rax_argslot, -1));
-+ __ null_check(rcx_recv);
-+ __ verify_oop(rcx_recv);
-+ }
-+ __ jmp(rbx_method_fie);
-+ }
-+ break;
-+
-+ case _invokevirtual_mh:
-+ {
-+ // same as TemplateTable::invokevirtual,
-+ // minus the CP setup and profiling:
-+
-+ // pick out the vtable index and receiver offset from the MH,
-+ // and then we can discard it:
-+ __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp);
-+ Register rbx_index = rbx_temp;
-+ __ movl(rbx_index, rcx_dmh_vmindex);
-+ // Note: The verifier allows us to ignore rcx_mh_vmtarget.
-+ __ movptr(rcx_recv, __ argument_address(rax_argslot, -1));
-+ __ null_check(rcx_recv, oopDesc::klass_offset_in_bytes());
-+
-+ // get receiver klass
-+ Register rax_klass = rax_argslot;
-+ __ movl(rax_klass, Address(rcx_recv, oopDesc::klass_offset_in_bytes()));
-+ __ verify_oop(rax_klass);
-+
-+ // get target methodOop & entry point
-+ const int base = instanceKlass::vtable_start_offset() * wordSize;
-+ assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
-+ Address vtable_entry_addr(rax_klass,
-+ rbx_index, Address::times_ptr,
-+ base + vtableEntry::method_offset_in_bytes());
-+ Register rbx_method = rbx_temp;
-+ __ movl(rbx_method, vtable_entry_addr);
-+
-+ __ verify_oop(rbx_method);
-+ __ jmp(rbx_method_fie);
-+ }
-+ break;
-+
-+ case _invokeinterface_mh:
-+ {
-+ // same as TemplateTable::invokeinterface,
-+ // minus the CP setup and profiling:
-+
-+ // pick out the interface and itable index from the MH.
-+ __ load_method_handle_vmslots(rax_argslot, rcx_recv, rdx_temp);
-+ Register rdx_intf = rdx_temp;
-+ Register rbx_index = rbx_temp;
-+ __ movptr(rdx_intf, rcx_mh_vmtarget);
-+ __ movl(rbx_index, rcx_dmh_vmindex);
-+ __ movptr(rcx_recv, __ argument_address(rax_argslot, -1));
-+ __ null_check(rcx_recv, oopDesc::klass_offset_in_bytes());
-+
-+ // get receiver klass
-+ Register rax_klass = rax_argslot;
-+ __ movl(rax_klass, Address(rcx_recv, oopDesc::klass_offset_in_bytes()));
-+ __ verify_oop(rax_klass);
-+
-+ Register rcx_temp = rcx_recv;
-+ Register rbx_method = rbx_index;
-+
-+ // get interface klass
-+ Label no_such_interface;
-+ __ verify_oop(rdx_intf);
-+ __ lookup_interface_method(rax_klass, rdx_intf,
-+ // note: next two args must be the same:
-+ rbx_index, rbx_method,
-+ rcx_temp,
-+ no_such_interface);
-+
-+ __ verify_oop(rbx_method);
-+ __ jmp(rbx_method_fie);
-+ __ hlt();
-+
-+ __ bind(no_such_interface);
-+ // Throw an exception.
-+ // For historical reasons, it will be IncompatibleClassChangeError.
-+ __ should_not_reach_here(); // %%% FIXME NYI
-+ }
-+ break;
-+
-+ case _bound_ref_mh:
-+ case _bound_int_mh:
-+ case _bound_long_mh:
-+ case _bound_ref_direct_mh:
-+ case _bound_int_direct_mh:
-+ case _bound_long_direct_mh:
-+ {
-+ bool direct_to_method = (ek >= _bound_ref_direct_mh);
-+ BasicType arg_type = T_ILLEGAL;
-+ if (ek == _bound_long_mh || ek == _bound_long_direct_mh) {
-+ arg_type = T_LONG;
-+ } else if (ek == _bound_int_mh || ek == _bound_int_direct_mh) {
-+ arg_type = T_INT;
-+ } else {
-+ assert(ek == _bound_ref_mh || ek == _bound_ref_direct_mh, "must be ref");
-+ arg_type = T_OBJECT;
-+ }
-+ int arg_slots = type2size[arg_type];
-+ int arg_mask = (arg_type == T_OBJECT ? _INSERT_REF_MASK :
-+ arg_slots == 1 ? _INSERT_INT_MASK : _INSERT_LONG_MASK);
-+
-+ // make room for the new argument:
-+ __ movl(rax_argslot, rcx_bmh_vmargslot);
-+ __ lea(rax_argslot, __ argument_address(rax_argslot));
-+ insert_arg_slots(_masm, arg_slots * stack_move_unit(), arg_mask,
-+ rax_argslot, rbx_temp, rdx_temp);
-+
-+ // store bound argument into the new stack slot:
-+ __ movptr(rbx_temp, rcx_bmh_argument);
-+ Address prim_value_addr(rbx_temp, java_lang_boxing_object::value_offset_in_bytes(arg_type));
-+ if (arg_type == T_OBJECT) {
-+ __ movptr(Address(rax_argslot, 0), rbx_temp);
-+ } else {
-+ __ load_sized_value(rbx_temp, prim_value_addr,
-+ type2aelembytes(arg_type), is_signed_subword_type(arg_type));
-+ __ movptr(Address(rax_argslot, 0), rbx_temp);
-+#ifndef _LP64
-+ if (arg_slots == 2) {
-+ __ movl(rbx_temp, prim_value_addr.plus_disp(wordSize));
-+ __ movptr(Address(rax_argslot, Interpreter::stackElementSize()), rbx_temp);
-+ }
-+#endif //_LP64
-+ break;
-+ }
-+
-+ if (direct_to_method) {
-+ Register rbx_method = rbx_temp;
-+ __ movptr(rbx_method, rcx_mh_vmtarget);
-+ __ verify_oop(rbx_method);
-+ __ jmp(rbx_method_fie);
-+ } else {
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ __ verify_oop(rcx_recv);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ }
-+ break;
-+
-+ case _adapter_mh_first+_adapt_retype_only:
-+ // immediately jump to the next MH layer:
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ __ verify_oop(rcx_recv);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ // This is OK when all parameter types widen.
-+ // It is also OK when a return type narrows.
-+ break;
-+
-+ case _adapter_mh_first+_adapt_check_cast:
-+ {
-+ // temps:
-+ Register rbx_klass = rbx_temp; // interesting AMH data
-+
-+ // check a reference argument before jumping to the next layer of MH:
-+ __ movl(rax_argslot, rcx_amh_vmargslot);
-+ vmarg = __ argument_address(rax_argslot);
-+
-+ // What class are we casting to?
-+ __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
-+ __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes()));
-+
-+ // get the new MH:
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ // (now we are done with the old MH)
-+
-+ Label done;
-+ __ movptr(rdx_temp, vmarg);
-+ __ testl(rdx_temp, rdx_temp);
-+ __ jcc(Assembler::zero, done); // no cast if null
-+ __ movl(rdx_temp, Address(rdx_temp, oopDesc::klass_offset_in_bytes()));
-+
-+ // live at this point:
-+ // - rbx_klass: klass required by the target method
-+ // - rdx_temp: argument klass to test
-+ // - rcx_recv: method handle to invoke (after cast succeeds)
-+ __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done);
-+
-+ // If we get here, the type check failed!
-+ // Call the wrong_method_type stub, passing the failing argument type in rax.
-+ Register rax_mtype = rax_argslot;
-+#if 0
-+ __ push(rbx_klass); // missed klass (required)
-+ __ push(rdx_temp); // bad object (actual)
-+ __ jump(ExternalAddress(Interpreter::_throw_WrongMethodType_entry));
-+#else
-+ __ mov(rax_mtype, rbx_klass); // missed klass (required)
-+ __ mov(rcx_recv, rdx_temp); // bad object (actual)
-+ __ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type]));
-+ __ jmp(Address(rdx_temp, MethodEntry::from_interpreted_entry_offset_in_bytes()));
-+#endif
-+
-+ __ bind(done);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ break;
-+
-+ case _adapter_mh_first+_adapt_prim_to_prim:
-+ case _adapter_mh_first+_adapt_ref_to_prim:
-+ // handled completely by optimized cases
-+ __ stop("init_AdapterMethodHandle should not issue this");
-+ break;
-+
-+ case _adapter_opt_i2i: // optimized subcase of adapt_prim_to_prim
-+//case _adapter_opt_f2i: // optimized subcase of adapt_prim_to_prim
-+ case _adapter_opt_l2i: // optimized subcase of adapt_prim_to_prim
-+ case _adapter_opt_a2i: // optimized subcase of adapt_ref_to_prim
-+ {
-+ // perform an in-place conversion to int or an int subword
-+ __ movl(rax_argslot, rcx_amh_vmargslot);
-+ vmarg = __ argument_address(rax_argslot);
-+
-+ switch (ek) {
-+ case _adapter_opt_i2i:
-+ __ movl(rdx_temp, vmarg);
-+ break;
-+ case _adapter_opt_l2i:
-+ {
-+ // just delete the extra slot; on a little-endian machine we keep the first
-+ __ lea(rax_argslot, __ argument_address(rax_argslot, 1));
-+ remove_arg_slots(_masm, -stack_move_unit(),
-+ rax_argslot, rbx_temp, rdx_temp);
-+ vmarg = Address(rax_argslot, -Interpreter::stackElementSize());
-+ __ movl(rdx_temp, vmarg);
-+ }
-+ break;
-+ case _adapter_opt_a2i:
-+ {
-+ // Load the value up from the heap.
-+ __ movptr(rdx_temp, vmarg);
-+ int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_INT);
-+#ifdef ASSERT
-+ for (int bt = T_BOOLEAN; bt < T_INT; bt++) {
-+ if (is_subword_type(BasicType(bt)))
-+ assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(BasicType(bt)), "");
-+ }
-+#endif
-+ __ null_check(rdx_temp, value_offset);
-+ __ movl(rdx_temp, Address(rdx_temp, value_offset));
-+ // We load this as a word. Because we are little-endian,
-+ // the low bits will be correct, but the high bits may need cleaning.
-+ // The vminfo will guide us to clean those bits.
-+ }
-+ break;
-+ default:
-+ assert(false, "");
-+ }
-+ goto finish_int_conversion;
-+ }
-+
-+ finish_int_conversion:
-+ {
-+ Register rbx_vminfo = rbx_temp;
-+ __ movl(rbx_vminfo, rcx_amh_conversion);
-+ assert(_CONV_VMINFO_SHIFT == 0, "preshifted");
-+
-+ // get the new MH:
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ // (now we are done with the old MH)
-+
-+ // original 32-bit vmdata word must be of this form:
-+ // | MBZ:16 | signBitCount:8 | srcDstTypes:8 | conversionOp:8 |
-+ __ xchgl(rcx, rbx_vminfo); // free rcx for shifts
-+ __ shll(rdx_temp /*, rcx*/);
-+ Label zero_extend, done;
-+ __ testl(rcx, _CONV_VMINFO_SIGN_FLAG);
-+ __ jcc(Assembler::zero, zero_extend);
-+
-+ // this path is taken for int->byte, int->short
-+ __ sarl(rdx_temp /*, rcx*/);
-+ __ jmp(done);
-+
-+ __ bind(zero_extend);
-+ // this is taken for int->char
-+ __ shrl(rdx_temp /*, rcx*/);
-+
-+ __ bind(done);
-+ __ movptr(vmarg, rdx_temp);
-+ __ xchgl(rcx, rbx_vminfo); // restore rcx_recv
-+
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ break;
-+
-+ case _adapter_opt_i2l: // optimized subcase of adapt_prim_to_prim
-+ case _adapter_opt_a2l: // optimized subcase of adapt_ref_to_prim
-+ {
-+ // perform an in-place int-to-long or ref-to-long conversion
-+ __ movl(rax_argslot, rcx_amh_vmargslot);
-+
-+ // on a little-endian machine we keep the first slot and add another after
-+ __ lea(rax_argslot, __ argument_address(rax_argslot, 1));
-+ insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK,
-+ rax_argslot, rbx_temp, rdx_temp);
-+ Address vmarg1(rax_argslot, -Interpreter::stackElementSize());
-+ Address vmarg2 = vmarg1.plus_disp(Interpreter::stackElementSize());
-+
-+ switch (ek) {
-+ case _adapter_opt_i2l:
-+ {
-+ __ movl(rdx_temp, vmarg1);
-+ __ extend_sign(rbx_temp, rdx_temp);
-+ __ movl(vmarg2, rbx_temp); // store second word
-+ }
-+ break;
-+ case _adapter_opt_a2l:
-+ {
-+ // Load the value up from the heap.
-+ __ movptr(rdx_temp, vmarg1);
-+ int value_offset = java_lang_boxing_object::value_offset_in_bytes(T_LONG);
-+ assert(value_offset == java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE), "");
-+ __ null_check(rdx_temp, value_offset);
-+ __ movl(rbx_temp, Address(rdx_temp, value_offset + 0*BytesPerInt));
-+ __ movl(rdx_temp, Address(rdx_temp, value_offset + 1*BytesPerInt));
-+ __ movl(vmarg1, rbx_temp);
-+ __ movl(vmarg2, rdx_temp);
-+ }
-+ break;
-+ default:
-+ assert(false, "");
-+ }
-+
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ break;
-+
-+ case _adapter_opt_f2d: // optimized subcase of adapt_prim_to_prim
-+ case _adapter_opt_d2f: // optimized subcase of adapt_prim_to_prim
-+ {
-+ // perform an in-place floating primitive conversion
-+ __ movl(rax_argslot, rcx_amh_vmargslot);
-+ __ lea(rax_argslot, __ argument_address(rax_argslot, 1));
-+ if (ek == _adapter_opt_f2d) {
-+ insert_arg_slots(_masm, stack_move_unit(), _INSERT_INT_MASK,
-+ rax_argslot, rbx_temp, rdx_temp);
-+ }
-+ Address vmarg(rax_argslot, -Interpreter::stackElementSize());
-+
-+#ifdef _LP64
-+ if (ek == _adapter_opt_f2d) {
-+ __ movflt(xmm0, vmarg);
-+ __ cvtss2sd(xmm0, xmm0);
-+ __ movdbl(vmarg, xmm0);
-+ } else {
-+ __ movdbl(xmm0, vmarg);
-+ __ cvtsd2ss(xmm0, xmm0);
-+ __ movflt(vmarg, xmm0);
-+ }
-+#else //_LP64
-+ if (ek == _adapter_opt_f2d) {
-+ __ fld_s(vmarg); // load float to ST0
-+ __ fstp_s(vmarg); // store single
-+ } else if (!TaggedStackInterpreter) {
-+ __ fld_d(vmarg); // load double to ST0
-+ __ fstp_s(vmarg); // store single
-+ } else {
-+ Address vmarg_tag = vmarg.plus_disp(tag_offset);
-+ Address vmarg2 = vmarg.plus_disp(Interpreter::stackElementSize());
-+ // vmarg2_tag does not participate in this code
-+ Register rbx_tag = rbx_temp;
-+ __ movl(rbx_tag, vmarg_tag); // preserve tag
-+ __ movl(rdx_temp, vmarg2); // get second word of double
-+ __ movl(vmarg_tag, rdx_temp); // align with first word
-+ __ fld_d(vmarg); // load double to ST0
-+ __ movl(vmarg_tag, rbx_tag); // restore tag
-+ __ fstp_s(vmarg); // store single
-+ }
-+#endif //_LP64
-+
-+ if (ek == _adapter_opt_d2f) {
-+ remove_arg_slots(_masm, -stack_move_unit(),
-+ rax_argslot, rbx_temp, rdx_temp);
-+ }
-+
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ break;
-+
-+ case _adapter_mh_first+_adapt_prim_to_ref:
-+ __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
-+ break;
-+
-+ case _adapter_mh_first+_adapt_swap_args:
-+ case _adapter_mh_first+_adapt_rot_args:
-+ // handled completely by optimized cases
-+ __ stop("init_AdapterMethodHandle should not issue this");
-+ break;
-+
-+ case _adapter_opt_swap_1:
-+ case _adapter_opt_swap_2:
-+ case _adapter_opt_rot_1_up:
-+ case _adapter_opt_rot_1_down:
-+ case _adapter_opt_rot_2_up:
-+ case _adapter_opt_rot_2_down:
-+ {
-+ int rotate = 0, swap_slots = 0;
-+ switch ((int)ek) {
-+ case _adapter_opt_swap_1: swap_slots = 1; break;
-+ case _adapter_opt_swap_2: swap_slots = 2; break;
-+ case _adapter_opt_rot_1_up: swap_slots = 1; rotate++; break;
-+ case _adapter_opt_rot_1_down: swap_slots = 1; rotate--; break;
-+ case _adapter_opt_rot_2_up: swap_slots = 2; rotate++; break;
-+ case _adapter_opt_rot_2_down: swap_slots = 2; rotate--; break;
-+ default: assert(false, "");
-+ }
-+
-+ // the real size of the move must be doubled if TaggedStackInterpreter:
-+ int swap_bytes = (int)( swap_slots * Interpreter::stackElementWords() * wordSize );
-+
-+ // 'argslot' is the position of the first argument to swap
-+ __ movl(rax_argslot, rcx_amh_vmargslot);
-+ __ lea(rax_argslot, __ argument_address(rax_argslot));
-+
-+ // 'vminfo' is the second
-+ Register rbx_destslot = rbx_temp;
-+ __ movl(rbx_destslot, rcx_amh_conversion);
-+ assert(_CONV_VMINFO_SHIFT == 0, "preshifted");
-+ __ andl(rbx_destslot, _CONV_VMINFO_MASK);
-+ __ lea(rbx_destslot, __ argument_address(rbx_destslot));
-+ DEBUG_ONLY(verify_argslot(_masm, rbx_destslot, "swap point must fall within current frame"));
-+
-+ if (!rotate) {
-+ for (int i = 0; i < swap_bytes; i += wordSize) {
-+ __ movptr(rdx_temp, Address(rax_argslot , i));
-+ __ push(rdx_temp);
-+ __ movptr(rdx_temp, Address(rbx_destslot, i));
-+ __ movptr(Address(rax_argslot, i), rdx_temp);
-+ __ pop(rdx_temp);
-+ __ movptr(Address(rbx_destslot, i), rdx_temp);
-+ }
-+ } else {
-+ // push the first chunk, which is going to get overwritten
-+ for (int i = swap_bytes; (i -= wordSize) >= 0; ) {
-+ __ movptr(rdx_temp, Address(rax_argslot, i));
-+ __ push(rdx_temp);
-+ }
-+
-+ if (rotate > 0) {
-+ // rotate upward
-+ __ subptr(rax_argslot, swap_bytes);
-+#ifdef ASSERT
-+ {
-+ // Verify that argslot > destslot, by at least swap_bytes.
-+ Label L_ok;
-+ __ cmpptr(rax_argslot, rbx_destslot);
-+ __ jcc(Assembler::aboveEqual, L_ok);
-+ __ stop("source must be above destination (upward rotation)");
-+ __ bind(L_ok);
-+ }
-+#endif
-+ // work argslot down to destslot, copying contiguous data upwards
-+ // pseudo-code:
-+ // rax = src_addr - swap_bytes
-+ // rbx = dest_addr
-+ // while (rax >= rbx) *(rax + swap_bytes) = *(rax + 0), rax--;
-+ Label loop;
-+ __ bind(loop);
-+ __ movptr(rdx_temp, Address(rax_argslot, 0));
-+ __ movptr(Address(rax_argslot, swap_bytes), rdx_temp);
-+ __ addptr(rax_argslot, -wordSize);
-+ __ cmpptr(rax_argslot, rbx_destslot);
-+ __ jcc(Assembler::aboveEqual, loop);
-+ } else {
-+ __ addptr(rax_argslot, swap_bytes);
-+#ifdef ASSERT
-+ {
-+ // Verify that argslot < destslot, by at least swap_bytes.
-+ Label L_ok;
-+ __ cmpptr(rax_argslot, rbx_destslot);
-+ __ jcc(Assembler::belowEqual, L_ok);
-+ __ stop("source must be below destination (downward rotation)");
-+ __ bind(L_ok);
-+ }
-+#endif
-+ // work argslot up to destslot, copying contiguous data downwards
-+ // pseudo-code:
-+ // rax = src_addr + swap_bytes
-+ // rbx = dest_addr
-+ // while (rax <= rbx) *(rax - swap_bytes) = *(rax + 0), rax++;
-+ Label loop;
-+ __ bind(loop);
-+ __ movptr(rdx_temp, Address(rax_argslot, 0));
-+ __ movptr(Address(rax_argslot, -swap_bytes), rdx_temp);
-+ __ addptr(rax_argslot, wordSize);
-+ __ cmpptr(rax_argslot, rbx_destslot);
-+ __ jcc(Assembler::belowEqual, loop);
-+ }
-+
-+ // pop the original first chunk into the destination slot, now free
-+ for (int i = 0; i < swap_bytes; i += wordSize) {
-+ __ pop(rdx_temp);
-+ __ movptr(Address(rbx_destslot, i), rdx_temp);
-+ }
-+ }
-+
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ break;
-+
-+ case _adapter_mh_first+_adapt_dup_args:
-+ {
-+ // 'argslot' is the position of the first argument to duplicate
-+ __ movl(rax_argslot, rcx_amh_vmargslot);
-+ __ lea(rax_argslot, __ argument_address(rax_argslot));
-+
-+ // 'stack_move' is negative number of words to duplicate
-+ Register rdx_stack_move = rdx_temp;
-+ __ movl(rdx_stack_move, rcx_amh_conversion);
-+ __ sarl(rdx_stack_move, _CONV_STACK_MOVE_SHIFT);
-+
-+ Address argslot0 = __ argument_address(0);
-+ assert(argslot0.base() == rsp, "");
-+ int pre_arg_size = argslot0.disp();
-+ assert(pre_arg_size % wordSize == 0, "");
-+ assert(pre_arg_size > 0, "must include PC");
-+
-+ // remember the old rsp+1 (argslot[0])
-+ Register rbx_oldarg = rbx_temp;
-+ __ lea(rbx_oldarg, argslot0);
-+
-+ // move rsp down to make room for dups
-+ __ lea(rsp, Address(rsp, rdx_stack_move, Address::times_ptr));
-+
-+ // compute the new rsp+1 (argslot[0])
-+ Register rdx_newarg = rdx_temp;
-+ __ lea(rdx_newarg, argslot0);
-+
-+ __ push(rdi); // need a temp
-+ // (preceding push must be done after arg addresses are taken!)
-+
-+ // pull down the pre_arg_size data (PC)
-+ for (int i = -pre_arg_size; i < 0; i += wordSize) {
-+ __ movptr(rdi, Address(rbx_oldarg, i));
-+ __ movptr(Address(rdx_newarg, i), rdi);
-+ }
-+
-+ // copy from rax_argslot[0...] down to new_rsp[1...]
-+ // pseudo-code:
-+ // rbx = old_rsp+1
-+ // rdx = new_rsp+1
-+ // rax = argslot
-+ // while (rdx < rbx) *rdx++ = *rax++
-+ Label loop;
-+ __ bind(loop);
-+ __ movptr(rdi, Address(rax_argslot, 0));
-+ __ movptr(Address(rdx_newarg, 0), rdi);
-+ __ addptr(rax_argslot, wordSize);
-+ __ addptr(rdx_newarg, wordSize);
-+ __ cmpptr(rdx_newarg, rbx_oldarg);
-+ __ jcc(Assembler::less, loop);
-+
-+ __ pop(rdi); // restore temp
-+
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ break;
-+
-+ case _adapter_mh_first+_adapt_drop_args:
-+ {
-+ // 'argslot' is the position of the first argument to nuke
-+ __ movl(rax_argslot, rcx_amh_vmargslot);
-+ __ lea(rax_argslot, __ argument_address(rax_argslot));
-+
-+ __ push(rdi); // need a temp
-+ // (must do previous push after argslot address is taken)
-+
-+ // 'stack_move' is number of words to drop
-+ Register rdi_stack_move = rdi;
-+ __ movl(rdi_stack_move, rcx_amh_conversion);
-+ __ sarl(rdi_stack_move, _CONV_STACK_MOVE_SHIFT);
-+ remove_arg_slots(_masm, rdi_stack_move,
-+ rax_argslot, rbx_temp, rdx_temp);
-+
-+ __ pop(rdi); // restore temp
-+
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+ }
-+ break;
-+
-+ case _adapter_mh_first+_adapt_collect_args:
-+ __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
-+ break;
-+
-+ case _adapter_mh_first+_adapt_spread_args:
-+ // handled completely by optimized cases
-+ __ stop("init_AdapterMethodHandle should not issue this");
-+ break;
-+
-+ case _adapt_opt_spread_0:
-+ case _adapt_opt_spread_1:
-+ case _adapt_opt_spread_more:
-+ {
-+ // spread an array out into a group of arguments
-+ int length_constant = -1;
-+ switch (ek) {
-+ case _adapt_opt_spread_0: length_constant = 0; break;
-+ case _adapt_opt_spread_1: length_constant = 1; break;
-+ }
-+
-+ // find the address of the array argument
-+ __ movl(rax_argslot, rcx_amh_vmargslot);
-+ __ lea(rax_argslot, __ argument_address(rax_argslot));
-+
-+ // grab some temps
-+ { __ push(rsi); __ push(rdi); }
-+ // (preceding pushes must be done after argslot address is taken!)
-+#define UNPUSH_RSI_RDI \
-+ { __ pop(rdi); __ pop(rsi); }
-+
-+ // arx_argslot points both to the array and to the first output arg
-+ vmarg = Address(rax_argslot, 0);
-+
-+ // Get the array value.
-+ Register rsi_array = rsi;
-+ Register rdx_array_klass = rdx_temp;
-+ BasicType elem_type = T_OBJECT;
-+ int length_offset = arrayOopDesc::length_offset_in_bytes();
-+ int elem0_offset = arrayOopDesc::base_offset_in_bytes(elem_type);
-+ __ movptr(rsi_array, vmarg);
-+ Label skip_array_check;
-+ if (length_constant == 0) {
-+ __ testptr(rsi_array, rsi_array);
-+ __ jcc(Assembler::zero, skip_array_check);
-+ }
-+ __ null_check(rsi_array, oopDesc::klass_offset_in_bytes());
-+ __ movl(rdx_array_klass, Address(rsi_array, oopDesc::klass_offset_in_bytes()));
-+
-+ // Check the array type.
-+ Register rbx_klass = rbx_temp;
-+ __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
-+ __ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes()));
-+
-+ Label ok_array_klass, bad_array_klass, bad_array_length;
-+ __ check_klass_subtype(rdx_array_klass, rbx_klass, rdi, ok_array_klass);
-+ // If we get here, the type check failed!
-+ __ jmp(bad_array_klass);
-+ __ bind(ok_array_klass);
-+
-+ // Check length.
-+ if (length_constant >= 0) {
-+ __ cmpl(Address(rsi_array, length_offset), length_constant);
-+ } else {
-+ Register rbx_vminfo = rbx_temp;
-+ __ movl(rbx_vminfo, rcx_amh_conversion);
-+ assert(_CONV_VMINFO_SHIFT == 0, "preshifted");
-+ __ andl(rbx_vminfo, _CONV_VMINFO_MASK);
-+ __ cmpl(rbx_vminfo, Address(rsi_array, length_offset));
-+ }
-+ __ jcc(Assembler::notEqual, bad_array_length);
-+
-+ Register rdx_argslot_limit = rdx_temp;
-+
-+ // Array length checks out. Now insert any required stack slots.
-+ if (length_constant == -1) {
-+ // Form a pointer to the end of the affected region.
-+ __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize()));
-+ // 'stack_move' is negative number of words to insert
-+ Register rdi_stack_move = rdi;
-+ __ movl(rdi_stack_move, rcx_amh_conversion);
-+ __ sarl(rdi_stack_move, _CONV_STACK_MOVE_SHIFT);
-+ Register rsi_temp = rsi_array; // spill this
-+ insert_arg_slots(_masm, rdi_stack_move, -1,
-+ rax_argslot, rbx_temp, rsi_temp);
-+ // reload the array (since rsi was killed)
-+ __ movptr(rsi_array, vmarg);
-+ } else if (length_constant > 1) {
-+ int arg_mask = 0;
-+ int new_slots = (length_constant - 1);
-+ for (int i = 0; i < new_slots; i++) {
-+ arg_mask <<= 1;
-+ arg_mask |= _INSERT_REF_MASK;
-+ }
-+ insert_arg_slots(_masm, new_slots * stack_move_unit(), arg_mask,
-+ rax_argslot, rbx_temp, rdx_temp);
-+ } else if (length_constant == 1) {
-+ // no stack resizing required
-+ } else if (length_constant == 0) {
-+ remove_arg_slots(_masm, -stack_move_unit(),
-+ rax_argslot, rbx_temp, rdx_temp);
-+ }
-+
-+ // Copy from the array to the new slots.
-+ // Note: Stack change code preserves integrity of rax_argslot pointer.
-+ // So even after slot insertions, rax_argslot still points to first argument.
-+ if (length_constant == -1) {
-+ // [rax_argslot, rdx_argslot_limit) is the area we are inserting into.
-+ Register rsi_source = rsi_array;
-+ __ lea(rsi_source, Address(rsi_array, elem0_offset));
-+ Label loop;
-+ __ bind(loop);
-+ __ movptr(rbx_temp, Address(rsi_source, 0));
-+ __ movptr(Address(rax_argslot, 0), rbx_temp);
-+ __ addptr(rsi_source, type2aelembytes(elem_type));
-+ if (TaggedStackInterpreter) {
-+ __ movptr(Address(rax_argslot, tag_offset),
-+ frame::tag_for_basic_type(elem_type));
-+ }
-+ __ addptr(rax_argslot, Interpreter::stackElementSize());
-+ __ cmpptr(rax_argslot, rdx_argslot_limit);
-+ __ jcc(Assembler::less, loop);
-+ } else if (length_constant == 0) {
-+ __ bind(skip_array_check);
-+ // nothing to copy
-+ } else {
-+ int elem_offset = elem0_offset;
-+ int slot_offset = 0;
-+ for (int index = 0; index < length_constant; index++) {
-+ __ movptr(rbx_temp, Address(rsi_array, elem_offset));
-+ __ movptr(Address(rax_argslot, slot_offset), rbx_temp);
-+ elem_offset += type2aelembytes(elem_type);
-+ if (TaggedStackInterpreter) {
-+ __ movptr(Address(rax_argslot, slot_offset + tag_offset),
-+ frame::tag_for_basic_type(elem_type));
-+ }
-+ slot_offset += Interpreter::stackElementSize();
-+ }
-+ }
-+
-+ // Arguments are spread. Move to next method handle.
-+ UNPUSH_RSI_RDI;
-+ __ movptr(rcx_recv, rcx_mh_vmtarget);
-+ __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
-+
-+ __ bind(bad_array_klass);
-+ UNPUSH_RSI_RDI;
-+ __ stop("bad array klass NYI");
-+
-+ __ bind(bad_array_length);
-+ UNPUSH_RSI_RDI;
-+ __ stop("bad array length NYI");
-+
-+#undef UNPUSH_RSI_RDI
-+ }
-+ break;
-+
-+ case _adapter_mh_first+_adapt_flyby:
-+ case _adapter_mh_first+_adapt_ricochet:
-+ __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
-+ break;
-+
-+ default: ShouldNotReachHere();
-+ }
-+ __ hlt();
-+
-+ address me_cookie = MethodEntry::start_compiled_entry(_masm, interp_entry);
-+ __ unimplemented(entry_name(ek)); // %%% FIXME: NYI
-+
-+ init_entry(ek, MethodEntry::finish_compiled_entry(_masm, me_cookie));
-+}
-diff --git a/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/src/cpu/x86/vm/stubGenerator_x86_32.cpp
---- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp
-+++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp
-@@ -2170,6 +2170,9 @@
- return stub->entry_point();
- }
-
-+#undef __
-+#define __ _masm->
-+
-
- void create_control_words() {
- // Round to nearest, 53-bit mode, exceptions masked
-@@ -2249,6 +2252,16 @@
+@@ -98,7 +98,7 @@
+ // fetch the MethodType from the method handle into rax (the 'check' register)
+ {
+ Register tem = rbx_method;
+- for (int* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) {
++ for (jint* pchase = methodOopDesc::method_type_offsets_chain(); (*pchase) != -1; pchase++) {
+ __ movptr(rax_mtype, Address(tem, *pchase));
+ tem = rax_mtype; // in case there is another indirection
+ }
+@@ -283,7 +283,6 @@
+ // as set up by generate_method_handle_interpreter_entry():
+ // - rbx: garbage temp (was MethodHandle.invoke methodOop, unused)
+ // - rcx: receiver method handle
+- // - rax: method handle type (already checked at call site, then unused)
+ // - rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
+ // - rdx: garbage temp, can blow away
+
+diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp
++++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+@@ -2933,6 +2933,16 @@
// arraycopy stubs used by compilers
generate_arraycopy_stubs();
+
+ // generic method handle stubs
-+ if (MethodHandleSupport && SystemDictionary::MethodHandle_klass() != NULL) {
++ if (EnableMethodHandles && SystemDictionary::MethodHandle_klass() != NULL) {
+ for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
+ ek < MethodHandles::_EK_LIMIT;
+ ek = MethodHandles::EntryKind(1 + (int)ek)) {
@@ -2825,32 +520,24 @@ diff --git a/src/cpu/x86/vm/stubGenerato
+ }
}
-
-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 @@
+ public:
+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
+@@ -100,21 +100,26 @@
return entry;
}
-+#ifdef ASSERT
-+address last_WrongMethodType_caller;
-+#endif //ASSERT
-+
+-// Arguments are: required type in rarg1, failing object (or NULL) in rarg2
+// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4.
-+// pc at TOS (just for debugging)
-+address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
-+ address entry = __ pc();
-+
-+ __ pop(rcx); // address raising the error (for debug)
-+#ifdef ASSERT
-+ __ lea(rax, ExternalAddress((address) &last_WrongMethodType_caller));
-+ __ movptr(Address(rax, 0), rcx);
-+#endif //ASSERT
-+
-+ __ pop(rbx); // actual failing object is at TOS
-+ __ pop(rax); // required type is at TOS+4
-+
+ address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
+ address entry = __ pc();
+
+ __ pop(c_rarg2); // failing object is at TOS
+ __ pop(c_rarg1); // required type is at TOS+8
+
+- // expression stack must be empty before entering the VM if an
+- // exception happened
+ __ verify_oop(rbx);
+ __ verify_oop(rax);
+
@@ -2859,6501 +546,59 @@ diff --git a/src/cpu/x86/vm/templateInte
+ __ restore_locals();
+
+ // Expression stack must be empty before entering the VM for an exception.
-+ __ empty_expression_stack();
-+ __ empty_FPU_stack();
-+ __ call_VM(noreg,
-+ CAST_FROM_FN_PTR(address,
+ __ empty_expression_stack();
+
+ __ call_VM(noreg,
+ CAST_FROM_FN_PTR(address,
+- InterpreterRuntime::
+- throw_WrongMethodTypeException),
+ InterpreterRuntime::throw_WrongMethodTypeException),
-+ // pass required type, failing object (or NULL)
-+ rax, rbx);
-+ 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();
-@@ -1370,6 +1407,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;
-+ case Interpreter::method_handle : entry_point = ((InterpreterGenerator*)this)->generate_method_handle_entry(); break;
-
- case Interpreter::java_lang_math_sin : // fall thru
- case Interpreter::java_lang_math_cos : // fall thru
-@@ -1400,9 +1438,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;
-
-- const int method_stack = (method->max_locals() + method->max_stack()) *
-+ const int extra_stack = methodOopDesc::extra_stack();
-+ const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
- Interpreter::stackElementWords();
-- return overhead_size + method_stack + stub_code;
-+ return overhead_size + method_stack + extra_stack + stub_code;
- }
-
- // asm based interpreter deoptimization helpers
-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
-@@ -100,6 +100,36 @@
+ // pass required type, failing object (or NULL)
+ c_rarg1, c_rarg2);
return entry;
- }
-
-+#ifdef ASSERT
-+address last_WrongMethodType_caller;
-+#endif //ASSERT
-+
-+// Arguments are: required type in rarg1, failing object (or NULL) in rarg2
-+address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
-+ address entry = __ pc();
-+
-+ __ pop(rax); // address raising the error (for debug)
-+#ifdef ASSERT
-+ __ lea(c_rarg1, ExternalAddress((address) &last_WrongMethodType_caller));
-+ __ movptr(Address(c_rarg1, 0), rax);
-+#endif //ASSERT
-+
-+ __ pop(c_rarg2); // failing object is at TOS
-+ __ pop(c_rarg1); // required type is at TOS+8
-+
-+ // expression stack must be empty before entering the VM if an
-+ // exception happened
-+ __ empty_expression_stack();
-+
-+ __ call_VM(noreg,
-+ CAST_FROM_FN_PTR(address,
-+ InterpreterRuntime::
-+ 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");
-@@ -161,7 +191,6 @@
-
- __ restore_bcp();
- __ restore_locals();
--
- __ get_cache_and_index_at_bcp(rbx, rcx, 1);
- __ movl(rbx, Address(rbx, rcx,
- Address::times_8,
-@@ -1393,6 +1422,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;
-+ case Interpreter::method_handle : entry_point = ((InterpreterGenerator*) this)->generate_method_handle_entry();break;
- case Interpreter::java_lang_math_sin : break;
- case Interpreter::java_lang_math_cos : break;
- case Interpreter::java_lang_math_tan : break;
-@@ -1422,7 +1452,8 @@
- -(frame::interpreter_frame_initial_sp_offset) + entry_size;
-
- const int stub_code = frame::entry_frame_after_call_words;
-- const int method_stack = (method->max_locals() + method->max_stack()) *
-+ const int extra_stack = methodOopDesc::extra_stack();
-+ const int method_stack = (method->max_locals() + method->max_stack() + extra_stack) *
- Interpreter::stackElementWords();
- return (overhead_size + method_stack + stub_code);
- }
-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
-@@ -2113,13 +2113,10 @@
- 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_ptr,
-- constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
-+ __ movl(temp, Address(Rcache, index, Address::times_4, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
- __ shrl(temp, shift_count);
- // have we resolved this bytecode?
-- __ andptr(temp, 0xFF);
-+ __ andl(temp, 0xFF);
- __ cmpl(temp, (int)bytecode());
- __ jcc(Assembler::equal, resolved);
-
-@@ -2907,7 +2904,7 @@
- __ movl(recv, flags);
- __ andl(recv, 0xFF);
- // recv count is 0 based?
-- __ movptr(recv, Address(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)));
-+ __ movl(recv, Address(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)));
- __ verify_oop(recv);
- }
-
-@@ -2925,10 +2922,11 @@
- // Make sure we don't need to mask flags for tosBits after the above shift
- ConstantPoolCacheEntry::verify_tosBits();
- // load return address
-- {
-- ExternalAddress table(is_invokeinterface ? (address)Interpreter::return_5_addrs_by_index_table() :
-- (address)Interpreter::return_3_addrs_by_index_table());
-- __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr)));
-+ { 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));
- }
-
- // push return address
-@@ -3055,6 +3053,57 @@
- // profile this call
- __ profile_virtual_call(rdx, rsi, rdi);
-
-+ if (MethodHandleSupport) { // %%% let's use this refactored code always
-+ Label no_such_interface, no_such_method;
-+
-+ __ lookup_interface_method(// inputs: rec. class, interface, itable index
-+ rdx, rax, rbx,
-+ // outputs: method, scan temp. reg
-+ rbx, rsi,
-+ no_such_interface);
-+
-+ // rbx,: methodOop to call
-+ // rcx: receiver
-+ // Check for abstract method error
-+ // Note: This should be done more efficiently via a throw_abstract_method_error
-+ // interpreter entry point and a conditional jump to it in case of a null
-+ // method.
-+ __ testptr(rbx, rbx);
-+ __ jcc(Assembler::zero, no_such_method);
-+
-+ // do the call
-+ // rcx: receiver
-+ // rbx,: methodOop
-+ __ jump_from_interpreted(rbx, rdx);
-+ __ should_not_reach_here();
-+
-+ // exception handling code follows...
-+ // note: must restore interpreter registers to canonical
-+ // state for exception handling to work correctly!
-+
-+ __ bind(no_such_method);
-+ // throw exception
-+ __ pop(rbx); // pop return address (pushed by prepare_invoke)
-+ __ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
-+ __ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
-+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
-+ // the call_VM checks for exception, so we should never return here.
-+ __ should_not_reach_here();
-+
-+ __ bind(no_such_interface);
-+ // throw exception
-+ __ pop(rbx); // pop return address (pushed by prepare_invoke)
-+ __ restore_bcp(); // rsi must be correct for exception handler (was destroyed)
-+ __ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
-+ __ call_VM(noreg, CAST_FROM_FN_PTR(address,
-+ InterpreterRuntime::throw_IncompatibleClassChangeError));
-+ // the call_VM checks for exception, so we should never return here.
-+ __ should_not_reach_here();
-+ return;
-+ }
-+
-+ // %%% remove this old code, in favor of the previous block:
-+
- __ mov(rdi, rdx); // Save klassOop in rdi
-
- // Compute start of first itableOffsetEntry (which is at the end of the vtable)
-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
-@@ -2858,7 +2858,7 @@
- __ movl(recv, flags);
- __ andl(recv, 0xFF);
- if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
-- __ movptr(recv, Address(rsp, recv, Address::times_8,
-+ __ movq(recv, Address(rsp, recv, Address::times_8,
- -Interpreter::expr_offset_in_bytes(1)));
- __ verify_oop(recv);
- }
-@@ -2881,7 +2881,7 @@
- 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));
-- __ movptr(flags, Address(rscratch1, flags, Address::times_8));
-+ __ movq(flags, Address(rscratch1, flags, Address::times_8));
- }
-
- // push return address
-@@ -3010,6 +3010,57 @@
- // profile this call
- __ profile_virtual_call(rdx, r13, r14);
-
-+ if (MethodHandleSupport) { // %%% let's use this refactored code always
-+ Label no_such_interface, no_such_method;
-+
-+ __ lookup_interface_method(// inputs: rec. class, interface, itable index
-+ rdx, rax, rbx,
-+ // outputs: method, scan temp. reg
-+ rbx, r13,
-+ no_such_interface);
-+
-+ // rbx,: methodOop to call
-+ // rcx: receiver
-+ // Check for abstract method error
-+ // Note: This should be done more efficiently via a throw_abstract_method_error
-+ // interpreter entry point and a conditional jump to it in case of a null
-+ // method.
-+ __ testptr(rbx, rbx);
-+ __ jcc(Assembler::zero, no_such_method);
-+
-+ // do the call
-+ // rcx: receiver
-+ // rbx,: methodOop
-+ __ jump_from_interpreted(rbx, rdx);
-+ __ should_not_reach_here();
-+
-+ // exception handling code follows...
-+ // note: must restore interpreter registers to canonical
-+ // state for exception handling to work correctly!
-+
-+ __ bind(no_such_method);
-+ // throw exception
-+ __ pop(rbx); // pop return address (pushed by prepare_invoke)
-+ __ restore_bcp(); // r13 must be correct for exception handler (was destroyed)
-+ __ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
-+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
-+ // the call_VM checks for exception, so we should never return here.
-+ __ should_not_reach_here();
-+
-+ __ bind(no_such_interface);
-+ // throw exception
-+ __ pop(rbx); // pop return address (pushed by prepare_invoke)
-+ __ restore_bcp(); // r13 must be correct for exception handler (was destroyed)
-+ __ restore_locals(); // make sure locals pointer is correct as well (was destroyed)
-+ __ call_VM(noreg, CAST_FROM_FN_PTR(address,
-+ InterpreterRuntime::throw_IncompatibleClassChangeError));
-+ // the call_VM checks for exception, so we should never return here.
-+ __ should_not_reach_here();
-+ return;
-+ }
-+
-+ // %%% remove this old code, in favor of the previous block:
-+
- __ mov(r14, rdx); // Save klassOop in r14
-
- // 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
-@@ -34,10 +34,16 @@
- extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index);
- #endif
-
--// used by compiler only; may use only caller saved registers rax, rbx, rcx.
--// rdx holds first int arg, rsi, rdi, rbp are callee-save & must be preserved.
--// Leave receiver in rcx; required behavior when +OptoArgsInRegisters
--// is modifed to put first oop in rcx.
-+// These stubs are used by the compiler only.
-+// Argument registers, which must be preserved:
-+// rcx - receiver (always first argument)
-+// rdx - second argument (if any)
-+// Other registers that might be usable:
-+// rax - inline cache register (is interface for itable stub)
-+// rbx - method (used when calling out to interpreter)
-+// Callee-save registers (when?):
-+// rsi, rdi
-+// Note that rax and rdx are also used for return values.
- //
- VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
- const int i486_code_length = VtableStub::pd_code_size_limit(true);
-@@ -94,16 +100,25 @@
- __ jmp( Address(method, methodOopDesc::from_compiled_offset()));
-
- masm->flush();
-+
-+ if (PrintMiscellaneous && (WizardMode || Verbose)) {
-+ tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
-+ vtable_index, s->entry_point(),
-+ (int)(s->code_end() - s->entry_point()),
-+ (int)(s->code_end() - __ pc()));
-+ }
-+ guarantee(__ pc() <= s->code_end(), "overflowed buffer");
-+
- s->set_exception_points(npe_addr, ame_addr);
- return s;
- }
-
-
--VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
-+VtableStub* VtableStubs::create_itable_stub(int itable_index) {
- // Note well: pd_code_size_limit is the absolute minimum we can get away with. If you
- // add code here, bump the code stub size returned by pd_code_size_limit!
- const int i486_code_length = VtableStub::pd_code_size_limit(false);
-- VtableStub* s = new(i486_code_length) VtableStub(false, vtable_index);
-+ VtableStub* s = new(i486_code_length) VtableStub(false, itable_index);
- ResourceMark rm;
- CodeBuffer cb(s->entry_point(), i486_code_length);
- MacroAssembler* masm = new MacroAssembler(&cb);
-@@ -121,8 +136,57 @@
-
- assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx");
-
-+ address npe_addr = NULL, ame_addr = NULL;
-+
-+ if (MethodHandleSupport) { // %%% let's use this refactored code always
-+ // Most registers are in use; we'll use rax, rbx, rcx, rsi
-+ Register restore_rcx = rcx;
-+ __ push(restore_rcx);
-+
-+ // get receiver klass (also an implicit null-check)
-+ npe_addr = __ pc();
-+ __ movptr(rcx, Address(rcx, oopDesc::klass_offset_in_bytes()));
-+
-+ const Register method = rbx;
-+ Label throw_icce;
-+
-+ // Get methodOop and entrypoint for compiler
-+ __ lookup_interface_method(// inputs: rec. class, interface, itable index
-+ rcx, rax, itable_index,
-+ // outputs: method, scan temp. reg
-+ method, rsi,
-+ throw_icce);
-+
-+ // Restore saved register, before possible trap.
-+ __ pop(restore_rcx);
-+
-+ // method (rbx): methodOop
-+ // rcx: receiver
-+
-+ #ifdef ASSERT
-+ if (DebugVtables) {
-+ Label L1;
-+ __ cmpl(method, NULL_WORD);
-+ __ jcc(Assembler::equal, L1);
-+ __ cmpl(Address(method, methodOopDesc::from_compiled_offset()), NULL_WORD);
-+ __ jcc(Assembler::notZero, L1);
-+ __ stop("methodOop is null");
-+ __ bind(L1);
-+ }
-+ #endif // ASSERT
-+
-+ ame_addr = __ pc();
-+ __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
-+
-+ __ bind(throw_icce);
-+ // Restore saved register
-+ __ pop(restore_rcx);
-+ __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
-+ } else {
-+ // %%% remove this old code, in favor of the previous block:
-+
- // get receiver klass (also an implicit null-check)
-- address npe_addr = __ pc();
-+ npe_addr = __ pc();
- __ movptr(rbx, Address(rcx, oopDesc::klass_offset_in_bytes()));
-
- __ mov(rsi, rbx); // Save klass in free register
-@@ -159,7 +223,7 @@
- __ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes()));
-
- // Compute itableMethodEntry.
-- const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes();
-+ const int method_offset = (itableMethodEntry::size() * wordSize * itable_index) + itableMethodEntry::method_offset_in_bytes();
-
- // Get methodOop and entrypoint for compiler
- const Register method = rbx;
-@@ -183,7 +247,7 @@
- }
- #endif // ASSERT
-
-- address ame_addr = __ pc();
-+ ame_addr = __ pc();
- __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
-
- __ bind(throw_icce);
-@@ -191,8 +255,15 @@
- __ pop(rdx);
- __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
-
-+ } // %%% ...end of code to remove.
- masm->flush();
-
-+ if (PrintMiscellaneous && (WizardMode || Verbose)) {
-+ tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
-+ itable_index, s->entry_point(),
-+ (int)(s->code_end() - s->entry_point()),
-+ (int)(s->code_end() - __ pc()));
-+ }
- guarantee(__ pc() <= s->code_end(), "overflowed buffer");
-
- s->set_exception_points(npe_addr, ame_addr);
-@@ -207,6 +278,8 @@
- return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
- } else {
- // Itable stub size
-+ if (MethodHandleSupport) // %%% let's use this refactored code always
-+ return (DebugVtables ? 159 : 79) + (CountCompiledCalls ? 6 : 0);
- return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0);
- }
- }
-diff --git a/src/share/vm/asm/assembler.cpp b/src/share/vm/asm/assembler.cpp
---- a/src/share/vm/asm/assembler.cpp
-+++ b/src/share/vm/asm/assembler.cpp
-@@ -239,6 +239,69 @@
- }
- }
-
-+struct DelayedConstant {
-+ typedef void (*value_fn_t)();
-+ BasicType type;
-+ intptr_t value;
-+ value_fn_t value_fn;
-+ enum { DC_LIMIT = 20 };
-+ static DelayedConstant delayed_constants[DC_LIMIT];
-+ static DelayedConstant* add(BasicType type, value_fn_t value_fn);
-+ bool match(BasicType t, value_fn_t cfn) {
-+ return type == t && value_fn == cfn;
-+ }
-+ static void update_all();
-+};
-+
-+DelayedConstant DelayedConstant::delayed_constants[DC_LIMIT];
-+// Default C structure initialization rules have the following effect here:
-+// = { { (BasicType)0, (intptr_t)NULL }, ... };
-+
-+DelayedConstant* DelayedConstant::add(BasicType type,
-+ DelayedConstant::value_fn_t cfn) {
-+ for (int i = 0; i < DC_LIMIT; i++) {
-+ DelayedConstant* dcon = &delayed_constants[i];
-+ if (dcon->match(type, cfn))
-+ return dcon;
-+ if (dcon->value_fn == NULL) {
-+ if (Atomic::cmpxchg_ptr(CAST_FROM_FN_PTR(void*, cfn), &dcon->value_fn, NULL) == NULL) {
-+ dcon->type = type;
-+ return dcon;
-+ }
-+ }
-+ }
-+ assert(false, "too many delayed constants");
-+ return NULL;
-+}
-+
-+void DelayedConstant::update_all() {
-+ for (int i = 0; i < DC_LIMIT; i++) {
-+ DelayedConstant* dcon = &delayed_constants[i];
-+ if (dcon->value_fn != NULL && dcon->value == 0) {
-+ typedef int (*int_fn_t)();
-+ typedef address (*address_fn_t)();
-+ switch (dcon->type) {
-+ case T_INT: dcon->value = (intptr_t) ((int_fn_t) dcon->value_fn)(); break;
-+ case T_ADDRESS: dcon->value = (intptr_t) ((address_fn_t)dcon->value_fn)(); break;
-+ }
-+ }
-+ }
-+}
-+
-+intptr_t* AbstractAssembler::delayed_value_addr(int(*value_fn)()) {
-+ DelayedConstant* dcon = DelayedConstant::add(T_INT, (DelayedConstant::value_fn_t) value_fn);
-+ return &dcon->value;
-+}
-+address* AbstractAssembler::delayed_value_addr(address(*value_fn)()) {
-+ DelayedConstant* dcon = DelayedConstant::add(T_ADDRESS, (DelayedConstant::value_fn_t) value_fn);
-+ return (address*) &dcon->value;
-+}
-+void AbstractAssembler::update_delayed_values() {
-+ DelayedConstant::update_all();
-+}
-+
-+
-+
-
- void AbstractAssembler::block_comment(const char* comment) {
- if (sect() == CodeBuffer::SECT_INSTS) {
-diff --git a/src/share/vm/asm/assembler.hpp b/src/share/vm/asm/assembler.hpp
---- a/src/share/vm/asm/assembler.hpp
-+++ b/src/share/vm/asm/assembler.hpp
-@@ -280,6 +280,14 @@
- inline address address_constant(Label& L);
- inline address address_table_constant(GrowableArray<Label*> label);
-
-+ // Bootstrapping aid to cope with delayed determination of constants.
-+ // Returns a static address which will eventually contain the constant.
-+ // The value zero (NULL) stands instead of a constant which is still uncomputed.
-+ // Use sparingly.
-+ static intptr_t* delayed_value_addr(int(*constant_fn)());
-+ static address* delayed_value_addr(address(*constant_fn)());
-+ static void update_delayed_values();
-+
- // 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/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,30 @@
- }
-
- // ------------------------------------------------------------------
-+// invokedynamic support
-+//
-+bool ciMethod::is_method_handle_invoke() {
-+ check_is_loaded();
-+ bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
-+#ifdef ASSERT
-+ {
-+ VM_ENTRY_MARK;
-+ bool flag2 = get_methodOop()->is_method_handle_invoke();
-+ assert(flag == flag2, "consistent");
-+ }
-+#endif //ASSERT
-+ return flag;
-+}
-+
-+ciInstance* ciMethod::method_handle_type() {
-+ check_is_loaded();
-+ VM_ENTRY_MARK;
-+ oop mtype = get_methodOop()->method_handle_type();
-+ return CURRENT_THREAD_ENV->get_object(mtype)->as_instance();
-+}
-+
-+
-+// ------------------------------------------------------------------
- // ciMethod::build_method_data
- //
- // Generate new methodDataOop objects at compile time.
-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,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();
-
- // What kind of ciObject is this?
- bool is_method() { return true; }
-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
-@@ -1842,6 +1842,11 @@
- _has_vanilla_constructor = true;
- }
-
-+ if (MethodHandleSupport && m->is_method_handle_invoke()) {
-+ THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
-+ "Method handle invokers must be defined internally to the VM", nullHandle);
-+ }
-+
- return m;
- }
-
-@@ -2465,9 +2470,82 @@
- }
-
-
-+void ClassFileParser::java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
-+ typeArrayHandle* fields_ptr,
-+ FieldAllocationCount *fac_ptr,
-+ TRAPS) {
-+ // Add fake fields for java.dyn.MethodHandle instances
-+ //
-+ // This is not particularly nice, but since there is no way to express
-+ // a native wordSize field in Java, we must do it at this level.
-+
-+ if (!MethodHandleSupport) return;
-+
-+ int word_sig_index = 0;
-+ const int cp_size = cp->length();
-+ for (int index = 1; index < cp_size; index++) {
-+ if (cp->tag_at(index).is_utf8() &&
-+ cp->symbol_at(index) == vmSymbols::machine_word_signature()) {
-+ word_sig_index = index;
-+ break;
-+ }
-+ }
-+
-+ if (word_sig_index == 0)
-+ THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
-+ "missing I or J signature (for vmentry) in java.dyn.MethodHandle");
-+
-+ bool found_vmentry = false;
-+
-+ const int n = (*fields_ptr)()->length();
-+ for (int i = 0; i < n; i += instanceKlass::next_offset) {
-+ int name_index = (*fields_ptr)->ushort_at(i + instanceKlass::name_index_offset);
-+ int sig_index = (*fields_ptr)->ushort_at(i + instanceKlass::signature_index_offset);
-+ int acc_flags = (*fields_ptr)->ushort_at(i + instanceKlass::access_flags_offset);
-+ symbolOop f_name = cp->symbol_at(name_index);
-+ symbolOop f_sig = cp->symbol_at(sig_index);
-+ if (f_sig == vmSymbols::byte_signature() &&
-+ f_name == vmSymbols::vmentry_name() &&
-+ (acc_flags & JVM_ACC_STATIC) == 0) {
-+ // Adjust the field type from byte to an unmanaged pointer.
-+ assert(fac_ptr->nonstatic_byte_count > 0, "");
-+ fac_ptr->nonstatic_byte_count -= 1;
-+ (*fields_ptr)->ushort_at_put(i + instanceKlass::signature_index_offset,
-+ word_sig_index);
-+ if (wordSize == jintSize) {
-+ fac_ptr->nonstatic_word_count += 1;
-+ } else {
-+ fac_ptr->nonstatic_double_count += 1;
-+ }
-+
-+ FieldAllocationType atype = (FieldAllocationType) (*fields_ptr)->ushort_at(i+4);
-+ assert(atype == NONSTATIC_BYTE, "");
-+ FieldAllocationType new_atype = NONSTATIC_WORD;
-+ if (wordSize > jintSize) {
-+ if (Universe::field_type_should_be_aligned(T_LONG)) {
-+ atype = NONSTATIC_ALIGNED_DOUBLE;
-+ } else {
-+ atype = NONSTATIC_DOUBLE;
-+ }
-+ }
-+ (*fields_ptr)->ushort_at_put(i+4, new_atype);
-+
-+ found_vmentry = true;
-+ break;
-+ }
-+ }
-+
-+ if (!found_vmentry)
-+ THROW_MSG(vmSymbols::java_lang_VirtualMachineError(),
-+ "missing vmentry byte field in java.dyn.MethodHandle");
-+
-+}
-+
-+
- instanceKlassHandle ClassFileParser::parseClassFile(symbolHandle name,
- Handle class_loader,
- Handle protection_domain,
-+ KlassHandle host_klass,
- GrowableArray<Handle>* cp_patches,
- symbolHandle& parsed_name,
- TRAPS) {
-@@ -2500,6 +2578,7 @@
- }
- }
-
-+ _host_klass = host_klass;
- _cp_patches = cp_patches;
-
- instanceKlassHandle nullHandle;
-@@ -2807,6 +2886,11 @@
- java_lang_Class_fix_pre(&methods, &fac, CHECK_(nullHandle));
- }
-
-+ // adjust the vmentry field declaration in java.dyn.MethodHandle
-+ if (MethodHandleSupport && class_name() == vmSymbols::impl_java_dyn_MethodHandleImpl() && class_loader.is_null()) {
-+ java_dyn_MethodHandle_fix_pre(cp, &fields, &fac, CHECK_(nullHandle));
-+ }
-+
- // Add a fake "discovered" field if it is not present
- // for compatibility with earlier jdk's.
- if (class_name() == vmSymbols::java_lang_ref_Reference()
-@@ -3133,7 +3217,7 @@
- this_klass->set_method_ordering(method_ordering());
- this_klass->set_initial_method_idnum(methods->length());
- this_klass->set_name(cp->klass_name_at(this_class_index));
-- if (LinkWellKnownClasses) // I am well known to myself
-+ if (LinkWellKnownClasses || is_anonymous()) // I am well known to myself
- cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
- this_klass->set_protection_domain(protection_domain());
- this_klass->set_fields_annotations(fields_annotations());
-diff --git a/src/share/vm/classfile/classFileParser.hpp b/src/share/vm/classfile/classFileParser.hpp
---- a/src/share/vm/classfile/classFileParser.hpp
-+++ b/src/share/vm/classfile/classFileParser.hpp
-@@ -33,6 +33,7 @@
- u2 _major_version;
- u2 _minor_version;
- symbolHandle _class_name;
-+ KlassHandle _host_klass;
- GrowableArray<Handle>* _cp_patches; // overrides for CP entries
-
- bool _has_finalizer;
-@@ -145,6 +146,11 @@
- // Adjust the next_nonstatic_oop_offset to place the fake fields
- // before any Java fields.
- void java_lang_Class_fix_post(int* next_nonstatic_oop_offset);
-+ // Adjust the field allocation counts for java.dyn.MethodHandle to add
-+ // a fake address (void*) field.
-+ void java_dyn_MethodHandle_fix_pre(constantPoolHandle cp,
-+ typeArrayHandle* fields_ptr,
-+ FieldAllocationCount *fac_ptr, TRAPS);
-
- // Format checker methods
- void classfile_parse_error(const char* msg, TRAPS);
-@@ -204,6 +210,10 @@
- char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
- char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
-
-+ bool is_anonymous() {
-+ assert(AnonymousClasses || _host_klass.is_null(), "");
-+ return _host_klass.not_null();
-+ }
- bool has_cp_patch_at(int index) {
- assert(AnonymousClasses, "");
- assert(index >= 0, "oob");
-@@ -249,11 +259,13 @@
- Handle protection_domain,
- symbolHandle& parsed_name,
- TRAPS) {
-- return parseClassFile(name, class_loader, protection_domain, NULL, parsed_name, THREAD);
-+ KlassHandle no_host_klass;
-+ return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, THREAD);
- }
- instanceKlassHandle parseClassFile(symbolHandle name,
- Handle class_loader,
- Handle protection_domain,
-+ KlassHandle host_klass,
- GrowableArray<Handle>* cp_patches,
- symbolHandle& parsed_name,
- TRAPS);
-diff --git a/src/share/vm/classfile/dictionary.cpp b/src/share/vm/classfile/dictionary.cpp
---- a/src/share/vm/classfile/dictionary.cpp
-+++ b/src/share/vm/classfile/dictionary.cpp
-@@ -549,6 +549,63 @@
- }
- }
-
-+SymbolPropertyTable::SymbolPropertyTable(int table_size)
-+ : Hashtable(table_size, sizeof(SymbolPropertyEntry))
-+{
-+}
-+SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t,
-+ int number_of_entries)
-+ : Hashtable(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
-+{
-+}
-+
-+
-+SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash,
-+ symbolHandle sym) {
-+ assert(index == index_for(sym), "incorrect index?");
-+ for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
-+ if (p->hash() == hash && p->symbol() == sym()) {
-+ return p;
-+ }
-+ }
-+ return NULL;
-+}
-+
-+
-+SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash,
-+ symbolHandle sym) {
-+ assert_locked_or_safepoint(SystemDictionary_lock);
-+ assert(index == index_for(sym), "incorrect index?");
-+ assert(find_entry(index, hash, sym) == NULL, "no double entry");
-+
-+ SymbolPropertyEntry* p = new_entry(hash, sym());
-+ Hashtable::add_entry(index, p);
-+ return p;
-+}
-+
-+
-+void SymbolPropertyTable::oops_do(OopClosure* f) {
-+ for (int index = 0; index < table_size(); index++) {
-+ for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
-+ f->do_oop((oop*) p->symbol_addr());
-+ if (p->property_oop() != NULL) {
-+ f->do_oop(p->property_oop_addr());
-+ }
-+ }
-+ }
-+}
-+
-+void SymbolPropertyTable::methods_do(void f(methodOop)) {
-+ for (int index = 0; index < table_size(); index++) {
-+ for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
-+ oop prop = p->property_oop();
-+ if (prop != NULL && prop->is_method()) {
-+ f((methodOop)prop);
-+ }
-+ }
-+ }
-+}
-+
-
- // ----------------------------------------------------------------------------
- #ifndef PRODUCT
-diff --git a/src/share/vm/classfile/dictionary.hpp b/src/share/vm/classfile/dictionary.hpp
---- a/src/share/vm/classfile/dictionary.hpp
-+++ b/src/share/vm/classfile/dictionary.hpp
-@@ -217,3 +217,107 @@
- tty->print_cr("pd set = #%d", count);
- }
- };
-+
-+class SymbolPropertyEntry : public HashtableEntry {
-+ friend class VMStructs;
-+ private:
-+ oop _property_oop;
-+ address _property_data;
-+
-+ public:
-+ symbolOop symbol() const { return (symbolOop) literal(); }
-+
-+ oop property_oop() const { return _property_oop; }
-+ void set_property_oop(oop p) { _property_oop = p; }
-+
-+ address property_data() const { return _property_data; }
-+ void set_property_data(address p) { _property_data = p; }
-+
-+ SymbolPropertyEntry* next() const {
-+ return (SymbolPropertyEntry*)HashtableEntry::next();
-+ }
-+
-+ SymbolPropertyEntry** next_addr() {
-+ return (SymbolPropertyEntry**)HashtableEntry::next_addr();
-+ }
-+
-+ oop* symbol_addr() { return literal_addr(); }
-+ oop* property_oop_addr() { return &_property_oop; }
-+
-+ void print_on(outputStream* st) const {
-+ symbol()->print_value_on(st);
-+ st->print(" -> ");
-+ bool printed = false;
-+ if (property_oop() != NULL) {
-+ property_oop()->print_value_on(st);
-+ printed = true;
-+ }
-+ if (property_data() != NULL) {
-+ if (printed) st->print(" and ");
-+ st->print(INTPTR_FORMAT, property_data());
-+ printed = true;
-+ }
-+ st->print_cr(printed ? "" : "(empty)");
-+ }
-+};
-+
-+class SymbolPropertyTable : public Hashtable {
-+ friend class VMStructs;
-+private:
-+ SymbolPropertyEntry* bucket(int i) {
-+ return (SymbolPropertyEntry*) Hashtable::bucket(i);
-+ }
-+
-+ // The following method is not MT-safe and must be done under lock.
-+ SymbolPropertyEntry** bucket_addr(int i) {
-+ return (SymbolPropertyEntry**) Hashtable::bucket_addr(i);
-+ }
-+
-+ void add_entry(int index, SymbolPropertyEntry* new_entry) {
-+ ShouldNotReachHere();
-+ }
-+ void set_entry(int index, SymbolPropertyEntry* new_entry) {
-+ ShouldNotReachHere();
-+ }
-+
-+ SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol) {
-+ SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol);
-+ entry->set_property_oop(NULL);
-+ entry->set_property_data(NULL);
-+ return entry;
-+ }
-+
-+public:
-+ SymbolPropertyTable(int table_size);
-+ SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries);
-+
-+ void free_entry(SymbolPropertyEntry* entry) {
-+ Hashtable::free_entry(entry);
-+ }
-+
-+ unsigned int compute_hash(symbolHandle sym) {
-+ // Use the regular identity_hash.
-+ return Hashtable::compute_hash(sym);
-+ }
-+
-+ // need not be locked; no state change
-+ SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name);
-+
-+ // must be done under SystemDictionary_lock
-+ SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name);
-+
-+ // GC support
-+ void oops_do(OopClosure* f);
-+ void methods_do(void f(methodOop));
-+
-+ // Sharing support
-+ void dump(SerializeOopClosure* soc);
-+ void restore(SerializeOopClosure* soc);
-+ void reorder_dictionary();
-+
-+#ifndef PRODUCT
-+ void print();
-+#endif
-+ void verify();
-+};
-+
-diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp
---- a/src/share/vm/classfile/javaClasses.cpp
-+++ b/src/share/vm/classfile/javaClasses.cpp
-@@ -25,13 +25,24 @@
- # include "incls/_precompiled.incl"
- # include "incls/_javaClasses.cpp.incl"
-
-+static bool find_field(instanceKlass* ik,
-+ symbolOop name_symbol, symbolOop signature_symbol,
-+ fieldDescriptor* fd,
-+ bool allow_super = false) {
-+ if (allow_super)
-+ return ik->find_field(name_symbol, signature_symbol, fd) != NULL;
-+ else
-+ return ik->find_local_field(name_symbol, signature_symbol, fd);
-+}
-+
- // Helpful routine for computing field offsets at run time rather than hardcoding them
- static void
- compute_offset(int &dest_offset,
-- klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) {
-+ klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol,
-+ bool allow_super = false) {
- fieldDescriptor fd;
- instanceKlass* ik = instanceKlass::cast(klass_oop);
-- if (!ik->find_local_field(name_symbol, signature_symbol, &fd)) {
-+ if (!find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
- ResourceMark rm;
- tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
- fatal("Invalid layout of preloaded class");
-@@ -42,14 +53,16 @@
- // Same as above but for "optional" offsets that might not be present in certain JDK versions
- static void
- compute_optional_offset(int& dest_offset,
-- klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol) {
-+ klassOop klass_oop, symbolOop name_symbol, symbolOop signature_symbol,
-+ bool allow_super = false) {
- fieldDescriptor fd;
- instanceKlass* ik = instanceKlass::cast(klass_oop);
-- if (ik->find_local_field(name_symbol, signature_symbol, &fd)) {
-+ if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
- dest_offset = fd.offset();
- }
- }
-
-+
- Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
- // Create the String object first, so there's a chance that the String
- // and the char array it points to end up in the same cache line.
-@@ -239,21 +252,19 @@
- typeArrayOop value = java_lang_String::value(obj);
- int offset = java_lang_String::offset(obj);
- int length = java_lang_String::length(obj);
-+ jchar* base = value->char_at_addr(offset);
-+ symbolOop sym = SymbolTable::lookup_unicode(base, length, THREAD);
-+ return symbolHandle(THREAD, sym);
-+}
-
-- ResourceMark rm(THREAD);
-- symbolHandle result;
-+symbolOop java_lang_String::as_symbol_or_null(oop java_string) {
-+ typeArrayOop value = java_lang_String::value(java_string);
-+ int offset = java_lang_String::offset(java_string);
-+ int length = java_lang_String::length(java_string);
-+ jchar* base = value->char_at_addr(offset);
-+ return SymbolTable::probe_unicode(base, length);
-+}
-
-- if (length > 0) {
-- int utf8_length = UNICODE::utf8_length(value->char_at_addr(offset), length);
-- char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
-- UNICODE::convert_to_utf8(value->char_at_addr(offset), length, chars);
-- // Allocate the symbol
-- result = oopFactory::new_symbol_handle(chars, utf8_length, CHECK_(symbolHandle()));
-- } else {
-- result = oopFactory::new_symbol_handle("", 0, CHECK_(symbolHandle()));
-- }
-- return result;
--}
-
- int java_lang_String::utf8_length(oop java_string) {
- typeArrayOop value = java_lang_String::value(java_string);
-@@ -385,13 +396,53 @@
- }
-
-
-+void java_lang_Class::print_signature(oop java_class, outputStream* st) {
-+ assert(java_lang_Class::is_instance(java_class), "must be a Class object");
-+ symbolOop name = NULL;
-+ bool is_instance = false;
-+ if (is_primitive(java_class)) {
-+ name = vmSymbols::type_signature(primitive_type(java_class));
-+ } else {
-+ klassOop k = as_klassOop(java_class);
-+ is_instance = Klass::cast(k)->oop_is_instance();
-+ name = Klass::cast(k)->name();
-+ }
-+ if (name == NULL) {
-+ st->print("<null>");
-+ return;
-+ }
-+ if (is_instance) st->print("L");
-+ st->write((char*) name->base(), (int) name->utf8_length());
-+ if (is_instance) st->print(";");
-+}
-+
-+symbolOop java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) {
-+ assert(java_lang_Class::is_instance(java_class), "must be a Class object");
-+ symbolOop name = NULL;
-+ if (is_primitive(java_class)) {
-+ return vmSymbols::type_signature(primitive_type(java_class));
-+ } else {
-+ klassOop k = as_klassOop(java_class);
-+ if (!Klass::cast(k)->oop_is_instance()) {
-+ return Klass::cast(k)->name();
-+ } else {
-+ ResourceMark rm;
-+ const char* sigstr = Klass::cast(k)->signature_name();
-+ int siglen = (int) strlen(sigstr);
-+ if (!intern_if_not_found)
-+ return SymbolTable::probe(sigstr, siglen);
-+ else
-+ return oopFactory::new_symbol(sigstr, siglen, THREAD);
-+ }
-+ }
-+}
-+
- klassOop java_lang_Class::array_klass(oop java_class) {
- klassOop k = klassOop(java_class->obj_field(array_klass_offset));
- assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_javaArray(), "should be array klass");
- return k;
- }
-
--
- void java_lang_Class::set_array_klass(oop java_class, klassOop klass) {
- assert(klass->is_klass() && Klass::cast(klass)->oop_is_javaArray(), "should be array klass");
- java_class->obj_field_put(array_klass_offset, klass);
-@@ -412,6 +463,8 @@
-
-
- bool java_lang_Class::is_primitive(oop java_class) {
-+ // should assert:
-+ //assert(java_lang_Class::is_instance(java_class), "must be a Class object");
- klassOop k = klassOop(java_class->obj_field(klass_offset));
- return k == NULL;
- }
-@@ -431,6 +484,19 @@
- return type;
- }
-
-+BasicType java_lang_Class::as_BasicType(oop java_class, klassOop* reference_klass) {
-+ assert(java_lang_Class::is_instance(java_class), "must be a Class object");
-+ if (is_primitive(java_class)) {
-+ if (reference_klass != NULL)
-+ (*reference_klass) = NULL;
-+ return primitive_type(java_class);
-+ } else {
-+ if (reference_klass != NULL)
-+ (*reference_klass) = as_klassOop(java_class);
-+ return T_OBJECT;
-+ }
-+}
-+
-
- oop java_lang_Class::primitive_mirror(BasicType t) {
- oop mirror = Universe::java_mirror(t);
-@@ -1988,6 +2054,21 @@
- }
-
-
-+void java_lang_boxing_object::print(BasicType type, jvalue* value, outputStream* st) {
-+ switch (type) {
-+ case T_BOOLEAN: st->print("%s", value->z ? "true" : "false"); break;
-+ case T_CHAR: st->print("%d", value->c); break;
-+ case T_BYTE: st->print("%d", value->b); break;
-+ case T_SHORT: st->print("%d", value->s); break;
-+ case T_INT: st->print("%d", value->i); break;
-+ case T_LONG: st->print(INT64_FORMAT, value->j); break;
-+ case T_FLOAT: st->print("%f", value->f); break;
-+ case T_DOUBLE: st->print("%lf", value->d); break;
-+ default: st->print("type %d?", type); break;
-+ }
-+}
-+
-+
- // Support for java_lang_ref_Reference
- oop java_lang_ref_Reference::pending_list_lock() {
- instanceKlass* ik = instanceKlass::cast(SystemDictionary::reference_klass());
-@@ -2037,13 +2118,324 @@
- }
-
-
-+// Support for java_dyn_MethodHandle
-+
-+int java_dyn_MethodHandle::_type_offset;
-+int java_dyn_MethodHandle::_vmtarget_offset;
-+int java_dyn_MethodHandle::_vmentry_offset;
-+int java_dyn_MethodHandle::_vmslots_offset;
-+
-+int impl_java_dyn_MemberName::_clazz_offset;
-+int impl_java_dyn_MemberName::_name_offset;
-+int impl_java_dyn_MemberName::_type_offset;
-+int impl_java_dyn_MemberName::_flags_offset;
-+int impl_java_dyn_MemberName::_vmtarget_offset;
-+int impl_java_dyn_MemberName::_vmindex_offset;
-+
-+int impl_java_dyn_DirectMethodHandle::_vmindex_offset;
-+
-+int impl_java_dyn_BoundMethodHandle::_argument_offset;
-+int impl_java_dyn_BoundMethodHandle::_vmargslot_offset;
-+
-+int impl_java_dyn_AdapterMethodHandle::_conversion_offset;
-+
-+void java_dyn_MethodHandle::compute_offsets() {
-+ klassOop k = SystemDictionary::MethodHandle_klass();
-+ if (k != NULL && MethodHandleSupport) {
-+ compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true);
-+ compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature(), true);
-+ compute_offset(_vmentry_offset, k, vmSymbols::vmentry_name(), vmSymbols::machine_word_signature(), true);
-+
-+ // Note: MH.vmslots (if it is present) is a hoisted copy of MH.type.form.vmslots.
-+ // It is optional pending experiments to keep or toss.
-+ compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true);
-+ }
-+}
-+
-+void impl_java_dyn_MemberName::compute_offsets() {
-+ klassOop k = SystemDictionary::MemberName_klass();
-+ if (k != NULL && MethodHandleSupport) {
-+ compute_offset(_clazz_offset, k, vmSymbols::clazz_name(), vmSymbols::class_signature());
-+ compute_offset(_name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
-+ compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::object_signature());
-+ compute_offset(_flags_offset, k, vmSymbols::flags_name(), vmSymbols::int_signature());
-+ compute_offset(_vmtarget_offset, k, vmSymbols::vmtarget_name(), vmSymbols::object_signature());
-+ compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature());
-+ }
-+}
-+
-+void impl_java_dyn_DirectMethodHandle::compute_offsets() {
-+ klassOop k = SystemDictionary::DirectMethodHandle_klass();
-+ if (k != NULL && MethodHandleSupport) {
-+ compute_offset(_vmindex_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature(), true);
-+ }
-+}
-+
-+void impl_java_dyn_BoundMethodHandle::compute_offsets() {
-+ klassOop k = SystemDictionary::BoundMethodHandle_klass();
-+ if (k != NULL && MethodHandleSupport) {
-+ compute_offset(_vmargslot_offset, k, vmSymbols::vmargslot_name(), vmSymbols::int_signature(), true);
-+ compute_offset(_argument_offset, k, vmSymbols::argument_name(), vmSymbols::object_signature(), true);
-+ }
-+}
-+
-+void impl_java_dyn_AdapterMethodHandle::compute_offsets() {
-+ klassOop k = SystemDictionary::AdapterMethodHandle_klass();
-+ if (k != NULL && MethodHandleSupport) {
-+ compute_offset(_conversion_offset, k, vmSymbols::conversion_name(), vmSymbols::int_signature(), true);
-+ }
-+}
-+
-+oop java_dyn_MethodHandle::type(oop mh) {
-+ return mh->obj_field(_type_offset);
-+}
-+
-+void java_dyn_MethodHandle::set_type(oop mh, oop mtype) {
-+ mh->obj_field_put(_type_offset, mtype);
-+}
-+
-+int java_dyn_MethodHandle::vmslots(oop mh) {
-+ int vmslots_offset = _vmslots_offset;
-+ if (vmslots_offset != 0) {
-+#ifdef ASSERT
-+ int x = mh->int_field(vmslots_offset);
-+ int y = compute_vmslots(mh);
-+ assert(x == y, "correct hoisted value");
-+#endif
-+ return mh->int_field(vmslots_offset);
-+ } else {
-+ return compute_vmslots(mh);
-+ }
-+}
-+
-+// if MH.vmslots exists, hoist into it the value of type.form.vmslots
-+void java_dyn_MethodHandle::init_vmslots(oop mh) {
-+ int vmslots_offset = _vmslots_offset;
-+ if (vmslots_offset != 0) {
-+ mh->int_field_put(vmslots_offset, compute_vmslots(mh));
-+ }
-+}
-+
-+// fetch type.form.vmslots, which is the number of JVM stack slots
-+// required to carry the arguments of this MH
-+int java_dyn_MethodHandle::compute_vmslots(oop mh) {
-+ oop mtype = type(mh);
-+ if (mtype == NULL) return 0; // Java code would get NPE
-+ oop form = java_dyn_MethodType::form(mtype);
-+ if (form == NULL) return 0; // Java code would get NPE
-+ return java_dyn_MethodTypeForm::vmslots(form);
-+}
-+
-+// fetch the low-level entry point for this mh
-+MethodEntry* java_dyn_MethodHandle::vmentry(oop mh) {
-+ return (MethodEntry*) mh->address_field(_vmentry_offset);
-+}
-+
-+void java_dyn_MethodHandle::set_vmentry(oop mh, MethodEntry* me) {
-+ assert(_vmentry_offset != 0, "must be present");
-+
-+ // This is always the final step that initializes a valid method handle:
-+ mh->release_address_field_put(_vmentry_offset, (address) me);
-+
-+ // There should be enough memory barriers on exit from native methods
-+ // to ensure that the MH is fully initialized to all threads before
-+ // Java code can publish it in global data structures.
-+ // But just in case, we use release_address_field_put.
-+}
-+
-+/// MemberName accessors
-+
-+oop impl_java_dyn_MemberName::clazz(oop mname) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ return mname->obj_field(_clazz_offset);
-+}
-+
-+void impl_java_dyn_MemberName::set_clazz(oop mname, oop clazz) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ mname->obj_field_put(_clazz_offset, clazz);
-+}
-+
-+oop impl_java_dyn_MemberName::name(oop mname) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ return mname->obj_field(_name_offset);
-+}
-+
-+void impl_java_dyn_MemberName::set_name(oop mname, oop name) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ mname->obj_field_put(_name_offset, name);
-+}
-+
-+oop impl_java_dyn_MemberName::type(oop mname) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ return mname->obj_field(_type_offset);
-+}
-+
-+void impl_java_dyn_MemberName::set_type(oop mname, oop type) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ mname->obj_field_put(_type_offset, type);
-+}
-+
-+int impl_java_dyn_MemberName::flags(oop mname) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ return mname->int_field(_flags_offset);
-+}
-+
-+void impl_java_dyn_MemberName::set_flags(oop mname, int flags) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ mname->int_field_put(_flags_offset, flags);
-+}
-+
-+oop impl_java_dyn_MemberName::vmtarget(oop mname) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ return mname->obj_field(_vmtarget_offset);
-+}
-+
-+void impl_java_dyn_MemberName::set_vmtarget(oop mname, oop ref) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ mname->obj_field_put(_vmtarget_offset, ref);
-+}
-+
-+int impl_java_dyn_MemberName::vmindex(oop mname) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ return mname->int_field(_vmindex_offset);
-+}
-+
-+void impl_java_dyn_MemberName::set_vmindex(oop mname, int index) {
-+ assert(Klass::cast(mname->klass())->is_subclass_of(SystemDictionary::MemberName_klass()), "wrong type");
-+ mname->int_field_put(_vmindex_offset, index);
-+}
-+
-+oop java_dyn_MethodHandle::vmtarget(oop mh) {
-+ assert(Klass::cast(mh->klass())->is_subclass_of(SystemDictionary::MethodHandle_klass()), "wrong type");
-+ return mh->obj_field(_vmtarget_offset);
-+}
-+
-+void java_dyn_MethodHandle::set_vmtarget(oop mh, oop ref) {
-+ assert(Klass::cast(mh->klass())->is_subclass_of(SystemDictionary::MethodHandle_klass()), "wrong type");
-+ mh->obj_field_put(_vmtarget_offset, ref);
-+}
-+
-+int impl_java_dyn_DirectMethodHandle::vmindex(oop mh) {
-+ assert(Klass::cast(mh->klass())->is_subclass_of(SystemDictionary::DirectMethodHandle_klass()), "wrong type");
-+ return mh->int_field(_vmindex_offset);
-+}
-+
-+void impl_java_dyn_DirectMethodHandle::set_vmindex(oop mh, int index) {
-+ assert(Klass::cast(mh->klass())->is_subclass_of(SystemDictionary::DirectMethodHandle_klass()), "wrong type");
-+ mh->int_field_put(_vmindex_offset, index);
-+}
-+
-+int impl_java_dyn_BoundMethodHandle::vmargslot(oop mh) {
-+ assert(Klass::cast(mh->klass())->is_subclass_of(SystemDictionary::BoundMethodHandle_klass()), "wrong type");
-+ return mh->int_field(_vmargslot_offset);
-+}
-+
-+oop impl_java_dyn_BoundMethodHandle::argument(oop mh) {
-+ assert(Klass::cast(mh->klass())->is_subclass_of(SystemDictionary::BoundMethodHandle_klass()), "wrong type");
-+ return mh->obj_field(_argument_offset);
-+}
-+
-+int impl_java_dyn_AdapterMethodHandle::conversion(oop mh) {
-+ assert(mh->klass() == SystemDictionary::AdapterMethodHandle_klass(), "AMH only");
-+ return mh->int_field(_conversion_offset);
-+}
-+
-+void impl_java_dyn_AdapterMethodHandle::set_conversion(oop mh, int conv) {
-+ assert(mh->klass() == SystemDictionary::AdapterMethodHandle_klass(), "AMH only");
-+ mh->int_field_put(_conversion_offset, conv);
-+}
-+
-+
-+// Support for java_dyn_MethodType
-+
-+int java_dyn_MethodType::_rtype_offset;
-+int java_dyn_MethodType::_ptypes_offset;
-+int java_dyn_MethodType::_form_offset;
-+
-+void java_dyn_MethodType::compute_offsets() {
-+ klassOop k = SystemDictionary::MethodType_klass();
-+ if (k != NULL) {
-+ compute_offset(_rtype_offset, k, vmSymbols::rtype_name(), vmSymbols::class_signature());
-+ compute_offset(_ptypes_offset, k, vmSymbols::ptypes_name(), vmSymbols::class_array_signature());
-+ compute_offset(_form_offset, k, vmSymbols::form_name(), vmSymbols::java_dyn_MethodTypeForm_signature());
-+ }
-+}
-+
-+void java_dyn_MethodType::print_signature(oop mt, outputStream* st) {
-+ st->print("(");
-+ objArrayOop pts = ptypes(mt);
-+ for (int i = 0, limit = pts->length(); i < limit; i++) {
-+ java_lang_Class::print_signature(pts->obj_at(i), st);
-+ }
-+ st->print(")");
-+ java_lang_Class::print_signature(rtype(mt), st);
-+}
-+
-+symbolOop java_dyn_MethodType::as_signature(oop mt, bool intern_if_not_found, TRAPS) {
-+ ResourceMark rm;
-+ stringStream buffer(128);
-+ print_signature(mt, &buffer);
-+ const char* sigstr = buffer.base();
-+ int siglen = (int) buffer.size();
-+ if (!intern_if_not_found)
-+ return SymbolTable::probe(sigstr, siglen);
-+ else
-+ return oopFactory::new_symbol(sigstr, siglen, THREAD);
-+}
-+
-+oop java_dyn_MethodType::rtype(oop mt) {
-+ assert(is_instance(mt), "must be a MethodType");
-+ return mt->obj_field(_rtype_offset);
-+}
-+
-+objArrayOop java_dyn_MethodType::ptypes(oop mt) {
-+ assert(is_instance(mt), "must be a MethodType");
-+ return (objArrayOop) mt->obj_field(_ptypes_offset);
-+}
-+
-+oop java_dyn_MethodType::form(oop mt) {
-+ assert(is_instance(mt), "must be a MethodType");
-+ return mt->obj_field(_form_offset);
-+}
-+
-+oop java_dyn_MethodType::ptype(oop mt, int idx) {
-+ return ptypes(mt)->obj_at(idx);
-+}
-+
-+
-+
-+// Support for java_dyn_MethodTypeForm
-+
-+int java_dyn_MethodTypeForm::_vmslots_offset;
-+int java_dyn_MethodTypeForm::_erasedType_offset;
-+
-+void java_dyn_MethodTypeForm::compute_offsets() {
-+ klassOop k = SystemDictionary::MethodTypeForm_klass();
-+ if (k != NULL) {
-+ compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true);
-+ compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_dyn_MethodType_signature(), true);
-+ }
-+}
-+
-+int java_dyn_MethodTypeForm::vmslots(oop mtform) {
-+ assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only");
-+ return mtform->int_field(_vmslots_offset);
-+}
-+
-+oop java_dyn_MethodTypeForm::erasedType(oop mtform) {
-+ assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only");
-+ return mtform->obj_field(_erasedType_offset);
-+}
-+
-+
-+
-+
- // Support for java_security_AccessControlContext
-
- int java_security_AccessControlContext::_context_offset = 0;
- int java_security_AccessControlContext::_privilegedContext_offset = 0;
- int java_security_AccessControlContext::_isPrivileged_offset = 0;
-
--
- void java_security_AccessControlContext::compute_offsets() {
- assert(_isPrivileged_offset == 0, "offsets should be initialized only once");
- fieldDescriptor fd;
-@@ -2372,6 +2764,15 @@
- java_lang_System::compute_offsets();
- java_lang_Thread::compute_offsets();
- java_lang_ThreadGroup::compute_offsets();
-+ if (MethodHandleSupport) {
-+ java_dyn_MethodHandle::compute_offsets();
-+ impl_java_dyn_MemberName::compute_offsets();
-+ impl_java_dyn_DirectMethodHandle::compute_offsets();
-+ impl_java_dyn_BoundMethodHandle::compute_offsets();
-+ impl_java_dyn_AdapterMethodHandle::compute_offsets();
-+ java_dyn_MethodType::compute_offsets();
-+ java_dyn_MethodTypeForm::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
-@@ -2389,6 +2790,9 @@
- sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
- }
- sun_misc_AtomicLongCSImpl::compute_offsets();
-+
-+ // generated interpreter code wants to know about the offsets we just computed:
-+ AbstractAssembler::update_delayed_values();
- }
-
- #ifndef PRODUCT
-diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp
---- a/src/share/vm/classfile/javaClasses.hpp
-+++ b/src/share/vm/classfile/javaClasses.hpp
-@@ -107,6 +107,7 @@
-
- // Conversion
- static symbolHandle as_symbol(Handle java_string, TRAPS);
-+ static symbolOop as_symbol_or_null(oop java_string);
-
- // Testers
- static bool is_instance(oop obj) {
-@@ -149,6 +150,9 @@
- static oop create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
- // Conversion
- static klassOop as_klassOop(oop java_class);
-+ static BasicType as_BasicType(oop java_class, klassOop* reference_klass = NULL);
-+ static symbolOop as_signature(oop java_class, bool intern_if_not_found, TRAPS);
-+ static void print_signature(oop java_class, outputStream *st);
- // Testing
- static bool is_instance(oop obj) {
- return obj != NULL && obj->klass() == SystemDictionary::class_klass();
-@@ -668,6 +672,8 @@
- static BasicType basic_type(oop box);
- static bool is_instance(oop box) { return basic_type(box) != T_ILLEGAL; }
- static bool is_instance(oop box, BasicType type) { return basic_type(box) == type; }
-+ static void print(oop box, outputStream* st) { jvalue value; print(get_value(box, &value), &value, st); }
-+ static void print(BasicType type, jvalue* value, outputStream* st);
-
- static int value_offset_in_bytes(BasicType type) {
- return ( type == T_LONG || type == T_DOUBLE ) ? long_value_offset :
-@@ -772,6 +778,255 @@
- };
-
-
-+// Interface to java.dyn.MethodHandle objects
-+
-+class MethodEntry;
-+
-+class java_dyn_MethodHandle: AllStatic {
-+ friend class JavaClasses;
-+
-+ private:
-+ static int _vmentry_offset; // assembly code trampoline for MH
-+ static int _vmtarget_offset; // class-specific target reference
-+ static int _type_offset; // the MethodType of this MH
-+ static int _vmslots_offset; // OPTIONAL hoisted type.form.vmslots
-+
-+ static void compute_offsets();
-+
-+ public:
-+ // Accessors
-+ static oop type(oop mh);
-+ static void set_type(oop mh, oop mtype);
-+
-+ static oop vmtarget(oop mh);
-+ static void set_vmtarget(oop mh, oop target);
-+
-+ static MethodEntry* vmentry(oop mh);
-+ static void set_vmentry(oop mh, MethodEntry* data);
-+
-+ static int vmslots(oop mh);
-+ static void init_vmslots(oop mh);
-+ static int compute_vmslots(oop mh);
-+
-+ // Testers
-+ static bool is_subclass(klassOop klass) {
-+ return Klass::cast(klass)->is_subclass_of(SystemDictionary::MethodHandle_klass());
-+ }
-+ static bool is_instance(oop obj) {
-+ return obj != NULL && is_subclass(obj->klass());
-+ }
-+
-+ // Accessors for code generation:
-+ static int type_offset_in_bytes() { return _type_offset; }
-+ static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
-+ static int vmentry_offset_in_bytes() { return _vmentry_offset; }
-+ static int vmslots_offset_in_bytes() { return _vmslots_offset; }
-+};
-+
-+class impl_java_dyn_MemberName: AllStatic {
-+ friend class JavaClasses;
-+
-+ private:
-+ // From java.dyn.MemberName:
-+ // private Class<?> clazz; // class in which the method is defined
-+ // private String name; // may be null if not yet materialized
-+ // private Object type; // may be null if not yet materialized
-+ // private int flags; // modifier bits; see reflect.Modifier
-+ // private Object vmtarget; // VM-specific target value
-+ // private int vmindex; // method index within class or interface
-+ static int _clazz_offset;
-+ static int _name_offset;
-+ static int _type_offset;
-+ static int _flags_offset;
-+ static int _vmtarget_offset;
-+ static int _vmindex_offset;
-+
-+ static void compute_offsets();
-+
-+ public:
-+ // Accessors
-+ static oop clazz(oop mname);
-+ static void set_clazz(oop mname, oop clazz);
-+
-+ static oop type(oop mname);
-+ static void set_type(oop mname, oop type);
-+
-+ static oop name(oop mname);
-+ static void set_name(oop mname, oop name);
-+
-+ static int flags(oop mname);
-+ static void set_flags(oop mname, int flags);
-+
-+ static int modifiers(oop mname) { return (u2) flags(mname); }
-+ static void set_modifiers(oop mname, int mods)
-+ { set_flags(mname, (flags(mname) &~ (u2)-1) | (u2)mods); }
-+
-+ static oop vmtarget(oop mname);
-+ static void set_vmtarget(oop mname, oop target);
-+
-+ static int vmindex(oop mname);
-+ static void set_vmindex(oop mname, int index);
-+
-+ // Testers
-+ static bool is_subclass(klassOop klass) {
-+ return Klass::cast(klass)->is_subclass_of(SystemDictionary::MemberName_klass());
-+ }
-+ static bool is_instance(oop obj) {
-+ return obj != NULL && is_subclass(obj->klass());
-+ }
-+
-+ // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
-+ enum {
-+ MN_IS_METHOD = 0x00010000, // method (not constructor)
-+ MN_IS_CONSTRUCTOR = 0x00020000, // constructor
-+ MN_IS_FIELD = 0x00040000, // field
-+ MN_IS_TYPE = 0x00080000, // nested type
-+ MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
-+ MN_SEARCH_INTERFACES = 0x00200000, // for MHN.getMembers
-+ VM_INDEX_UNINITIALIZED = -99
-+ };
-+
-+ // Accessors for code generation:
-+ static int clazz_offset_in_bytes() { return _clazz_offset; }
-+ static int type_offset_in_bytes() { return _type_offset; }
-+ static int name_offset_in_bytes() { return _name_offset; }
-+ static int flags_offset_in_bytes() { return _flags_offset; }
-+ static int vmtarget_offset_in_bytes() { return _vmtarget_offset; }
-+ static int vmindex_offset_in_bytes() { return _vmindex_offset; }
-+};
-+
-+class impl_java_dyn_DirectMethodHandle: public java_dyn_MethodHandle {
-+ friend class JavaClasses;
-+
-+ private:
-+ // _vmtarget_offset; // method or class or interface
-+ static int _vmindex_offset; // negative or vtable idx or itable idx
-+ static void compute_offsets();
-+
-+ public:
-+ // Accessors
-+ static int vmindex(oop mh);
-+ static void set_vmindex(oop mh, int index);
-+
-+ // Accessors for code generation:
-+ static int vmindex_offset_in_bytes() { return _vmindex_offset; }
-+};
-+
-+class impl_java_dyn_BoundMethodHandle: public java_dyn_MethodHandle {
-+ friend class JavaClasses;
-+
-+ private:
-+ static int _argument_offset; // argument value bound into this MH
-+ static int _vmargslot_offset; // relevant argument slot (<= vmslots)
-+ static void compute_offsets();
-+
-+public:
-+ static oop argument(oop mh);
-+ static void set_argument(oop mh, oop ref);
-+
-+ static jint vmargslot(oop mh);
-+ static void set_vmargslot(oop mh, jint slot);
-+
-+ static int argument_offset_in_bytes() { return _argument_offset; }
-+ static int vmargslot_offset_in_bytes() { return _vmargslot_offset; }
-+};
-+
-+class impl_java_dyn_AdapterMethodHandle: public impl_java_dyn_BoundMethodHandle {
-+ friend class JavaClasses;
-+
-+ private:
-+ static int _conversion_offset; // type of conversion to apply
-+ static void compute_offsets();
-+
-+ public:
-+ static int conversion(oop mh);
-+ static void set_conversion(oop mh, int conv);
-+
-+ // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
-+ enum {
-+ RETYPE_ONLY = 0x000, // no argument changes; straight retype
-+ CHECK_CAST = 0x100, // ref-to-ref conversion; requires a Class argument
-+ PRIM_TO_PRIM = 0x200, // converts from one primitive to another
-+ REF_TO_PRIM = 0x300, // unboxes a wrapper to produce a primitive
-+ PRIM_TO_REF = 0x400, // boxes a primitive into a wrapper (NYI)
-+ SWAP_ARGS = 0x500, // swap arguments (vminfo is 2nd arg)
-+ ROT_ARGS = 0x600, // rotate arguments (vminfo is displaced arg)
-+ DUP_ARGS = 0x700, // duplicates one or more arguments (at TOS)
-+ DROP_ARGS = 0x800, // remove one or more argument slots
-+ COLLECT_ARGS = 0x900, // combine one or more arguments into a varargs (NYI)
-+ SPREAD_ARGS = 0xA00, // expand in place a varargs array (of known size)
-+ FLYBY = 0xB00, // operate first on reified argument list (NYI)
-+ RICOCHET = 0xC00, // run an adapter chain on the return value (NYI)
-+
-+ CONV_OP_MASK = 0xF00, // byte 3 contains the conversion op field
-+ CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
-+ CONV_VMINFO_SHIFT = 0, // position of bits in CONV_VMINFO_MASK
-+ CONV_OP_SHIFT = 8, // position of bits in CONV_OP_MASK
-+ CONV_DEST_TYPE_SHIFT = 12, // byte 3 has the adapter BasicType (if needed)
-+ CONV_SRC_TYPE_SHIFT = 16, // byte 2 has the source BasicType (if needed)
-+ CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
-+ CONV_STACK_MOVE_MASK = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1
-+ };
-+
-+ static int conversion_offset_in_bytes() { return _conversion_offset; }
-+};
-+
-+
-+// Interface to java.dyn.MethodType objects
-+
-+class java_dyn_MethodType: AllStatic {
-+ friend class JavaClasses;
-+
-+ private:
-+ static int _rtype_offset;
-+ static int _ptypes_offset;
-+ static int _form_offset;
-+
-+ static void compute_offsets();
-+
-+ public:
-+ // Accessors
-+ static oop rtype(oop mt);
-+ static objArrayOop ptypes(oop mt);
-+ static oop form(oop mt);
-+
-+ static oop ptype(oop mt, int index);
-+
-+ static symbolOop as_signature(oop mt, bool intern_if_not_found, TRAPS);
-+ static void print_signature(oop mt, outputStream* st);
-+
-+ static bool is_instance(oop obj) {
-+ return obj != NULL && obj->klass() == SystemDictionary::MethodType_klass();
-+ }
-+
-+ // Accessors for code generation:
-+ static int rtype_offset_in_bytes() { return _rtype_offset; }
-+ static int ptypes_offset_in_bytes() { return _ptypes_offset; }
-+ static int form_offset_in_bytes() { return _form_offset; }
-+};
-+
-+class java_dyn_MethodTypeForm: AllStatic {
-+ friend class JavaClasses;
-+
-+ private:
-+ static int _vmslots_offset; // number of argument slots needed
-+ static int _erasedType_offset; // erasedType = canonical MethodType
-+
-+ static void compute_offsets();
-+
-+ public:
-+ // Accessors
-+ static int vmslots(oop mtform);
-+ static oop erasedType(oop mtform);
-+
-+ // Accessors for code generation:
-+ static int vmslots_offset_in_bytes() { return _vmslots_offset; }
-+ static int erasedType_offset_in_bytes() { return _erasedType_offset; }
-+};
-+
-+
-+
-+
- // Interface to java.security.AccessControlContext objects
-
- class java_security_AccessControlContext: AllStatic {
-diff --git a/src/share/vm/classfile/loaderConstraints.hpp b/src/share/vm/classfile/loaderConstraints.hpp
---- a/src/share/vm/classfile/loaderConstraints.hpp
-+++ b/src/share/vm/classfile/loaderConstraints.hpp
-@@ -60,8 +60,10 @@
- bool add_entry(symbolHandle name, klassOop klass1, Handle loader1,
- klassOop klass2, Handle loader2);
-
-- void check_signature_loaders(symbolHandle signature, Handle loader1,
-- Handle loader2, bool is_method, TRAPS);
-+ // Note: The main entry point for this module is via SystemDictionary.
-+ // SystemDictionary::check_signature_loaders(symbolHandle signature,
-+ // Handle loader1, Handle loader2,
-+ // bool is_method, TRAPS)
-
- klassOop find_constrained_klass(symbolHandle name, Handle loader);
- klassOop find_constrained_elem_klass(symbolHandle name, symbolHandle elem_name,
-diff --git a/src/share/vm/classfile/symbolTable.cpp b/src/share/vm/classfile/symbolTable.cpp
---- a/src/share/vm/classfile/symbolTable.cpp
-+++ b/src/share/vm/classfile/symbolTable.cpp
-@@ -109,6 +109,40 @@
- return the_table()->lookup(index, name, len, hash);
- }
-
-+// Suggestion: Push unicode-based lookup all the way into the hashing
-+// and probing logic, so there is no need for convert_to_utf8 until
-+// an actual new symbolOop is created.
-+symbolOop SymbolTable::lookup_unicode(const jchar* name, int utf16_length, TRAPS) {
-+ int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
-+ char stack_buf[128];
-+ if (utf8_length < (int) sizeof(stack_buf)) {
-+ char* chars = stack_buf;
-+ UNICODE::convert_to_utf8(name, utf16_length, chars);
-+ return lookup(chars, utf8_length, THREAD);
-+ } else {
-+ ResourceMark rm(THREAD);
-+ char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);;
-+ UNICODE::convert_to_utf8(name, utf16_length, chars);
-+ return lookup(chars, utf8_length, THREAD);
-+ }
-+}
-+
-+symbolOop SymbolTable::lookup_only_unicode(const jchar* name, int utf16_length,
-+ unsigned int& hash) {
-+ int utf8_length = UNICODE::utf8_length((jchar*) name, utf16_length);
-+ char stack_buf[128];
-+ if (utf8_length < (int) sizeof(stack_buf)) {
-+ char* chars = stack_buf;
-+ UNICODE::convert_to_utf8(name, utf16_length, chars);
-+ return lookup_only(chars, utf8_length, hash);
-+ } else {
-+ ResourceMark rm;
-+ char* chars = NEW_RESOURCE_ARRAY(char, utf8_length + 1);;
-+ UNICODE::convert_to_utf8(name, utf16_length, chars);
-+ return lookup_only(chars, utf8_length, hash);
-+ }
-+}
-+
- void SymbolTable::add(constantPoolHandle cp, int names_count,
- const char** names, int* lengths, int* cp_indices,
- unsigned int* hashValues, TRAPS) {
-@@ -126,15 +160,6 @@
- }
- }
-
--// Needed for preloading classes in signatures when compiling.
--
--symbolOop SymbolTable::probe(const char* name, int len) {
-- unsigned int hashValue = hash_symbol(name, len);
-- int index = the_table()->hash_to_index(hashValue);
-- return the_table()->lookup(index, name, len, hashValue);
--}
--
--
- symbolOop SymbolTable::basic_add(int index, u1 *name, int len,
- unsigned int hashValue, TRAPS) {
- assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
-diff --git a/src/share/vm/classfile/symbolTable.hpp b/src/share/vm/classfile/symbolTable.hpp
---- a/src/share/vm/classfile/symbolTable.hpp
-+++ b/src/share/vm/classfile/symbolTable.hpp
-@@ -91,6 +91,10 @@
- // Only copy to C string to be added if lookup failed.
- static symbolOop lookup(symbolHandle sym, int begin, int end, TRAPS);
-
-+ // jchar (utf16) version of lookups
-+ static symbolOop lookup_unicode(const jchar* name, int len, TRAPS);
-+ static symbolOop lookup_only_unicode(const jchar* name, int len, unsigned int& hash);
-+
- static void add(constantPoolHandle cp, int names_count,
- const char** names, int* lengths, int* cp_indices,
- unsigned int* hashValues, TRAPS);
-@@ -112,7 +116,14 @@
- // Needed for preloading classes in signatures when compiling.
- // Returns the symbol is already present in symbol table, otherwise
- // NULL. NO ALLOCATION IS GUARANTEED!
-- static symbolOop probe(const char* name, int len);
-+ static symbolOop probe(const char* name, int len) {
-+ unsigned int ignore_hash;
-+ return lookup_only(name, len, ignore_hash);
-+ }
-+ static symbolOop probe_unicode(const jchar* name, int len) {
-+ unsigned int ignore_hash;
-+ return lookup_only_unicode(name, len, ignore_hash);
-+ }
-
- // Histogram
- static void print_histogram() PRODUCT_RETURN;
-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
-@@ -31,6 +31,7 @@
- Dictionary* SystemDictionary::_shared_dictionary = NULL;
- LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
- ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
-+SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
-
-
- int SystemDictionary::_number_of_modifications = 0;
-@@ -960,6 +961,8 @@
- instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
- class_loader,
- protection_domain,
-+ host_klass,
-+ cp_patches,
- parsed_name,
- THREAD);
-
-@@ -1685,6 +1688,10 @@
- // represent classes we're actively loading.
- placeholders_do(blk);
-
-+ // Visit extra methods
-+ if (invoke_method_table() != NULL)
-+ invoke_method_table()->oops_do(blk);
-+
- // Loader constraints. We must keep the symbolOop used in the name alive.
- constraints()->always_strong_classes_do(blk);
-
-@@ -1720,6 +1727,10 @@
- // Adjust dictionary
- dictionary()->oops_do(f);
-
-+ // Visit extra methods
-+ if (invoke_method_table() != NULL)
-+ invoke_method_table()->oops_do(f);
-+
- // Partially loaded classes
- placeholders()->oops_do(f);
-
-@@ -1792,6 +1803,8 @@
-
- void SystemDictionary::methods_do(void f(methodOop)) {
- dictionary()->methods_do(f);
-+ if (invoke_method_table() != NULL)
-+ invoke_method_table()->methods_do(f);
- }
-
- // ----------------------------------------------------------------------------
-@@ -1824,6 +1837,7 @@
- _number_of_modifications = 0;
- _loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
- _resolution_errors = new ResolutionErrorTable(_resolution_error_size);
-+ // _invoke_method_table is allocated lazily in find_method_handle_invoke()
-
- // Allocate private object used as system class loader lock
- _system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK);
-@@ -1885,6 +1899,9 @@
- wk_klass_name_limits[0] = s;
- }
- }
-+
-+ // move the starting value forward to the limit:
-+ start_id = limit_id;
- }
-
-
-@@ -1918,6 +1935,17 @@
- instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
- instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
-
-+ WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
-+ WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
-+ initialize_wk_klasses_until(meth_group_start, scan, CHECK);
-+ if (MethodHandleSupport) {
-+ 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);
-
- _box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
-@@ -1958,6 +1986,13 @@
- return T_OBJECT;
- }
-
-+KlassHandle KlassHandles::box_klass(BasicType t) {
-+ if (t >= T_BOOLEAN && t <= T_VOID)
-+ return KlassHandle(&SystemDictionary::_box_klasses[t], true);
-+ else
-+ return KlassHandle();
-+}
-+
- // Constraints on class loaders. The details of the algorithm can be
- // found in the OOPSLA'98 paper "Dynamic Class Loading in the Java
- // Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is
-@@ -2168,11 +2203,56 @@
- }
-
-
-+// Signature constraints ensure that callers and callees agree about
-+// the meaning of type names in their signatures. This routine is the
-+// intake for constraints. It collects them from several places:
-+//
-+// * LinkResolver::resolve_method (if check_access is true) requires
-+// that the resolving class (the caller) and the defining class of
-+// the resolved method (the callee) agree on each type in the
-+// method's signature.
-+//
-+// * LinkResolver::resolve_interface_method performs exactly the same
-+// checks.
-+//
-+// * LinkResolver::resolve_field requires that the constant pool
-+// attempting to link to a field agree with the field's defining
-+// class about the type of the field signature.
-+//
-+// * klassVtable::initialize_vtable requires that, when a class
-+// overrides a vtable entry allocated by a superclass, that the
-+// overriding method (i.e., the callee) agree with the superclass
-+// on each type in the method's signature.
-+//
-+// * klassItable::initialize_itable requires that, when a class fills
-+// in its itables, for each non-abstract method installed in an
-+// itable, the method (i.e., the callee) agree with the interface
-+// on each type in the method's signature.
-+//
-+// All those methods have a boolean (check_access, checkconstraints)
-+// which turns off the checks. This is used from specialized contexts
-+// such as bootstrapping, dumping, and debugging.
-+//
-+// No direct constraint is placed between the class and its
-+// supertypes. Constraints are only placed along linked relations
-+// between callers and callees. When a method overrides or implements
-+// an abstract method in a supertype (superclass or interface), the
-+// constraints are placed as if the supertype were the caller to the
-+// overriding method. (This works well, since callers to the
-+// supertype have already established agreement between themselves and
-+// the supertype.) As a result of all this, a class can disagree with
-+// its supertype about the meaning of a type name, as long as that
-+// class neither calls a relevant method of the supertype, nor is
-+// called (perhaps via an override) from the supertype.
-+//
-+//
-+// SystemDictionary::check_signature_loaders(sig, l1, l2)
-+//
- // Make sure all class components (including arrays) in the given
- // signature will be resolved to the same class in both loaders.
- // Returns the name of the type that failed a loader constraint check, or
- // NULL if no constraint failed. The returned C string needs cleaning up
--// with a ResourceMark in the caller
-+// with a ResourceMark in the caller. No exception except OOME is thrown.
- char* SystemDictionary::check_signature_loaders(symbolHandle signature,
- Handle loader1, Handle loader2,
- bool is_method, TRAPS) {
-@@ -2196,6 +2276,91 @@
- }
-
-
-+methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
-+ Handle class_loader,
-+ Handle protection_domain,
-+ TRAPS) {
-+ if (!MethodHandleSupport) return NULL;
-+ assert(class_loader.is_null() && protection_domain.is_null(),
-+ "cannot load specialized versions of MethodHandle.invoke");
-+ if (invoke_method_table() == NULL) {
-+ // create this side table lazily
-+ _invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
-+ }
-+ unsigned int hash = invoke_method_table()->compute_hash(signature);
-+ int index = invoke_method_table()->hash_to_index(hash);
-+ 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.
-+ Handle mt = compute_method_handle_type(signature(),
-+ class_loader, protection_domain,
-+ CHECK_NULL);
-+ KlassHandle mh_klass = KlassHandles::MethodHandle_klass();
-+ methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature,
-+ mt, CHECK_NULL);
-+ // Now grab the lock. We might have to throw away the new method,
-+ // if a racing thread has managed to install one at the same time.
-+ {
-+ MutexLocker ml(SystemDictionary_lock, Thread::current());
-+ spe = invoke_method_table()->find_entry(index, hash, signature);
-+ if (spe == NULL)
-+ spe = invoke_method_table()->add_entry(index, hash, signature);
-+ if (spe->property_oop() == NULL)
-+ spe->set_property_oop(m());
-+ }
-+ }
-+ methodOop m = (methodOop) spe->property_oop();
-+ assert(m->is_method(), "");
-+ return m;
-+}
-+
-+// Ask Java code to find or construct a java.dyn.MethodType for the given
-+// signature, as interpreted relative to the given class loader.
-+// Because of class loader constraints, all method handle usage must be
-+// consistent with this loader.
-+Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
-+ Handle class_loader,
-+ Handle protection_domain,
-+ TRAPS) {
-+ Handle empty;
-+ int npts = ArgumentCount(signature()).size();
-+ objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty));
-+ int arg = 0;
-+ Handle rt; // the return type from the signature
-+ for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
-+ oop mirror;
-+ if (!ss.is_object()) {
-+ mirror = Universe::java_mirror(ss.type());
-+ } else {
-+ symbolOop name_oop = ss.as_symbol(CHECK_(empty));
-+ symbolHandle name(THREAD, name_oop);
-+ klassOop klass = resolve_or_fail(name,
-+ class_loader, protection_domain,
-+ true, CHECK_(empty));
-+ mirror = Klass::cast(klass)->java_mirror();
-+ }
-+ if (ss.at_return_type())
-+ rt = Handle(THREAD, mirror);
-+ else
-+ pts->obj_at_put(arg++, mirror);
-+ }
-+ assert(arg == npts, "");
-+
-+ // call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true)
-+ bool varargs = false, trusted = true;
-+ JavaCallArguments args(Handle(THREAD, rt()));
-+ args.push_oop(pts());
-+ args.push_int(false);
-+ args.push_int(trusted);
-+ JavaValue result(T_OBJECT);
-+ JavaCalls::call_static(&result,
-+ SystemDictionary::MethodType_klass(),
-+ vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(),
-+ &args, CHECK_(empty));
-+ return Handle(THREAD, (oop) result.get_jobject());
-+}
-+
-+
- // Since the identity hash code for symbols changes when the symbols are
- // moved from the regular perm gen (hash in the mark word) to the shared
- // spaces (hash is the address), the classes loaded into the dictionary
-diff --git a/src/share/vm/classfile/systemDictionary.hpp b/src/share/vm/classfile/systemDictionary.hpp
---- a/src/share/vm/classfile/systemDictionary.hpp
-+++ b/src/share/vm/classfile/systemDictionary.hpp
-@@ -63,6 +63,7 @@
- class LoaderConstraintTable;
- class HashtableBucket;
- class ResolutionErrorTable;
-+class SymbolPropertyTable;
-
- // 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,16 @@
- 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) \
- \
-+ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
-+ template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \
-+ template(MemberName_klass, impl_java_dyn_MemberName, Opt) \
-+ template(MethodHandleImpl_klass, impl_java_dyn_MethodHandleImpl, Opt) \
-+ template(AdapterMethodHandle_klass, impl_java_dyn_AdapterMethodHandle, Opt) \
-+ template(BoundMethodHandle_klass, impl_java_dyn_BoundMethodHandle, Opt) \
-+ template(DirectMethodHandle_klass, impl_java_dyn_DirectMethodHandle, Opt) \
-+ template(MethodType_klass, java_dyn_MethodType, Opt) \
-+ template(MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \
-+ template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
- template(vector_klass, java_util_Vector, Pre) \
- template(hashtable_klass, java_util_Hashtable, Pre) \
- template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
-@@ -161,6 +172,7 @@
- class SystemDictionary : AllStatic {
- friend class VMStructs;
- friend class CompactingPermGenGen;
-+ friend class KlassHandles;
- NOT_PRODUCT(friend class instanceKlassKlass;)
-
- public:
-@@ -443,6 +455,17 @@
- static char* check_signature_loaders(symbolHandle signature, Handle loader1,
- Handle loader2, bool is_method, TRAPS);
-
-+ // JSR 292
-+ // find the java.dyn.MethodHandles::invoke method for a given signature
-+ static methodOop find_method_handle_invoke(symbolHandle signature,
-+ Handle class_loader,
-+ Handle protection_domain,
-+ TRAPS);
-+ // ask Java to compute the java.dyn.MethodType object for a given signature
-+ static Handle compute_method_handle_type(symbolHandle signature,
-+ Handle class_loader,
-+ Handle protection_domain,
-+ TRAPS);
- // Utility for printing loader "name" as part of tracing constraints
- static const char* loader_name(oop loader) {
- return ((loader) == NULL ? "<bootloader>" :
-@@ -459,6 +482,7 @@
- enum Constants {
- _loader_constraint_size = 107, // number of entries in constraint table
- _resolution_error_size = 107, // number of entries in resolution error table
-+ _invoke_method_size = 139, // number of entries in invoke method table
- _nof_buckets = 1009 // number of buckets in hash table
- };
-
-@@ -488,6 +512,9 @@
- // Resolution errors
- static ResolutionErrorTable* _resolution_errors;
-
-+ // Invoke methods (JSR 292)
-+ static SymbolPropertyTable* _invoke_method_table;
-+
- public:
- // for VM_CounterDecay iteration support
- friend class CounterDecay;
-@@ -505,6 +532,7 @@
- static PlaceholderTable* placeholders() { return _placeholders; }
- static LoaderConstraintTable* constraints() { return _loader_constraints; }
- static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
-+ static SymbolPropertyTable* invoke_method_table() { return _invoke_method_table; }
-
- // Basic loading operations
- static klassOop resolve_instance_class_or_null(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
-@@ -595,3 +623,17 @@
- static bool _has_loadClassInternal;
- static bool _has_checkPackageAccess;
- };
-+
-+class KlassHandles : AllStatic {
-+public:
-+ #define WK_KLASS_HANDLE_DECLARE(name, ignore_symbol, option) \
-+ static KlassHandle name() { \
-+ SystemDictionary::name(); \
-+ klassOop* loc = &SystemDictionary::_well_known_klasses[SystemDictionary::WK_KLASS_ENUM_NAME(name)]; \
-+ return KlassHandle(loc, true); \
-+ }
-+ WK_KLASSES_DO(WK_KLASS_HANDLE_DECLARE);
-+ #undef WK_KLASS_HANDLE_DECLARE
-+
-+ static KlassHandle box_klass(BasicType t);
-+};
-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
-@@ -214,7 +214,26 @@
- 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_MethodHandle, "java/dyn/MethodHandle") \
-+ template(java_dyn_MethodType, "java/dyn/MethodType") \
-+ template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") \
-+ template(java_dyn_MethodType_signature, "Ljava/dyn/MethodType;") \
-+ template(java_dyn_MethodHandle_signature, "Ljava/dyn/MethodHandle;") \
-+ /* internal classes known only to the JVM: */ \
-+ template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \
-+ template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \
-+ template(impl_java_dyn_MemberName, "impl/java/dyn/MemberName") \
-+ template(impl_java_dyn_MethodHandleImpl, "impl/java/dyn/MethodHandleImpl") \
-+ template(impl_java_dyn_AdapterMethodHandle, "impl/java/dyn/AdapterMethodHandle") \
-+ template(impl_java_dyn_BoundMethodHandle, "impl/java/dyn/BoundMethodHandle") \
-+ template(impl_java_dyn_DirectMethodHandle, "impl/java/dyn/DirectMethodHandle") \
-+ template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \
-+ template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \
-+ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
-+ LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
-+ \
-+ /* common method and field names */ \
- template(object_initializer_name, "<init>") \
- template(class_initializer_name, "<clinit>") \
- template(println_name, "println") \
-@@ -284,6 +303,21 @@
- template(value_name, "value") \
- template(frontCacheEnabled_name, "frontCacheEnabled") \
- template(stringCacheEnabled_name, "stringCacheEnabled") \
-+ template(toString_name, "toString") \
-+ template(values_name, "values") \
-+ template(receiver_name, "receiver") \
-+ template(vmtarget_name, "vmtarget") \
-+ template(vmentry_name, "vmentry") \
-+ template(vmslots_name, "vmslots") \
-+ template(vmindex_name, "vmindex") \
-+ template(vmargslot_name, "vmargslot") \
-+ template(flags_name, "flags") \
-+ template(argument_name, "argument") \
-+ template(conversion_name, "conversion") \
-+ template(rtype_name, "rtype") \
-+ template(ptypes_name, "ptypes") \
-+ template(form_name, "form") \
-+ template(erasedType_name, "erasedType") \
- \
- /* non-intrinsic name/signature pairs: */ \
- template(register_method_name, "register") \
-@@ -347,6 +381,7 @@
- template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
- template(void_object_signature, "()Ljava/lang/Object;") \
- template(void_class_signature, "()Ljava/lang/Class;") \
-+ template(void_string_signature, "()Ljava/lang/String;") \
- 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;") \
-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
-@@ -799,6 +799,7 @@
- if (young_gen()->is_in_reserved(addr)) {
- assert(young_gen()->is_in(addr),
- "addr should be in allocated part of young gen");
-+ if (Debugging) return NULL; // called from find() in debug.cpp
- Unimplemented();
- } else if (old_gen()->is_in_reserved(addr)) {
- assert(old_gen()->is_in(addr),
-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
-@@ -254,6 +254,7 @@
- assembler_<arch>.cpp collectedHeap.inline.hpp
- assembler_<arch>.cpp interfaceSupport.hpp
- assembler_<arch>.cpp interpreter.hpp
-+assembler_<arch>.cpp methodHandles.hpp
- assembler_<arch>.cpp objectMonitor.hpp
- assembler_<arch>.cpp os.hpp
- assembler_<arch>.cpp resourceArea.hpp
-@@ -1273,6 +1274,7 @@
- cpCacheKlass.cpp collectedHeap.hpp
- cpCacheKlass.cpp constantPoolOop.hpp
- cpCacheKlass.cpp cpCacheKlass.hpp
-+cpCacheKlass.cpp genOopClosures.inline.hpp
- cpCacheKlass.cpp handles.inline.hpp
- cpCacheKlass.cpp javaClasses.hpp
- cpCacheKlass.cpp markSweep.inline.hpp
-@@ -2200,6 +2202,7 @@
- interpreter_<arch_model>.cpp jvmtiExport.hpp
- interpreter_<arch_model>.cpp jvmtiThreadState.hpp
- interpreter_<arch_model>.cpp methodDataOop.hpp
-+interpreter_<arch_model>.cpp methodHandles.hpp
- interpreter_<arch_model>.cpp methodOop.hpp
- interpreter_<arch_model>.cpp oop.inline.hpp
- interpreter_<arch_model>.cpp sharedRuntime.hpp
-@@ -2594,6 +2597,7 @@
- linkResolver.cpp instanceKlass.hpp
- linkResolver.cpp interpreterRuntime.hpp
- linkResolver.cpp linkResolver.hpp
-+linkResolver.cpp methodHandles.hpp
- linkResolver.cpp nativeLookup.hpp
- linkResolver.cpp objArrayOop.hpp
- linkResolver.cpp reflection.hpp
-@@ -2810,6 +2814,24 @@
- methodDataOop.hpp orderAccess.hpp
- methodDataOop.hpp universe.hpp
-
-+methodHandles.hpp frame.inline.hpp
-+methodHandles.hpp globals.hpp
-+methodHandles.hpp interfaceSupport.hpp
-+methodHandles.hpp vmSymbols.hpp
-+
-+methodHandles.cpp allocation.inline.hpp
-+methodHandles.cpp interpreter.hpp
-+methodHandles.cpp javaCalls.hpp
-+methodHandles.cpp methodHandles.hpp
-+methodHandles.cpp oopFactory.hpp
-+methodHandles.cpp reflection.hpp
-+methodHandles.cpp signature.hpp
-+methodHandles.cpp symbolTable.hpp
-+
-+methodHandles_<arch>.cpp allocation.inline.hpp
-+methodHandles_<arch>.cpp interpreter.hpp
-+methodHandles_<arch>.cpp methodHandles.hpp
-+
- methodKlass.cpp collectedHeap.inline.hpp
- methodKlass.cpp constMethodKlass.hpp
- methodKlass.cpp gcLocker.hpp
-@@ -3059,6 +3081,7 @@
- oop.inline.hpp arrayOop.hpp
- oop.inline.hpp atomic.hpp
- oop.inline.hpp barrierSet.inline.hpp
-+oop.inline.hpp bytes_<arch>.hpp
- oop.inline.hpp cardTableModRefBS.hpp
- oop.inline.hpp collectedHeap.inline.hpp
- oop.inline.hpp compactingPermGenGen.hpp
-@@ -3670,6 +3693,7 @@
- sharedRuntime.cpp interpreter.hpp
- sharedRuntime.cpp javaCalls.hpp
- sharedRuntime.cpp jvmtiExport.hpp
-+sharedRuntime.cpp methodHandles.hpp
- sharedRuntime.cpp nativeInst_<arch>.hpp
- sharedRuntime.cpp nativeLookup.hpp
- sharedRuntime.cpp oop.inline.hpp
-@@ -3856,6 +3880,7 @@
- stubGenerator_<arch_model>.cpp handles.inline.hpp
- stubGenerator_<arch_model>.cpp instanceOop.hpp
- stubGenerator_<arch_model>.cpp interpreter.hpp
-+stubGenerator_<arch_model>.cpp methodHandles.hpp
- stubGenerator_<arch_model>.cpp methodOop.hpp
- stubGenerator_<arch_model>.cpp nativeInst_<arch>.hpp
- stubGenerator_<arch_model>.cpp objArrayKlass.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
-@@ -36,6 +36,12 @@
- constantPoolKlass.cpp psScavenge.inline.hpp
- constantPoolKlass.cpp parOopClosures.inline.hpp
-
-+constantPoolKlass.cpp cardTableRS.hpp
-+constantPoolKlass.cpp oop.pcgc.inline.hpp
-+constantPoolKlass.cpp psPromotionManager.inline.hpp
-+constantPoolKlass.cpp psScavenge.inline.hpp
-+constantPoolKlass.cpp parOopClosures.inline.hpp
-+
- genCollectedHeap.cpp concurrentMarkSweepThread.hpp
- genCollectedHeap.cpp vmCMSOperations.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
-@@ -61,6 +61,7 @@
- empty, // empty method (code: _return)
- accessor, // accessor method (code: _aload_0, _getfield, _(a|i)return)
- abstract, // abstract method (throws an AbstractMethodException)
-+ method_handle, // java.dyn.MethodHandles::invoke
- 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)
-@@ -91,8 +92,6 @@
-
- static address _rethrow_exception_entry; // rethrows an activation in previous frame
-
--
--
- friend class AbstractInterpreterGenerator;
- friend class InterpreterGenerator;
- friend class InterpreterMacroAssembler;
-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
-@@ -114,6 +114,7 @@
- method_entry(empty);
- method_entry(accessor);
- method_entry(abstract);
-+ method_entry(invoke_method);
- method_entry(java_lang_math_sin );
- method_entry(java_lang_math_cos );
- method_entry(java_lang_math_tan );
-diff --git a/src/share/vm/interpreter/interpreter.cpp b/src/share/vm/interpreter/interpreter.cpp
---- a/src/share/vm/interpreter/interpreter.cpp
-+++ b/src/share/vm/interpreter/interpreter.cpp
-@@ -168,10 +168,14 @@
- // Abstract method?
- if (m->is_abstract()) return abstract;
-
-+ // Invoker for method handles?
-+ if (m->is_method_handle_invoke()) return method_handle;
-+
- // Native method?
- // Note: This test must come _before_ the test for intrinsic
- // methods. See also comments below.
- if (m->is_native()) {
-+ assert(!m->is_method_handle_invoke(), "overlapping bits here, watch out");
- return m->is_synchronized() ? native_synchronized : native;
- }
-
-@@ -249,6 +253,7 @@
- case empty : tty->print("empty" ); break;
- case accessor : tty->print("accessor" ); break;
- case abstract : tty->print("abstract" ); break;
-+ case method_handle : tty->print("method_handle" ); break;
- case java_lang_math_sin : tty->print("java_lang_math_sin" ); break;
- case java_lang_math_cos : tty->print("java_lang_math_cos" ); break;
- case java_lang_math_tan : tty->print("java_lang_math_tan" ); break;
-diff --git a/src/share/vm/interpreter/interpreterRuntime.cpp b/src/share/vm/interpreter/interpreterRuntime.cpp
---- a/src/share/vm/interpreter/interpreterRuntime.cpp
-+++ b/src/share/vm/interpreter/interpreterRuntime.cpp
-@@ -293,6 +293,24 @@
- THROW_MSG(vmSymbols::java_lang_ClassCastException(), message);
- IRT_END
-
-+// required can be either a MethodType, or a Class (for a single argument)
-+// actual (if not null) can be either a MethodHandle, or an arbitrary value (for a single argument)
-+IRT_ENTRY(void, InterpreterRuntime::throw_WrongMethodTypeException(JavaThread* thread,
-+ oopDesc* required,
-+ oopDesc* actual)) {
-+ ResourceMark rm(thread);
-+ char* message = SharedRuntime::generate_wrong_method_type_message(thread, required, actual);
-+
-+ if (ProfileTraps) {
-+ note_trap(thread, Deoptimization::Reason_constraint, CHECK);
-+ }
-+
-+ // create exception
-+ THROW_MSG(vmSymbols::java_dyn_WrongMethodTypeException(), message);
-+}
-+IRT_END
-+
-+
-
- // exception_handler_for_exception(...) returns the continuation address,
- // the exception oop (via TLS) and sets the bci/bcp for the continuation.
-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
-@@ -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);
-+ static void throw_WrongMethodTypeException(JavaThread* thread, oopDesc* mtype = NULL, oopDesc* mhandle = NULL);
- 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);
-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
-@@ -151,6 +151,20 @@
- result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name(), signature()));
- }
-
-+void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
-+ if (MethodHandleSupport && MethodHandles::enabled() &&
-+ name == vmSymbolHandles::invoke_name() && klass() == SystemDictionary::MethodHandle_klass()) {
-+ methodOop result_oop = SystemDictionary::find_method_handle_invoke(signature,
-+ Handle(),
-+ Handle(),
-+ CHECK);
-+ if (result_oop != NULL) {
-+ assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature(), "consistent");
-+ result = methodHandle(THREAD, result_oop);
-+ }
-+ }
-+}
-+
- void LinkResolver::check_method_accessability(KlassHandle ref_klass,
- KlassHandle resolved_klass,
- KlassHandle sel_klass,
-@@ -240,6 +254,11 @@
- lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK);
-
- if (resolved_method.is_null()) {
-+ // JSR 292: see if this is an implicitly generated method MethodHandle.invoke(*...)
-+ lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK);
-+ }
-+
-+ if (resolved_method.is_null()) {
- // 4. method lookup failed
- ResourceMark rm(THREAD);
- THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(),
-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
-@@ -103,6 +103,7 @@
- static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
- static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
- static void lookup_method_in_interfaces (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
-+ static void lookup_implicit_method (methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS);
-
- static int vtable_index_of_miranda_method(KlassHandle klass, symbolHandle name, symbolHandle signature, 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
-@@ -168,6 +168,7 @@
- address TemplateInterpreter::_throw_ArrayStoreException_entry = NULL;
- address TemplateInterpreter::_throw_ArithmeticException_entry = NULL;
- address TemplateInterpreter::_throw_ClassCastException_entry = NULL;
-+address TemplateInterpreter::_throw_WrongMethodType_entry = NULL;
- address TemplateInterpreter::_throw_NullPointerException_entry = NULL;
- address TemplateInterpreter::_throw_StackOverflowError_entry = NULL;
- address TemplateInterpreter::_throw_exception_entry = NULL;
-@@ -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();
-+ Interpreter::_throw_WrongMethodType_entry = generate_WrongMethodType_handler();
- Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL );
- Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler();
- }
-@@ -358,6 +360,7 @@
- method_entry(empty)
- method_entry(accessor)
- method_entry(abstract)
-+ method_entry(method_handle)
- method_entry(java_lang_math_sin )
- method_entry(java_lang_math_cos )
- method_entry(java_lang_math_tan )
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,6 +77,7 @@
- friend class VMStructs;
- friend class InterpreterMacroAssembler;
- friend class TemplateInterpreterGenerator;
-+ friend class InterpreterGenerator;
- friend class TemplateTable;
- // friend class Interpreter;
- public:
-@@ -93,6 +94,7 @@
- static address _throw_ArrayStoreException_entry;
- static address _throw_ArithmeticException_entry;
- static address _throw_ClassCastException_entry;
-+ static address _throw_WrongMethodType_entry;
- static address _throw_NullPointerException_entry;
- static address _throw_exception_entry;
-
-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,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);
-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
-@@ -928,6 +928,9 @@
- // shared classes at runtime, where constraints were previously created.
- guarantee(SystemDictionary::constraints()->number_of_entries() == 0,
- "loader constraints are not saved");
-+ // Revisit and implement this if we prelink method handle call sites:
-+ guarantee(SystemDictionary::invoke_method_table()->number_of_entries() == 0,
-+ "invoke method table is not saved");
- GenCollectedHeap* gch = GenCollectedHeap::heap();
-
- // At this point, many classes have been loaded.
-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
-@@ -1813,6 +1813,8 @@
- oop class_loader2, symbolOop class_name2) {
- if (class_loader1 != class_loader2) {
- return false;
-+ } else if (class_name1 == class_name2) {
-+ return true; // skip painful bytewise comparison
- } else {
- ResourceMark rm;
-
-@@ -1859,6 +1861,55 @@
- }
- }
-
-+/* defined for now in jvm.cpp, for historical reasons *--
-+klassOop instanceKlass::compute_enclosing_class_impl(instanceKlassHandle self,
-+ symbolOop& simple_name_result, TRAPS) {
-+ ...
-+}
-+*/
-+
-+// tell if two classes have the same enclosing class (at package level)
-+bool instanceKlass::is_same_package_member_impl(instanceKlassHandle class1,
-+ klassOop class2_oop, TRAPS) {
-+ if (class2_oop == class1->as_klassOop()) return true;
-+ if (!Klass::cast(class2_oop)->oop_is_instance()) return false;
-+ instanceKlassHandle class2(THREAD, class2_oop);
-+
-+ // must be in same package before we try anything else
-+ if (!class1->is_same_class_package(class2->class_loader(), class2->name()))
-+ return false;
-+
-+ // As long as there is an outer1.getEnclosingClass,
-+ // shift the search outward.
-+ instanceKlassHandle outer1 = class1;
-+ for (;;) {
-+ // As we walk along, look for equalities between outer1 and class2.
-+ // Eventually, the walks will terminate as outer1 stops
-+ // at the top-level class around the original class.
-+ symbolOop ignore_name;
-+ klassOop next = outer1->compute_enclosing_class(ignore_name, CHECK_(false));
-+ if (next == NULL) break;
-+ if (next == class2()) return true;
-+ outer1 = instanceKlassHandle(THREAD, next);
-+ }
-+
-+ // Now do the same for class2.
-+ instanceKlassHandle outer2 = class2;
-+ for (;;) {
-+ symbolOop ignore_name;
-+ klassOop next = outer2->compute_enclosing_class(ignore_name, CHECK_(false));
-+ if (next == NULL) break;
-+ // Might as well check the new outer against all available values.
-+ if (next == class1()) return true;
-+ if (next == outer1()) return true;
-+ outer2 = instanceKlassHandle(THREAD, next);
-+ }
-+
-+ // If by this point we have not found an equality between the
-+ // two classes, we know they are in separate package members.
-+ return false;
-+}
-+
-
- jint instanceKlass::compute_modifier_flags(TRAPS) const {
- klassOop k = as_klassOop();
-@@ -1996,9 +2047,11 @@
-
- // Printing
-
-+#define BULLET " - "
-+
- void FieldPrinter::do_field(fieldDescriptor* fd) {
-- if (fd->is_static() == (_obj == NULL)) {
-- _st->print(" - ");
-+ _st->print(BULLET);
-+ if (fd->is_static() || (_obj == NULL)) {
- fd->print_on(_st);
- _st->cr();
- } else {
-@@ -2019,7 +2072,7 @@
- value->is_typeArray() &&
- offset <= (juint) value->length() &&
- offset + length <= (juint) value->length()) {
-- st->print("string: ");
-+ st->print(BULLET"string: ");
- Handle h_obj(obj);
- java_lang_String::print(h_obj, st);
- st->cr();
-@@ -2027,23 +2080,23 @@
- }
- }
-
-- st->print_cr("fields:");
-+ st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj));
- FieldPrinter print_nonstatic_field(st, obj);
- do_nonstatic_fields(&print_nonstatic_field);
-
- if (as_klassOop() == SystemDictionary::class_klass()) {
- klassOop mirrored_klass = java_lang_Class::as_klassOop(obj);
-- st->print(" - fake entry for mirror: ");
-+ st->print(BULLET"fake entry for mirror: ");
- mirrored_klass->print_value_on(st);
- st->cr();
-- st->print(" - fake entry resolved_constructor: ");
-+ st->print(BULLET"fake entry resolved_constructor: ");
- methodOop ctor = java_lang_Class::resolved_constructor(obj);
- ctor->print_value_on(st);
- klassOop array_klass = java_lang_Class::array_klass(obj);
-- st->print(" - fake entry for array: ");
-+ st->cr();
-+ st->print(BULLET"fake entry for array: ");
- array_klass->print_value_on(st);
- st->cr();
-- st->cr();
- }
- }
-
-@@ -2051,6 +2104,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
-@@ -308,6 +308,22 @@
- bool is_same_class_package(oop classloader2, symbolOop classname2);
- static bool is_same_class_package(oop class_loader1, symbolOop class_name1, oop class_loader2, symbolOop class_name2);
-
-+ // find an enclosing class (defined where original code was, in jvm.cpp!)
-+ klassOop compute_enclosing_class(symbolOop& simple_name_result, TRAPS) {
-+ instanceKlassHandle self(THREAD, this->as_klassOop());
-+ return compute_enclosing_class_impl(self, simple_name_result, THREAD);
-+ }
-+ static klassOop compute_enclosing_class_impl(instanceKlassHandle self,
-+ symbolOop& simple_name_result, TRAPS);
-+
-+ // tell if two classes have the same enclosing class (at package level)
-+ bool is_same_package_member(klassOop class2, TRAPS) {
-+ instanceKlassHandle self(THREAD, this->as_klassOop());
-+ return is_same_package_member_impl(self, class2, THREAD);
-+ }
-+ static bool is_same_package_member_impl(instanceKlassHandle self,
-+ klassOop class2, TRAPS);
-+
- // initialization state
- bool is_loaded() const { return _init_state >= loaded; }
- bool is_linked() const { return _init_state >= linked; }
-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
-@@ -487,6 +487,8 @@
-
- // Printing
-
-+#define BULLET " - "
-+
- static const char* state_names[] = {
- "unparseable_by_gc", "allocated", "loaded", "linked", "being_initialized", "fully_initialized", "initialization_error"
- };
-@@ -497,13 +499,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 +518,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 +531,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 +565,43 @@
- // 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:");
-+ 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
-@@ -1150,6 +1150,26 @@
- return index;
- }
-
-+
-+methodOop klassItable::method_for_itable_index(klassOop intf, int itable_index) {
-+ assert(instanceKlass::cast(intf)->is_interface(), "sanity check");
-+ objArrayOop methods = instanceKlass::cast(intf)->methods();
-+
-+ int index = itable_index;
-+ // Adjust for <clinit>, which is left out of table if first method
-+ if (methods->length() > 0 && ((methodOop)methods->obj_at(0))->name() == vmSymbols::class_initializer_name()) {
-+ index++;
-+ }
-+
-+ if (itable_index < 0 || index >= methods->length())
-+ return NULL; // help caller defend against bad indexes
-+
-+ methodOop m = (methodOop)methods->obj_at(index);
-+ assert(compute_itable_index(m) == itable_index, "correct inverse");
-+
-+ return m;
-+}
-+
- void klassVtable::verify(outputStream* st, bool forced) {
- // make sure table is initialized
- if (!Universe::is_fully_initialized()) return;
-diff --git a/src/share/vm/oops/klassVtable.hpp b/src/share/vm/oops/klassVtable.hpp
---- a/src/share/vm/oops/klassVtable.hpp
-+++ b/src/share/vm/oops/klassVtable.hpp
-@@ -298,6 +298,8 @@
-
- // Resolving of method to index
- static int compute_itable_index(methodOop m);
-+ // ...and back again:
-+ static methodOop method_for_itable_index(klassOop klass, int itable_index);
-
- // Debugging/Statistics
- static void print_statistics() PRODUCT_RETURN;
-diff --git a/src/share/vm/oops/methodKlass.cpp b/src/share/vm/oops/methodKlass.cpp
---- a/src/share/vm/oops/methodKlass.cpp
-+++ b/src/share/vm/oops/methodKlass.cpp
-@@ -247,9 +247,14 @@
- st->print_cr(" - size of params: %d", m->size_of_parameters());
- st->print_cr(" - method size: %d", m->method_size());
- st->print_cr(" - vtable index: %d", m->_vtable_index);
-+ st->print_cr(" - i2i entry: " INTPTR_FORMAT, m->interpreter_entry());
-+ st->print_cr(" - adapter: " INTPTR_FORMAT, m->adapter());
-+ st->print_cr(" - compiled entry " INTPTR_FORMAT, m->from_compiled_entry());
- st->print_cr(" - code size: %d", m->code_size());
-- st->print_cr(" - code start: " INTPTR_FORMAT, m->code_base());
-- st->print_cr(" - code end (excl): " INTPTR_FORMAT, m->code_base() + m->code_size());
-+ if (m->code_size() != 0) {
-+ st->print_cr(" - code start: " INTPTR_FORMAT, m->code_base());
-+ st->print_cr(" - code end (excl): " INTPTR_FORMAT, m->code_base() + m->code_size());
-+ }
- if (m->method_data() != NULL) {
- st->print_cr(" - method data: " INTPTR_FORMAT, (address)m->method_data());
- }
-@@ -293,6 +298,14 @@
- m->code()->print_value_on(st);
- st->cr();
- }
-+ if (m->is_method_handle_invoke()) {
-+ st->print_cr(" - invoke method type: " INTPTR_FORMAT, (address) m->method_handle_type());
-+ // m is classified as native, but it does not have an interesting
-+ // native_function or signature handler
-+ } else if (m->is_native()) {
-+ st->print_cr(" - native function: " INTPTR_FORMAT, m->native_function());
-+ st->print_cr(" - signature handler: " INTPTR_FORMAT, m->signature_handler());
-+ }
- }
-
-
+@@ -139,6 +139,7 @@
+ static address remove_activation_entry() { return _remove_activation_entry; }
+ static address throw_exception_entry() { return _throw_exception_entry; }
+ static address throw_ArithmeticException_entry() { return _throw_ArithmeticException_entry; }
++ static address throw_ClassCastException_entry() { return _throw_ClassCastException_entry; }
+ static address throw_WrongMethodType_entry() { return _throw_WrongMethodType_entry; }
+ static address throw_NullPointerException_entry() { return _throw_NullPointerException_entry; }
+ static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_entry; }
diff --git a/src/share/vm/oops/methodOop.cpp b/src/share/vm/oops/methodOop.cpp
--- a/src/share/vm/oops/methodOop.cpp
+++ b/src/share/vm/oops/methodOop.cpp
-@@ -564,6 +564,11 @@
-
-
- bool methodOopDesc::is_not_compilable(int comp_level) const {
-+ if (is_method_handle_invoke()) {
-+ // compilers must recognize this method specially, or not at all
-+ return true;
-+ }
-+
- methodDataOop mdo = method_data();
- if (mdo != NULL
- && (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) {
-@@ -651,7 +656,7 @@
- assert(entry != NULL, "interpreter entry must be non-null");
- // Sets both _i2i_entry and _from_interpreted_entry
- set_interpreter_entry(entry);
-- if (is_native()) {
-+ if (is_native() && !is_method_handle_invoke()) {
- set_native_function(
- SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
- !native_bind_event_is_interesting);
-@@ -783,6 +788,100 @@
- 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_limit
-+};
-+
-+oop methodOopDesc::method_handle_type() const {
-+ if (!is_method_handle_invoke()) { assert(false, "caller resp."); return NULL; }
-+ oop mt = constants()->resolved_string_at(_imcp_method_type_value);
-+ assert(mt->klass() == SystemDictionary::MethodType_klass(), "");
-+ return mt;
-+}
-+
-+jint* methodOopDesc::method_type_pointer_chase() {
-+ static jint pchase[] = { -1, -1, -1 };
-+ if (pchase[0] == -1) {
-+ jint step0 = in_bytes(constants_offset());
-+ jint step1 = (constantPoolOopDesc::header_size() + _imcp_method_type_value) * HeapWordSize;
-+ // do this in reverse to avoid races:
-+ Or