提交 344b0e97 编写于 作者: J jrose

6815692: method handle code needs some cleanup (post-6655638)

Summary: correctly raise exceptions, support safe bitwise "raw" conversions, fix bugs revealed by VerifyMethodHandles, remove dead code, improve debugging support
Reviewed-by: never, twisti
上级 00d0ced6
...@@ -271,9 +271,15 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm, ...@@ -271,9 +271,15 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
void trace_method_handle_stub(const char* adaptername, void trace_method_handle_stub(const char* adaptername,
oopDesc* mh, oopDesc* mh,
intptr_t* entry_sp, intptr_t* entry_sp,
intptr_t* saved_sp) { intptr_t* saved_sp,
intptr_t* saved_bp) {
// called as a leaf from native code: do not block the JVM! // called as a leaf from native code: do not block the JVM!
printf("MH %s "PTR_FORMAT" "PTR_FORMAT" "INTX_FORMAT"\n", adaptername, (void*)mh, entry_sp, entry_sp - saved_sp); intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
printf("MH %s mh="INTPTR_FORMAT" sp=("INTPTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="INTPTR_FORMAT"\n",
adaptername, (intptr_t)mh, (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
if (last_sp != saved_sp)
printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
} }
#endif //PRODUCT #endif //PRODUCT
...@@ -293,6 +299,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -293,6 +299,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
Register rbx_temp = rbx; Register rbx_temp = rbx;
Register rdx_temp = rdx; Register rdx_temp = rdx;
// This guy is set up by prepare_to_jump_from_interpreted (from interpreted calls)
// and gen_c2i_adapter (from compiled calls):
Register saved_last_sp = LP64_ONLY(r13) NOT_LP64(rsi);
guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets"); guarantee(java_dyn_MethodHandle::vmentry_offset_in_bytes() != 0, "must have offsets");
// some handy addresses // some handy addresses
...@@ -315,6 +325,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -315,6 +325,8 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
assert(tag_offset = wordSize, "stack grows as expected"); assert(tag_offset = wordSize, "stack grows as expected");
} }
const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes();
if (have_entry(ek)) { if (have_entry(ek)) {
__ nop(); // empty stubs make SG sick __ nop(); // empty stubs make SG sick
return; return;
...@@ -328,45 +340,65 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -328,45 +340,65 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi); __ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi);
__ lea(rax, Address(rsp, wordSize*6)); // entry_sp __ lea(rax, Address(rsp, wordSize*6)); // entry_sp
// arguments: // arguments:
__ push(rbp); // interpreter frame pointer
__ push(rsi); // saved_sp __ push(rsi); // saved_sp
__ push(rax); // entry_sp __ push(rax); // entry_sp
__ push(rcx); // mh __ push(rcx); // mh
__ push(rcx); __ push(rcx);
__ movptr(Address(rsp, 0), (intptr_t)entry_name(ek)); __ movptr(Address(rsp, 0), (intptr_t)entry_name(ek));
__ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 4); __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 5);
__ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax); __ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax);
} }
#endif //PRODUCT #endif //PRODUCT
switch ((int) ek) { switch ((int) ek) {
case _check_mtype: case _raise_exception:
{ {
// this stub is special, because it requires a live mtype argument // Not a real MH entry, but rather shared code for raising an exception.
Register rax_mtype = rax; // Extra local arguments are pushed on stack, as required type at TOS+8,
// failing object (or NULL) at TOS+4, failing bytecode type at TOS.
// emit WrongMethodType path first, to enable jccb back-branch // Beyond those local arguments are the PC, of course.
Label wrong_method_type; Register rdx_code = rdx_temp;
__ bind(wrong_method_type); Register rcx_fail = rcx_recv;
__ movptr(rdx_temp, ExternalAddress((address) &_entries[_wrong_method_type])); Register rax_want = rax_argslot;
__ jmp(Address(rdx_temp, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); Register rdi_pc = rdi;
__ hlt(); __ pop(rdx_code); // TOS+0
__ pop(rcx_fail); // TOS+4
__ pop(rax_want); // TOS+8
__ pop(rdi_pc); // caller PC
__ mov(rsp, rsi); // cut the stack back to where the caller started
// Repush the arguments as if coming from the interpreter.
if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_INT));
__ push(rdx_code);
if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT));
__ push(rcx_fail);
if (TaggedStackInterpreter) __ push(frame::tag_for_basic_type(T_OBJECT));
__ push(rax_want);
interp_entry = __ pc(); Register rbx_method = rbx_temp;
__ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type); Label no_method;
// now rax_mtype is dead; subsequent stubs will use it as a temp // FIXME: fill in _raise_exception_method with a suitable sun.dyn method
__ movptr(rbx_method, ExternalAddress((address) &_raise_exception_method));
__ jump_to_method_handle_entry(rcx_recv, rdx_temp); __ testptr(rbx_method, rbx_method);
} __ jcc(Assembler::zero, no_method);
break; int jobject_oop_offset = 0;
__ movptr(rbx_method, Address(rbx_method, jobject_oop_offset)); // dereference the jobject
case _wrong_method_type: __ testptr(rbx_method, rbx_method);
{ __ jcc(Assembler::zero, no_method);
// this stub is special, because it requires a live mtype argument __ verify_oop(rbx_method);
Register rax_mtype = rax; __ push(rdi_pc); // and restore caller PC
__ jmp(rbx_method_fie);
interp_entry = __ pc(); // If we get here, the Java runtime did not do its job of creating the exception.
__ push(rax_mtype); // required mtype // Do something that is at least causes a valid throw from the interpreter.
__ push(rcx_recv); // random mh (1st stacked argument) __ bind(no_method);
__ pop(rax_want);
if (TaggedStackInterpreter) __ pop(rcx_fail);
__ pop(rcx_fail);
__ push(rax_want);
__ push(rcx_fail);
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry())); __ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
} }
break; break;
...@@ -442,7 +474,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -442,7 +474,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ load_klass(rax_klass, rcx_recv); __ load_klass(rax_klass, rcx_recv);
__ verify_oop(rax_klass); __ verify_oop(rax_klass);
Register rcx_temp = rcx_recv; Register rdi_temp = rdi;
Register rbx_method = rbx_index; Register rbx_method = rbx_index;
// get interface klass // get interface klass
...@@ -451,7 +483,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -451,7 +483,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ lookup_interface_method(rax_klass, rdx_intf, __ lookup_interface_method(rax_klass, rdx_intf,
// note: next two args must be the same: // note: next two args must be the same:
rbx_index, rbx_method, rbx_index, rbx_method,
rcx_temp, rdi_temp,
no_such_interface); no_such_interface);
__ verify_oop(rbx_method); __ verify_oop(rbx_method);
...@@ -461,7 +493,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -461,7 +493,10 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ bind(no_such_interface); __ bind(no_such_interface);
// Throw an exception. // Throw an exception.
// For historical reasons, it will be IncompatibleClassChangeError. // For historical reasons, it will be IncompatibleClassChangeError.
__ should_not_reach_here(); // %%% FIXME NYI __ pushptr(Address(rdx_intf, java_mirror_offset)); // required interface
__ push(rcx_recv); // bad receiver
__ push((int)Bytecodes::_invokeinterface); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
} }
break; break;
...@@ -524,6 +559,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -524,6 +559,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
break; break;
case _adapter_retype_only: case _adapter_retype_only:
case _adapter_retype_raw:
// immediately jump to the next MH layer: // immediately jump to the next MH layer:
__ movptr(rcx_recv, rcx_mh_vmtarget); __ movptr(rcx_recv, rcx_mh_vmtarget);
__ verify_oop(rcx_recv); __ verify_oop(rcx_recv);
...@@ -545,10 +581,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -545,10 +581,6 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ movptr(rbx_klass, rcx_amh_argument); // this is a Class object! __ movptr(rbx_klass, rcx_amh_argument); // this is a Class object!
__ movptr(rbx_klass, Address(rbx_klass, java_lang_Class::klass_offset_in_bytes())); __ 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; Label done;
__ movptr(rdx_temp, vmarg); __ movptr(rdx_temp, vmarg);
__ testl(rdx_temp, rdx_temp); __ testl(rdx_temp, rdx_temp);
...@@ -558,17 +590,23 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -558,17 +590,23 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
// live at this point: // live at this point:
// - rbx_klass: klass required by the target method // - rbx_klass: klass required by the target method
// - rdx_temp: argument klass to test // - rdx_temp: argument klass to test
// - rcx_recv: method handle to invoke (after cast succeeds) // - rcx_recv: adapter method handle
__ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done); __ check_klass_subtype(rdx_temp, rbx_klass, rax_argslot, done);
// If we get here, the type check failed! // If we get here, the type check failed!
// Call the wrong_method_type stub, passing the failing argument type in rax. // Call the wrong_method_type stub, passing the failing argument type in rax.
Register rax_mtype = rax_argslot; Register rax_mtype = rax_argslot;
__ push(rbx_klass); // missed klass (required type) __ movl(rax_argslot, rcx_amh_vmargslot); // reload argslot field
__ push(rdx_temp); // bad actual type (1st stacked argument) __ movptr(rdx_temp, vmarg);
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
__ pushptr(rcx_amh_argument); // required class
__ push(rdx_temp); // bad object
__ push((int)Bytecodes::_checkcast); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
__ bind(done); __ bind(done);
// get the new MH:
__ movptr(rcx_recv, rcx_mh_vmtarget);
__ jump_to_method_handle_entry(rcx_recv, rdx_temp); __ jump_to_method_handle_entry(rcx_recv, rdx_temp);
} }
break; break;
...@@ -1107,11 +1145,17 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan ...@@ -1107,11 +1145,17 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
__ bind(bad_array_klass); __ bind(bad_array_klass);
UNPUSH_RSI_RDI; UNPUSH_RSI_RDI;
__ stop("bad array klass NYI"); __ pushptr(Address(rdx_array_klass, java_mirror_offset)); // required type
__ pushptr(vmarg); // bad array
__ push((int)Bytecodes::_aaload); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
__ bind(bad_array_length); __ bind(bad_array_length);
UNPUSH_RSI_RDI; UNPUSH_RSI_RDI;
__ stop("bad array length NYI"); __ push(rcx_recv); // AMH requiring a certain length
__ pushptr(vmarg); // bad array
__ push((int)Bytecodes::_arraylength); // who is complaining?
__ jump(ExternalAddress(from_interpreted_entry(_raise_exception)));
#undef UNPUSH_RSI_RDI #undef UNPUSH_RSI_RDI
} }
......
...@@ -92,8 +92,7 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() { ...@@ -92,8 +92,7 @@ address TemplateInterpreterGenerator::generate_ClassCastException_handler() {
return entry; return entry;
} }
// Arguments are: required type at TOS+8, failing object (or NULL) at TOS+4. // Arguments are: required type at TOS+4, failing object (or NULL) at TOS.
// pc at TOS (just for debugging)
address TemplateInterpreterGenerator::generate_WrongMethodType_handler() { address TemplateInterpreterGenerator::generate_WrongMethodType_handler() {
address entry = __ pc(); address entry = __ pc();
......
...@@ -903,19 +903,20 @@ class sun_dyn_AdapterMethodHandle: public sun_dyn_BoundMethodHandle { ...@@ -903,19 +903,20 @@ class sun_dyn_AdapterMethodHandle: public sun_dyn_BoundMethodHandle {
// Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants): // Relevant integer codes (keep these in synch. with MethodHandleNatives.Constants):
enum { enum {
OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype OP_RETYPE_ONLY = 0x0, // no argument changes; straight retype
OP_CHECK_CAST = 0x1, // ref-to-ref conversion; requires a Class argument OP_RETYPE_RAW = 0x1, // straight retype, trusted (void->int, Object->T)
OP_PRIM_TO_PRIM = 0x2, // converts from one primitive to another OP_CHECK_CAST = 0x2, // ref-to-ref conversion; requires a Class argument
OP_REF_TO_PRIM = 0x3, // unboxes a wrapper to produce a primitive OP_PRIM_TO_PRIM = 0x3, // converts from one primitive to another
OP_PRIM_TO_REF = 0x4, // boxes a primitive into a wrapper (NYI) OP_REF_TO_PRIM = 0x4, // unboxes a wrapper to produce a primitive
OP_SWAP_ARGS = 0x5, // swap arguments (vminfo is 2nd arg) OP_PRIM_TO_REF = 0x5, // boxes a primitive into a wrapper (NYI)
OP_ROT_ARGS = 0x6, // rotate arguments (vminfo is displaced arg) OP_SWAP_ARGS = 0x6, // swap arguments (vminfo is 2nd arg)
OP_DUP_ARGS = 0x7, // duplicates one or more arguments (at TOS) OP_ROT_ARGS = 0x7, // rotate arguments (vminfo is displaced arg)
OP_DROP_ARGS = 0x8, // remove one or more argument slots OP_DUP_ARGS = 0x8, // duplicates one or more arguments (at TOS)
OP_COLLECT_ARGS = 0x9, // combine one or more arguments into a varargs (NYI) OP_DROP_ARGS = 0x9, // remove one or more argument slots
OP_SPREAD_ARGS = 0xA, // expand in place a varargs array (of known size) OP_COLLECT_ARGS = 0xA, // combine one or more arguments into a varargs (NYI)
OP_FLYBY = 0xB, // operate first on reified argument list (NYI) OP_SPREAD_ARGS = 0xB, // expand in place a varargs array (of known size)
OP_RICOCHET = 0xC, // run an adapter chain on the return value (NYI) OP_FLYBY = 0xC, // operate first on reified argument list (NYI)
CONV_OP_LIMIT = 0xD, // limit of CONV_OP enumeration OP_RICOCHET = 0xD, // run an adapter chain on the return value (NYI)
CONV_OP_LIMIT = 0xE, // limit of CONV_OP enumeration
CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field CONV_OP_MASK = 0xF00, // this nybble contains the conversion op field
CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
......
...@@ -1963,7 +1963,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) { ...@@ -1963,7 +1963,7 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass); WKID meth_group_end = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
initialize_wk_klasses_until(meth_group_start, scan, CHECK); initialize_wk_klasses_until(meth_group_start, scan, CHECK);
if (EnableMethodHandles) { if (EnableMethodHandles) {
initialize_wk_klasses_through(meth_group_start, scan, CHECK); initialize_wk_klasses_through(meth_group_end, scan, CHECK);
} }
if (_well_known_klasses[meth_group_start] == NULL) { if (_well_known_klasses[meth_group_start] == NULL) {
// Skip the rest of the method handle classes, if MethodHandle is not loaded. // Skip the rest of the method handle classes, if MethodHandle is not loaded.
......
...@@ -1900,7 +1900,7 @@ void instanceKlass::release_C_heap_structures() { ...@@ -1900,7 +1900,7 @@ void instanceKlass::release_C_heap_structures() {
} }
} }
char* instanceKlass::signature_name() const { const char* instanceKlass::signature_name() const {
const char* src = (const char*) (name()->as_C_string()); const char* src = (const char*) (name()->as_C_string());
const int src_length = (int)strlen(src); const int src_length = (int)strlen(src);
char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3); char* dest = NEW_RESOURCE_ARRAY(char, src_length + 3);
...@@ -2259,6 +2259,10 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) { ...@@ -2259,6 +2259,10 @@ void instanceKlass::oop_print_on(oop obj, outputStream* st) {
st->print(BULLET"fake entry for array: "); st->print(BULLET"fake entry for array: ");
array_klass->print_value_on(st); array_klass->print_value_on(st);
st->cr(); st->cr();
} else if (as_klassOop() == SystemDictionary::MethodType_klass()) {
st->print(BULLET"signature: ");
java_dyn_MethodType::print_signature(obj, st);
st->cr();
} }
} }
...@@ -2284,6 +2288,9 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) { ...@@ -2284,6 +2288,9 @@ void instanceKlass::oop_print_value_on(oop obj, outputStream* st) {
const char* tname = type2name(java_lang_Class::primitive_type(obj)); const char* tname = type2name(java_lang_Class::primitive_type(obj));
st->print("%s", tname ? tname : "type?"); st->print("%s", tname ? tname : "type?");
} }
} else if (as_klassOop() == SystemDictionary::MethodType_klass()) {
st->print(" = ");
java_dyn_MethodType::print_signature(obj, st);
} else if (java_lang_boxing_object::is_instance(obj)) { } else if (java_lang_boxing_object::is_instance(obj)) {
st->print(" = "); st->print(" = ");
java_lang_boxing_object::print(obj, st); java_lang_boxing_object::print(obj, st);
......
...@@ -722,7 +722,7 @@ class instanceKlass: public Klass { ...@@ -722,7 +722,7 @@ class instanceKlass: public Klass {
#endif // SERIALGC #endif // SERIALGC
// Naming // Naming
char* signature_name() const; const char* signature_name() const;
// Iterators // Iterators
int oop_oop_iterate(oop obj, OopClosure* blk) { int oop_oop_iterate(oop obj, OopClosure* blk) {
......
...@@ -496,11 +496,13 @@ const char* Klass::external_name() const { ...@@ -496,11 +496,13 @@ const char* Klass::external_name() const {
return result; return result;
} }
} }
if (name() == NULL) return "<unknown>";
return name()->as_klass_external_name(); return name()->as_klass_external_name();
} }
char* Klass::signature_name() const { const char* Klass::signature_name() const {
if (name() == NULL) return "<unknown>";
return name()->as_C_string(); return name()->as_C_string();
} }
......
...@@ -546,7 +546,7 @@ class Klass : public Klass_vtbl { ...@@ -546,7 +546,7 @@ class Klass : public Klass_vtbl {
// For arrays, this returns the name of the element with a leading '['. // For arrays, this returns the name of the element with a leading '['.
// For classes, this returns the name with a leading 'L' and a trailing ';' // For classes, this returns the name with a leading 'L' and a trailing ';'
// and the package separators as '/'. // and the package separators as '/'.
virtual char* signature_name() const; virtual const char* signature_name() const;
// garbage collection support // garbage collection support
virtual void oop_follow_contents(oop obj) = 0; virtual void oop_follow_contents(oop obj) = 0;
......
...@@ -31,8 +31,9 @@ void markOopDesc::print_on(outputStream* st) const { ...@@ -31,8 +31,9 @@ void markOopDesc::print_on(outputStream* st) const {
st->print("locked(0x%lx)->", value()); st->print("locked(0x%lx)->", value());
markOop(*(markOop*)value())->print_on(st); markOop(*(markOop*)value())->print_on(st);
} else { } else {
assert(is_unlocked(), "just checking"); assert(is_unlocked() || has_bias_pattern(), "just checking");
st->print("mark("); st->print("mark(");
if (has_bias_pattern()) st->print("biased,");
st->print("hash %#lx,", hash()); st->print("hash %#lx,", hash());
st->print("age %d)", age()); st->print("age %d)", age());
} }
......
...@@ -881,7 +881,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, ...@@ -881,7 +881,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
assert((oop)p == method_type(), "pointer chase is correct"); assert((oop)p == method_type(), "pointer chase is correct");
#endif #endif
if (TraceMethodHandles) if (TraceMethodHandles && (Verbose || WizardMode))
m->print_on(tty); m->print_on(tty);
return m; return m;
......
...@@ -32,8 +32,7 @@ class MethodHandles: AllStatic { ...@@ -32,8 +32,7 @@ class MethodHandles: AllStatic {
// See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}. // See also javaClasses for layouts java_dyn_Method{Handle,Type,Type::Form}.
public: public:
enum EntryKind { enum EntryKind {
_check_mtype, // how a caller calls a MH _raise_exception, // stub for error generation from other stubs
_wrong_method_type, // what happens when there is a type mismatch
_invokestatic_mh, // how a MH emulates invokestatic _invokestatic_mh, // how a MH emulates invokestatic
_invokespecial_mh, // ditto for the other invokes... _invokespecial_mh, // ditto for the other invokes...
_invokevirtual_mh, _invokevirtual_mh,
...@@ -47,6 +46,7 @@ class MethodHandles: AllStatic { ...@@ -47,6 +46,7 @@ class MethodHandles: AllStatic {
_adapter_mh_first, // adapter sequence goes here... _adapter_mh_first, // adapter sequence goes here...
_adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY, _adapter_retype_only = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY,
_adapter_retype_raw = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW,
_adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST, _adapter_check_cast = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_CHECK_CAST,
_adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM, _adapter_prim_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM,
_adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM, _adapter_ref_to_prim = _adapter_mh_first + sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM,
...@@ -113,6 +113,8 @@ class MethodHandles: AllStatic { ...@@ -113,6 +113,8 @@ class MethodHandles: AllStatic {
static bool _enabled; static bool _enabled;
static MethodHandleEntry* _entries[_EK_LIMIT]; static MethodHandleEntry* _entries[_EK_LIMIT];
static const char* _entry_names[_EK_LIMIT+1]; static const char* _entry_names[_EK_LIMIT+1];
static jobject _raise_exception_method;
static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; } static bool ek_valid(EntryKind ek) { return (uint)ek < (uint)_EK_LIMIT; }
static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; } static bool conv_op_valid(int op) { return (uint)op < (uint)CONV_OP_LIMIT; }
...@@ -131,6 +133,16 @@ class MethodHandles: AllStatic { ...@@ -131,6 +133,16 @@ class MethodHandles: AllStatic {
_entries[ek] = me; _entries[ek] = me;
} }
static methodOop raise_exception_method() {
oop rem = JNIHandles::resolve(_raise_exception_method);
assert(rem == NULL || rem->is_method(), "");
return (methodOop) rem;
}
static void set_raise_exception_method(methodOop rem) {
assert(_raise_exception_method == NULL, "");
_raise_exception_method = JNIHandles::make_global(Handle(rem));
}
static jint adapter_conversion(int conv_op, BasicType src, BasicType dest, static jint adapter_conversion(int conv_op, BasicType src, BasicType dest,
int stack_move = 0, int vminfo = 0) { int stack_move = 0, int vminfo = 0) {
assert(conv_op_valid(conv_op), "oob"); assert(conv_op_valid(conv_op), "oob");
...@@ -243,7 +255,7 @@ class MethodHandles: AllStatic { ...@@ -243,7 +255,7 @@ class MethodHandles: AllStatic {
enum { enum {
// format of query to getConstant: // format of query to getConstant:
GC_JVM_PUSH_LIMIT = 0, GC_JVM_PUSH_LIMIT = 0,
GC_JVM_STACK_MOVE_LIMIT = 1, GC_JVM_STACK_MOVE_UNIT = 1,
// format of result from getTarget / encode_target: // format of result from getTarget / encode_target:
ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
...@@ -261,7 +273,8 @@ class MethodHandles: AllStatic { ...@@ -261,7 +273,8 @@ class MethodHandles: AllStatic {
int insert_argnum, oop insert_type, int insert_argnum, oop insert_type,
int change_argnum, oop change_type, int change_argnum, oop change_type,
int delete_argnum, int delete_argnum,
oop dst_mtype, int dst_beg, int dst_end); oop dst_mtype, int dst_beg, int dst_end,
bool raw = false);
static const char* check_method_type_insertion(oop src_mtype, static const char* check_method_type_insertion(oop src_mtype,
int insert_argnum, oop insert_type, int insert_argnum, oop insert_type,
oop dst_mtype) { oop dst_mtype) {
...@@ -278,29 +291,29 @@ class MethodHandles: AllStatic { ...@@ -278,29 +291,29 @@ class MethodHandles: AllStatic {
change_argnum, change_type, change_argnum, change_type,
-1, dst_mtype, 0, -1); -1, dst_mtype, 0, -1);
} }
static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype) { static const char* check_method_type_passthrough(oop src_mtype, oop dst_mtype, bool raw) {
oop no_ref = NULL; oop no_ref = NULL;
return check_method_type_change(src_mtype, 0, -1, return check_method_type_change(src_mtype, 0, -1,
-1, no_ref, -1, no_ref, -1, -1, no_ref, -1, no_ref, -1,
dst_mtype, 0, -1); dst_mtype, 0, -1, raw);
} }
// These checkers operate on pairs of argument or return types: // These checkers operate on pairs of argument or return types:
static const char* check_argument_type_change(BasicType src_type, klassOop src_klass, static const char* check_argument_type_change(BasicType src_type, klassOop src_klass,
BasicType dst_type, klassOop dst_klass, BasicType dst_type, klassOop dst_klass,
int argnum); int argnum, bool raw = false);
static const char* check_argument_type_change(oop src_type, oop dst_type, static const char* check_argument_type_change(oop src_type, oop dst_type,
int argnum) { int argnum, bool raw = false) {
klassOop src_klass = NULL, dst_klass = NULL; klassOop src_klass = NULL, dst_klass = NULL;
BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass); BasicType src_bt = java_lang_Class::as_BasicType(src_type, &src_klass);
BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass); BasicType dst_bt = java_lang_Class::as_BasicType(dst_type, &dst_klass);
return check_argument_type_change(src_bt, src_klass, return check_argument_type_change(src_bt, src_klass,
dst_bt, dst_klass, argnum); dst_bt, dst_klass, argnum, raw);
} }
static const char* check_return_type_change(oop src_type, oop dst_type) { static const char* check_return_type_change(oop src_type, oop dst_type, bool raw = false) {
return check_argument_type_change(src_type, dst_type, -1); return check_argument_type_change(src_type, dst_type, -1, raw);
} }
static const char* check_return_type_change(BasicType src_type, klassOop src_klass, static const char* check_return_type_change(BasicType src_type, klassOop src_klass,
...@@ -357,9 +370,10 @@ class MethodHandles: AllStatic { ...@@ -357,9 +370,10 @@ class MethodHandles: AllStatic {
TRAPS); TRAPS);
static bool same_basic_type_for_arguments(BasicType src, BasicType dst, static bool same_basic_type_for_arguments(BasicType src, BasicType dst,
bool raw = false,
bool for_return = false); bool for_return = false);
static bool same_basic_type_for_returns(BasicType src, BasicType dst) { static bool same_basic_type_for_returns(BasicType src, BasicType dst, bool raw = false) {
return same_basic_type_for_arguments(src, dst, true); return same_basic_type_for_arguments(src, dst, raw, true);
} }
enum { // arg_mask values enum { // arg_mask values
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册