6939224: MethodHandle.invokeGeneric needs to perform the correct set of conversions
Reviewed-by: never
This commit is contained in:
parent
7be7d19ba5
commit
52e3d262a1
@ -43,7 +43,7 @@ enum /* platform_dependent_constants */ {
|
|||||||
|
|
||||||
// MethodHandles adapters
|
// MethodHandles adapters
|
||||||
enum method_handles_platform_dependent_constants {
|
enum method_handles_platform_dependent_constants {
|
||||||
method_handles_adapters_code_size = 6000
|
method_handles_adapters_code_size = 12000
|
||||||
};
|
};
|
||||||
|
|
||||||
class Sparc {
|
class Sparc {
|
||||||
|
@ -4993,19 +4993,22 @@ void MacroAssembler::debug32(int rdi, int rsi, int rbp, int rsp, int rbx, int rd
|
|||||||
ttyLocker ttyl;
|
ttyLocker ttyl;
|
||||||
tty->print_cr("eip = 0x%08x", eip);
|
tty->print_cr("eip = 0x%08x", eip);
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
tty->cr();
|
if ((WizardMode || Verbose) && PrintMiscellaneous) {
|
||||||
findpc(eip);
|
tty->cr();
|
||||||
tty->cr();
|
findpc(eip);
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
tty->print_cr("rax, = 0x%08x", rax);
|
tty->print_cr("rax = 0x%08x", rax);
|
||||||
tty->print_cr("rbx, = 0x%08x", rbx);
|
tty->print_cr("rbx = 0x%08x", rbx);
|
||||||
tty->print_cr("rcx = 0x%08x", rcx);
|
tty->print_cr("rcx = 0x%08x", rcx);
|
||||||
tty->print_cr("rdx = 0x%08x", rdx);
|
tty->print_cr("rdx = 0x%08x", rdx);
|
||||||
tty->print_cr("rdi = 0x%08x", rdi);
|
tty->print_cr("rdi = 0x%08x", rdi);
|
||||||
tty->print_cr("rsi = 0x%08x", rsi);
|
tty->print_cr("rsi = 0x%08x", rsi);
|
||||||
tty->print_cr("rbp, = 0x%08x", rbp);
|
tty->print_cr("rbp = 0x%08x", rbp);
|
||||||
tty->print_cr("rsp = 0x%08x", rsp);
|
tty->print_cr("rsp = 0x%08x", rsp);
|
||||||
BREAKPOINT;
|
BREAKPOINT;
|
||||||
|
assert(false, "start up GDB");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ttyLocker ttyl;
|
ttyLocker ttyl;
|
||||||
@ -7677,11 +7680,19 @@ RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_ad
|
|||||||
movptr(tmp, ExternalAddress((address) delayed_value_addr));
|
movptr(tmp, ExternalAddress((address) delayed_value_addr));
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
Label L;
|
{ Label L;
|
||||||
testptr(tmp, tmp);
|
testptr(tmp, tmp);
|
||||||
jccb(Assembler::notZero, L);
|
if (WizardMode) {
|
||||||
hlt();
|
jcc(Assembler::notZero, L);
|
||||||
bind(L);
|
char* buf = new char[40];
|
||||||
|
sprintf(buf, "DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]);
|
||||||
|
stop(buf);
|
||||||
|
} else {
|
||||||
|
jccb(Assembler::notZero, L);
|
||||||
|
hlt();
|
||||||
|
}
|
||||||
|
bind(L);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
|
@ -27,6 +27,14 @@
|
|||||||
|
|
||||||
#define __ _masm->
|
#define __ _masm->
|
||||||
|
|
||||||
|
#ifdef PRODUCT
|
||||||
|
#define BLOCK_COMMENT(str) /* nothing */
|
||||||
|
#else
|
||||||
|
#define BLOCK_COMMENT(str) __ block_comment(str)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
|
||||||
|
|
||||||
address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm,
|
address MethodHandleEntry::start_compiled_entry(MacroAssembler* _masm,
|
||||||
address interpreted_entry) {
|
address interpreted_entry) {
|
||||||
// Just before the actual machine code entry point, allocate space
|
// Just before the actual machine code entry point, allocate space
|
||||||
@ -64,6 +72,7 @@ static void verify_argslot(MacroAssembler* _masm, Register argslot_reg,
|
|||||||
const char* error_message) {
|
const char* error_message) {
|
||||||
// Verify that argslot lies within (rsp, rbp].
|
// Verify that argslot lies within (rsp, rbp].
|
||||||
Label L_ok, L_bad;
|
Label L_ok, L_bad;
|
||||||
|
BLOCK_COMMENT("{ verify_argslot");
|
||||||
__ cmpptr(argslot_reg, rbp);
|
__ cmpptr(argslot_reg, rbp);
|
||||||
__ jccb(Assembler::above, L_bad);
|
__ jccb(Assembler::above, L_bad);
|
||||||
__ cmpptr(rsp, argslot_reg);
|
__ cmpptr(rsp, argslot_reg);
|
||||||
@ -71,6 +80,7 @@ static void verify_argslot(MacroAssembler* _masm, Register argslot_reg,
|
|||||||
__ bind(L_bad);
|
__ bind(L_bad);
|
||||||
__ stop(error_message);
|
__ stop(error_message);
|
||||||
__ bind(L_ok);
|
__ bind(L_ok);
|
||||||
|
BLOCK_COMMENT("} verify_argslot");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -80,16 +90,21 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
|
|||||||
// rbx: methodOop
|
// rbx: methodOop
|
||||||
// rcx: receiver method handle (must load from sp[MethodTypeForm.vmslots])
|
// rcx: receiver method handle (must load from sp[MethodTypeForm.vmslots])
|
||||||
// rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
|
// rsi/r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
|
||||||
// rdx: garbage temp, blown away
|
// rdx, rdi: garbage temp, blown away
|
||||||
|
|
||||||
Register rbx_method = rbx;
|
Register rbx_method = rbx;
|
||||||
Register rcx_recv = rcx;
|
Register rcx_recv = rcx;
|
||||||
Register rax_mtype = rax;
|
Register rax_mtype = rax;
|
||||||
Register rdx_temp = rdx;
|
Register rdx_temp = rdx;
|
||||||
|
Register rdi_temp = rdi;
|
||||||
|
|
||||||
// emit WrongMethodType path first, to enable jccb back-branch from main path
|
// emit WrongMethodType path first, to enable jccb back-branch from main path
|
||||||
Label wrong_method_type;
|
Label wrong_method_type;
|
||||||
__ bind(wrong_method_type);
|
__ bind(wrong_method_type);
|
||||||
|
Label invoke_generic_slow_path;
|
||||||
|
assert(methodOopDesc::intrinsic_id_size_in_bytes() == sizeof(u1), "");;
|
||||||
|
__ cmpb(Address(rbx_method, methodOopDesc::intrinsic_id_offset_in_bytes()), (int) vmIntrinsics::_invokeExact);
|
||||||
|
__ jcc(Assembler::notEqual, invoke_generic_slow_path);
|
||||||
__ push(rax_mtype); // required mtype
|
__ push(rax_mtype); // required mtype
|
||||||
__ push(rcx_recv); // bad mh (1st stacked argument)
|
__ push(rcx_recv); // bad mh (1st stacked argument)
|
||||||
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
|
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
|
||||||
@ -106,17 +121,68 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
|
|||||||
tem = rax_mtype; // in case there is another indirection
|
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
|
// given the MethodType, find out where the MH argument is buried
|
||||||
__ movptr(rdx_temp, Address(rax_mtype,
|
__ movptr(rdx_temp, Address(rax_mtype,
|
||||||
__ delayed_value(java_dyn_MethodType::form_offset_in_bytes, rbx_temp)));
|
__ delayed_value(java_dyn_MethodType::form_offset_in_bytes, rdi_temp)));
|
||||||
__ movl(rdx_temp, Address(rdx_temp,
|
Register rdx_vmslots = rdx_temp;
|
||||||
__ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, rbx_temp)));
|
__ movl(rdx_vmslots, Address(rdx_temp,
|
||||||
__ movptr(rcx_recv, __ argument_address(rdx_temp));
|
__ delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, rdi_temp)));
|
||||||
|
__ movptr(rcx_recv, __ argument_address(rdx_vmslots));
|
||||||
|
|
||||||
__ check_method_handle_type(rax_mtype, rcx_recv, rdx_temp, wrong_method_type);
|
trace_method_handle(_masm, "invokeExact");
|
||||||
__ jump_to_method_handle_entry(rcx_recv, rdx_temp);
|
|
||||||
|
__ check_method_handle_type(rax_mtype, rcx_recv, rdi_temp, wrong_method_type);
|
||||||
|
__ jump_to_method_handle_entry(rcx_recv, rdi_temp);
|
||||||
|
|
||||||
|
// for invokeGeneric (only), apply argument and result conversions on the fly
|
||||||
|
__ bind(invoke_generic_slow_path);
|
||||||
|
#ifdef ASSERT
|
||||||
|
{ Label L;
|
||||||
|
__ cmpb(Address(rbx_method, methodOopDesc::intrinsic_id_offset_in_bytes()), (int) vmIntrinsics::_invokeGeneric);
|
||||||
|
__ jcc(Assembler::equal, L);
|
||||||
|
__ stop("bad methodOop::intrinsic_id");
|
||||||
|
__ bind(L);
|
||||||
|
}
|
||||||
|
#endif //ASSERT
|
||||||
|
Register rbx_temp = rbx_method; // don't need it now
|
||||||
|
|
||||||
|
// make room on the stack for another pointer:
|
||||||
|
Register rcx_argslot = rcx_recv;
|
||||||
|
__ lea(rcx_argslot, __ argument_address(rdx_vmslots, 1));
|
||||||
|
insert_arg_slots(_masm, 2 * stack_move_unit(), _INSERT_REF_MASK,
|
||||||
|
rcx_argslot, rbx_temp, rdx_temp);
|
||||||
|
|
||||||
|
// load up an adapter from the calling type (Java weaves this)
|
||||||
|
__ movptr(rdx_temp, Address(rax_mtype,
|
||||||
|
__ delayed_value(java_dyn_MethodType::form_offset_in_bytes, rdi_temp)));
|
||||||
|
Register rdx_adapter = rdx_temp;
|
||||||
|
// movptr(rdx_adapter, Address(rdx_temp, java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes()));
|
||||||
|
// deal with old JDK versions:
|
||||||
|
__ lea(rdi_temp, Address(rdx_temp,
|
||||||
|
__ delayed_value(java_dyn_MethodTypeForm::genericInvoker_offset_in_bytes, rdi_temp)));
|
||||||
|
__ cmpptr(rdi_temp, rdx_temp);
|
||||||
|
Label sorry_no_invoke_generic;
|
||||||
|
__ jccb(Assembler::below, sorry_no_invoke_generic);
|
||||||
|
|
||||||
|
__ movptr(rdx_adapter, Address(rdi_temp, 0));
|
||||||
|
__ testptr(rdx_adapter, rdx_adapter);
|
||||||
|
__ jccb(Assembler::zero, sorry_no_invoke_generic);
|
||||||
|
__ movptr(Address(rcx_argslot, 1 * Interpreter::stackElementSize), rdx_adapter);
|
||||||
|
// As a trusted first argument, pass the type being called, so the adapter knows
|
||||||
|
// the actual types of the arguments and return values.
|
||||||
|
// (Generic invokers are shared among form-families of method-type.)
|
||||||
|
__ movptr(Address(rcx_argslot, 0 * Interpreter::stackElementSize), rax_mtype);
|
||||||
|
// FIXME: assert that rdx_adapter is of the right method-type.
|
||||||
|
__ mov(rcx, rdx_adapter);
|
||||||
|
trace_method_handle(_masm, "invokeGeneric");
|
||||||
|
__ jump_to_method_handle_entry(rcx, rdi_temp);
|
||||||
|
|
||||||
|
__ bind(sorry_no_invoke_generic); // no invokeGeneric implementation available!
|
||||||
|
__ movptr(rcx_recv, Address(rcx_argslot, -1 * Interpreter::stackElementSize)); // recover original MH
|
||||||
|
__ push(rax_mtype); // required mtype
|
||||||
|
__ push(rcx_recv); // bad mh (1st stacked argument)
|
||||||
|
__ jump(ExternalAddress(Interpreter::throw_WrongMethodType_entry()));
|
||||||
|
|
||||||
return entry_point;
|
return entry_point;
|
||||||
}
|
}
|
||||||
@ -164,11 +230,12 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
|
|||||||
// for (rdx = rsp + size; rdx < argslot; rdx++)
|
// for (rdx = rsp + size; rdx < argslot; rdx++)
|
||||||
// rdx[-size] = rdx[0]
|
// rdx[-size] = rdx[0]
|
||||||
// argslot -= size;
|
// argslot -= size;
|
||||||
|
BLOCK_COMMENT("insert_arg_slots {");
|
||||||
__ mov(rdx_temp, rsp); // source pointer for copy
|
__ mov(rdx_temp, rsp); // source pointer for copy
|
||||||
__ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
|
__ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
|
||||||
{
|
{
|
||||||
Label loop;
|
Label loop;
|
||||||
__ bind(loop);
|
__ BIND(loop);
|
||||||
// pull one word down each time through the loop
|
// pull one word down each time through the loop
|
||||||
__ movptr(rbx_temp, Address(rdx_temp, 0));
|
__ movptr(rbx_temp, Address(rdx_temp, 0));
|
||||||
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
||||||
@ -179,6 +246,7 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
|
|||||||
|
|
||||||
// Now move the argslot down, to point to the opened-up space.
|
// Now move the argslot down, to point to the opened-up space.
|
||||||
__ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
|
__ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
|
||||||
|
BLOCK_COMMENT("} insert_arg_slots");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper to remove argument slots from the stack.
|
// Helper to remove argument slots from the stack.
|
||||||
@ -218,6 +286,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
BLOCK_COMMENT("remove_arg_slots {");
|
||||||
// Pull up everything shallower than rax_argslot.
|
// Pull up everything shallower than rax_argslot.
|
||||||
// Then remove the excess space on the stack.
|
// Then remove the excess space on the stack.
|
||||||
// The stacked return address gets pulled up with everything else.
|
// The stacked return address gets pulled up with everything else.
|
||||||
@ -229,7 +298,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
|||||||
__ lea(rdx_temp, Address(rax_argslot, -wordSize)); // source pointer for copy
|
__ lea(rdx_temp, Address(rax_argslot, -wordSize)); // source pointer for copy
|
||||||
{
|
{
|
||||||
Label loop;
|
Label loop;
|
||||||
__ bind(loop);
|
__ BIND(loop);
|
||||||
// pull one word up each time through the loop
|
// pull one word up each time through the loop
|
||||||
__ movptr(rbx_temp, Address(rdx_temp, 0));
|
__ movptr(rbx_temp, Address(rdx_temp, 0));
|
||||||
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
__ movptr(Address(rdx_temp, arg_slots, Address::times_ptr), rbx_temp);
|
||||||
@ -242,12 +311,14 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
|
|||||||
__ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
|
__ lea(rsp, Address(rsp, arg_slots, Address::times_ptr));
|
||||||
// And adjust the argslot address to point at the deletion point.
|
// And adjust the argslot address to point at the deletion point.
|
||||||
__ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
|
__ lea(rax_argslot, Address(rax_argslot, arg_slots, Address::times_ptr));
|
||||||
|
BLOCK_COMMENT("} remove_arg_slots");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
extern "C" void print_method_handle(oop mh);
|
extern "C" void print_method_handle(oop mh);
|
||||||
void trace_method_handle_stub(const char* adaptername,
|
void trace_method_handle_stub(const char* adaptername,
|
||||||
oop mh,
|
oop mh,
|
||||||
|
intptr_t* saved_regs,
|
||||||
intptr_t* entry_sp,
|
intptr_t* entry_sp,
|
||||||
intptr_t* saved_sp,
|
intptr_t* saved_sp,
|
||||||
intptr_t* saved_bp) {
|
intptr_t* saved_bp) {
|
||||||
@ -256,9 +327,47 @@ void trace_method_handle_stub(const char* adaptername,
|
|||||||
intptr_t* base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_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",
|
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);
|
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)
|
if (last_sp != saved_sp && last_sp != NULL)
|
||||||
printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
|
printf("*** last_sp="INTPTR_FORMAT"\n", (intptr_t)last_sp);
|
||||||
if (Verbose) print_method_handle(mh);
|
if (Verbose) {
|
||||||
|
printf(" reg dump: ");
|
||||||
|
int saved_regs_count = (entry_sp-1) - saved_regs;
|
||||||
|
// 32 bit: rdi rsi rbp rsp; rbx rdx rcx (*) rax
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= saved_regs_count; i++) {
|
||||||
|
if (i > 0 && i % 4 == 0 && i != saved_regs_count)
|
||||||
|
printf("\n + dump: ");
|
||||||
|
printf(" %d: "INTPTR_FORMAT, i, saved_regs[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
int stack_dump_count = 16;
|
||||||
|
if (stack_dump_count < (int)(saved_bp + 2 - saved_sp))
|
||||||
|
stack_dump_count = (int)(saved_bp + 2 - saved_sp);
|
||||||
|
if (stack_dump_count > 64) stack_dump_count = 48;
|
||||||
|
for (i = 0; i < stack_dump_count; i += 4) {
|
||||||
|
printf(" dump at SP[%d] "INTPTR_FORMAT": "INTPTR_FORMAT" "INTPTR_FORMAT" "INTPTR_FORMAT" "INTPTR_FORMAT"\n",
|
||||||
|
i, &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]);
|
||||||
|
}
|
||||||
|
print_method_handle(mh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
|
||||||
|
if (!TraceMethodHandles) return;
|
||||||
|
BLOCK_COMMENT("trace_method_handle {");
|
||||||
|
__ push(rax);
|
||||||
|
__ lea(rax, Address(rsp, wordSize*6)); // entry_sp
|
||||||
|
__ pusha();
|
||||||
|
// arguments:
|
||||||
|
__ push(rbp); // interpreter frame pointer
|
||||||
|
__ push(rsi); // saved_sp
|
||||||
|
__ push(rax); // entry_sp
|
||||||
|
__ push(rcx); // mh
|
||||||
|
__ push(rcx);
|
||||||
|
__ movptr(Address(rsp, 0), (intptr_t) adaptername);
|
||||||
|
__ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub), 5);
|
||||||
|
__ popa();
|
||||||
|
__ pop(rax);
|
||||||
|
BLOCK_COMMENT("} trace_method_handle");
|
||||||
}
|
}
|
||||||
#endif //PRODUCT
|
#endif //PRODUCT
|
||||||
|
|
||||||
@ -324,21 +433,9 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
|||||||
address interp_entry = __ pc();
|
address interp_entry = __ pc();
|
||||||
if (UseCompressedOops) __ unimplemented("UseCompressedOops");
|
if (UseCompressedOops) __ unimplemented("UseCompressedOops");
|
||||||
|
|
||||||
#ifndef PRODUCT
|
trace_method_handle(_masm, entry_name(ek));
|
||||||
if (TraceMethodHandles) {
|
|
||||||
__ push(rax); __ push(rbx); __ push(rcx); __ push(rdx); __ push(rsi); __ push(rdi);
|
BLOCK_COMMENT(entry_name(ek));
|
||||||
__ lea(rax, Address(rsp, wordSize*6)); // entry_sp
|
|
||||||
// arguments:
|
|
||||||
__ push(rbp); // interpreter frame pointer
|
|
||||||
__ 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), 5);
|
|
||||||
__ pop(rdi); __ pop(rsi); __ pop(rdx); __ pop(rcx); __ pop(rbx); __ pop(rax);
|
|
||||||
}
|
|
||||||
#endif //PRODUCT
|
|
||||||
|
|
||||||
switch ((int) ek) {
|
switch ((int) ek) {
|
||||||
case _raise_exception:
|
case _raise_exception:
|
||||||
|
@ -33,7 +33,7 @@ enum platform_dependent_constants {
|
|||||||
|
|
||||||
// MethodHandles adapters
|
// MethodHandles adapters
|
||||||
enum method_handles_platform_dependent_constants {
|
enum method_handles_platform_dependent_constants {
|
||||||
method_handles_adapters_code_size = 5000
|
method_handles_adapters_code_size = 10000
|
||||||
};
|
};
|
||||||
|
|
||||||
class x86 {
|
class x86 {
|
||||||
|
@ -35,7 +35,7 @@ enum platform_dependent_constants {
|
|||||||
|
|
||||||
// MethodHandles adapters
|
// MethodHandles adapters
|
||||||
enum method_handles_platform_dependent_constants {
|
enum method_handles_platform_dependent_constants {
|
||||||
method_handles_adapters_code_size = 13000
|
method_handles_adapters_code_size = 26000
|
||||||
};
|
};
|
||||||
|
|
||||||
class x86 {
|
class x86 {
|
||||||
|
@ -2424,12 +2424,15 @@ int java_dyn_MethodType::ptype_count(oop mt) {
|
|||||||
|
|
||||||
int java_dyn_MethodTypeForm::_vmslots_offset;
|
int java_dyn_MethodTypeForm::_vmslots_offset;
|
||||||
int java_dyn_MethodTypeForm::_erasedType_offset;
|
int java_dyn_MethodTypeForm::_erasedType_offset;
|
||||||
|
int java_dyn_MethodTypeForm::_genericInvoker_offset;
|
||||||
|
|
||||||
void java_dyn_MethodTypeForm::compute_offsets() {
|
void java_dyn_MethodTypeForm::compute_offsets() {
|
||||||
klassOop k = SystemDictionary::MethodTypeForm_klass();
|
klassOop k = SystemDictionary::MethodTypeForm_klass();
|
||||||
if (k != NULL) {
|
if (k != NULL) {
|
||||||
compute_optional_offset(_vmslots_offset, k, vmSymbols::vmslots_name(), vmSymbols::int_signature(), true);
|
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);
|
compute_optional_offset(_erasedType_offset, k, vmSymbols::erasedType_name(), vmSymbols::java_dyn_MethodType_signature(), true);
|
||||||
|
compute_optional_offset(_genericInvoker_offset, k, vmSymbols::genericInvoker_name(), vmSymbols::java_dyn_MethodHandle_signature(), true);
|
||||||
|
if (_genericInvoker_offset == 0) _genericInvoker_offset = -1; // set to explicit "empty" value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2443,6 +2446,11 @@ oop java_dyn_MethodTypeForm::erasedType(oop mtform) {
|
|||||||
return mtform->obj_field(_erasedType_offset);
|
return mtform->obj_field(_erasedType_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oop java_dyn_MethodTypeForm::genericInvoker(oop mtform) {
|
||||||
|
assert(mtform->klass() == SystemDictionary::MethodTypeForm_klass(), "MTForm only");
|
||||||
|
return mtform->obj_field(_genericInvoker_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Support for java_dyn_CallSite
|
// Support for java_dyn_CallSite
|
||||||
|
|
||||||
|
@ -1048,6 +1048,7 @@ class java_dyn_MethodTypeForm: AllStatic {
|
|||||||
private:
|
private:
|
||||||
static int _vmslots_offset; // number of argument slots needed
|
static int _vmslots_offset; // number of argument slots needed
|
||||||
static int _erasedType_offset; // erasedType = canonical MethodType
|
static int _erasedType_offset; // erasedType = canonical MethodType
|
||||||
|
static int _genericInvoker_offset; // genericInvoker = adapter for invokeGeneric
|
||||||
|
|
||||||
static void compute_offsets();
|
static void compute_offsets();
|
||||||
|
|
||||||
@ -1055,10 +1056,12 @@ class java_dyn_MethodTypeForm: AllStatic {
|
|||||||
// Accessors
|
// Accessors
|
||||||
static int vmslots(oop mtform);
|
static int vmslots(oop mtform);
|
||||||
static oop erasedType(oop mtform);
|
static oop erasedType(oop mtform);
|
||||||
|
static oop genericInvoker(oop mtform);
|
||||||
|
|
||||||
// Accessors for code generation:
|
// Accessors for code generation:
|
||||||
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
|
static int vmslots_offset_in_bytes() { return _vmslots_offset; }
|
||||||
static int erasedType_offset_in_bytes() { return _erasedType_offset; }
|
static int erasedType_offset_in_bytes() { return _erasedType_offset; }
|
||||||
|
static int genericInvoker_offset_in_bytes() { return _genericInvoker_offset; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2361,8 +2361,11 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name,
|
|||||||
// Must create lots of stuff here, but outside of the SystemDictionary lock.
|
// Must create lots of stuff here, but outside of the SystemDictionary lock.
|
||||||
if (THREAD->is_Compiler_thread())
|
if (THREAD->is_Compiler_thread())
|
||||||
return NULL; // do not attempt from within compiler
|
return NULL; // do not attempt from within compiler
|
||||||
|
bool for_invokeGeneric = (name_id == vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name));
|
||||||
bool found_on_bcp = false;
|
bool found_on_bcp = false;
|
||||||
Handle mt = find_method_handle_type(signature(), accessing_klass, found_on_bcp, CHECK_NULL);
|
Handle mt = find_method_handle_type(signature(), accessing_klass,
|
||||||
|
for_invokeGeneric,
|
||||||
|
found_on_bcp, CHECK_NULL);
|
||||||
KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass();
|
KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass();
|
||||||
methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature,
|
methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature,
|
||||||
mt, CHECK_NULL);
|
mt, CHECK_NULL);
|
||||||
@ -2393,6 +2396,7 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name,
|
|||||||
// consistent with this loader.
|
// consistent with this loader.
|
||||||
Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
|
Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
|
||||||
KlassHandle accessing_klass,
|
KlassHandle accessing_klass,
|
||||||
|
bool for_invokeGeneric,
|
||||||
bool& return_bcp_flag,
|
bool& return_bcp_flag,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
Handle class_loader, protection_domain;
|
Handle class_loader, protection_domain;
|
||||||
@ -2448,10 +2452,26 @@ Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
|
|||||||
vmSymbols::findMethodHandleType_name(),
|
vmSymbols::findMethodHandleType_name(),
|
||||||
vmSymbols::findMethodHandleType_signature(),
|
vmSymbols::findMethodHandleType_signature(),
|
||||||
&args, CHECK_(empty));
|
&args, CHECK_(empty));
|
||||||
|
Handle method_type(THREAD, (oop) result.get_jobject());
|
||||||
|
|
||||||
|
if (for_invokeGeneric) {
|
||||||
|
// call sun.dyn.MethodHandleNatives::notifyGenericMethodType(MethodType) -> void
|
||||||
|
JavaCallArguments args(Handle(THREAD, method_type()));
|
||||||
|
JavaValue no_result(T_VOID);
|
||||||
|
JavaCalls::call_static(&no_result,
|
||||||
|
SystemDictionary::MethodHandleNatives_klass(),
|
||||||
|
vmSymbols::notifyGenericMethodType_name(),
|
||||||
|
vmSymbols::notifyGenericMethodType_signature(),
|
||||||
|
&args, THREAD);
|
||||||
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
|
// If the notification fails, just kill it.
|
||||||
|
CLEAR_PENDING_EXCEPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// report back to the caller with the MethodType and the "on_bcp" flag
|
// report back to the caller with the MethodType and the "on_bcp" flag
|
||||||
return_bcp_flag = is_on_bcp;
|
return_bcp_flag = is_on_bcp;
|
||||||
return Handle(THREAD, (oop) result.get_jobject());
|
return method_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask Java code to find or construct a method handle constant.
|
// Ask Java code to find or construct a method handle constant.
|
||||||
@ -2466,7 +2486,7 @@ Handle SystemDictionary::link_method_handle_constant(KlassHandle caller,
|
|||||||
Handle type;
|
Handle type;
|
||||||
if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
|
if (signature->utf8_length() > 0 && signature->byte_at(0) == '(') {
|
||||||
bool ignore_is_on_bcp = false;
|
bool ignore_is_on_bcp = false;
|
||||||
type = find_method_handle_type(signature, caller, ignore_is_on_bcp, CHECK_(empty));
|
type = find_method_handle_type(signature, caller, false, ignore_is_on_bcp, CHECK_(empty));
|
||||||
} else {
|
} else {
|
||||||
SignatureStream ss(signature(), false);
|
SignatureStream ss(signature(), false);
|
||||||
if (!ss.is_done()) {
|
if (!ss.is_done()) {
|
||||||
|
@ -471,6 +471,7 @@ public:
|
|||||||
// ask Java to compute a java.dyn.MethodType object for a given signature
|
// ask Java to compute a java.dyn.MethodType object for a given signature
|
||||||
static Handle find_method_handle_type(symbolHandle signature,
|
static Handle find_method_handle_type(symbolHandle signature,
|
||||||
KlassHandle accessing_klass,
|
KlassHandle accessing_klass,
|
||||||
|
bool for_invokeGeneric,
|
||||||
bool& return_bcp_flag,
|
bool& return_bcp_flag,
|
||||||
TRAPS);
|
TRAPS);
|
||||||
// ask Java to compute a java.dyn.MethodHandle object for a given CP entry
|
// ask Java to compute a java.dyn.MethodHandle object for a given CP entry
|
||||||
|
@ -246,6 +246,8 @@
|
|||||||
/* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \
|
/* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \
|
||||||
template(findMethodHandleType_name, "findMethodHandleType") \
|
template(findMethodHandleType_name, "findMethodHandleType") \
|
||||||
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \
|
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \
|
||||||
|
template(notifyGenericMethodType_name, "notifyGenericMethodType") \
|
||||||
|
template(notifyGenericMethodType_signature, "(Ljava/dyn/MethodType;)V") \
|
||||||
template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \
|
template(linkMethodHandleConstant_name, "linkMethodHandleConstant") \
|
||||||
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") \
|
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/dyn/MethodHandle;") \
|
||||||
template(makeDynamicCallSite_name, "makeDynamicCallSite") \
|
template(makeDynamicCallSite_name, "makeDynamicCallSite") \
|
||||||
@ -345,6 +347,7 @@
|
|||||||
template(ptypes_name, "ptypes") \
|
template(ptypes_name, "ptypes") \
|
||||||
template(form_name, "form") \
|
template(form_name, "form") \
|
||||||
template(erasedType_name, "erasedType") \
|
template(erasedType_name, "erasedType") \
|
||||||
|
template(genericInvoker_name, "genericInvoker") \
|
||||||
template(append_name, "append") \
|
template(append_name, "append") \
|
||||||
\
|
\
|
||||||
/* non-intrinsic name/signature pairs: */ \
|
/* non-intrinsic name/signature pairs: */ \
|
||||||
|
@ -200,6 +200,7 @@ IRT_END
|
|||||||
void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) {
|
void InterpreterRuntime::note_trap(JavaThread* thread, int reason, TRAPS) {
|
||||||
assert(ProfileTraps, "call me only if profiling");
|
assert(ProfileTraps, "call me only if profiling");
|
||||||
methodHandle trap_method(thread, method(thread));
|
methodHandle trap_method(thread, method(thread));
|
||||||
|
|
||||||
if (trap_method.not_null()) {
|
if (trap_method.not_null()) {
|
||||||
methodDataHandle trap_mdo(thread, trap_method->method_data());
|
methodDataHandle trap_mdo(thread, trap_method->method_data());
|
||||||
if (trap_mdo.is_null()) {
|
if (trap_mdo.is_null()) {
|
||||||
|
@ -466,6 +466,7 @@ oop constantPoolOopDesc::resolve_constant_at_impl(constantPoolHandle this_oop, i
|
|||||||
bool ignore_is_on_bcp = false;
|
bool ignore_is_on_bcp = false;
|
||||||
Handle value = SystemDictionary::find_method_handle_type(signature,
|
Handle value = SystemDictionary::find_method_handle_type(signature,
|
||||||
klass,
|
klass,
|
||||||
|
false,
|
||||||
ignore_is_on_bcp,
|
ignore_is_on_bcp,
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
result_oop = value();
|
result_oop = value();
|
||||||
|
@ -819,11 +819,13 @@ bool methodOopDesc::should_not_be_cached() const {
|
|||||||
|
|
||||||
bool methodOopDesc::is_method_handle_invoke_name(vmSymbols::SID name_sid) {
|
bool methodOopDesc::is_method_handle_invoke_name(vmSymbols::SID name_sid) {
|
||||||
switch (name_sid) {
|
switch (name_sid) {
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name): // FIXME: remove this transitional form
|
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name):
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name):
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name):
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name):
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (AllowTransitionalJSR292
|
||||||
|
&& name_sid == vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name))
|
||||||
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,12 +913,16 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
|||||||
m->set_signature_index(_imcp_invoke_signature);
|
m->set_signature_index(_imcp_invoke_signature);
|
||||||
assert(is_method_handle_invoke_name(m->name()), "");
|
assert(is_method_handle_invoke_name(m->name()), "");
|
||||||
assert(m->signature() == signature(), "");
|
assert(m->signature() == signature(), "");
|
||||||
|
assert(m->is_method_handle_invoke(), "");
|
||||||
#ifdef CC_INTERP
|
#ifdef CC_INTERP
|
||||||
ResultTypeFinder rtf(signature());
|
ResultTypeFinder rtf(signature());
|
||||||
m->set_result_index(rtf.type());
|
m->set_result_index(rtf.type());
|
||||||
#endif
|
#endif
|
||||||
m->compute_size_of_parameters(THREAD);
|
m->compute_size_of_parameters(THREAD);
|
||||||
m->set_exception_table(Universe::the_empty_int_array());
|
m->set_exception_table(Universe::the_empty_int_array());
|
||||||
|
m->init_intrinsic_id();
|
||||||
|
assert(m->intrinsic_id() == vmIntrinsics::_invokeExact ||
|
||||||
|
m->intrinsic_id() == vmIntrinsics::_invokeGeneric, "must be an invoker");
|
||||||
|
|
||||||
// Finally, set up its entry points.
|
// Finally, set up its entry points.
|
||||||
assert(m->method_handle_type() == method_type(), "");
|
assert(m->method_handle_type() == method_type(), "");
|
||||||
@ -1029,6 +1035,7 @@ void methodOopDesc::init_intrinsic_id() {
|
|||||||
assert(_intrinsic_id == vmIntrinsics::_none, "do this just once");
|
assert(_intrinsic_id == vmIntrinsics::_none, "do this just once");
|
||||||
const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte));
|
const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte));
|
||||||
assert((uintptr_t)vmIntrinsics::ID_LIMIT <= max_id_uint, "else fix size");
|
assert((uintptr_t)vmIntrinsics::ID_LIMIT <= max_id_uint, "else fix size");
|
||||||
|
assert(intrinsic_id_size_in_bytes() == sizeof(_intrinsic_id), "");
|
||||||
|
|
||||||
// the klass name is well-known:
|
// the klass name is well-known:
|
||||||
vmSymbols::SID klass_id = klass_id_for_intrinsics(method_holder());
|
vmSymbols::SID klass_id = klass_id_for_intrinsics(method_holder());
|
||||||
@ -1036,9 +1043,10 @@ void methodOopDesc::init_intrinsic_id() {
|
|||||||
|
|
||||||
// ditto for method and signature:
|
// ditto for method and signature:
|
||||||
vmSymbols::SID name_id = vmSymbols::find_sid(name());
|
vmSymbols::SID name_id = vmSymbols::find_sid(name());
|
||||||
if (name_id == vmSymbols::NO_SID) return;
|
if (name_id == vmSymbols::NO_SID) return;
|
||||||
vmSymbols::SID sig_id = vmSymbols::find_sid(signature());
|
vmSymbols::SID sig_id = vmSymbols::find_sid(signature());
|
||||||
if (sig_id == vmSymbols::NO_SID) return;
|
if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_MethodHandle)
|
||||||
|
&& sig_id == vmSymbols::NO_SID) return;
|
||||||
jshort flags = access_flags().as_short();
|
jshort flags = access_flags().as_short();
|
||||||
|
|
||||||
vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
|
vmIntrinsics::ID id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
|
||||||
@ -1067,10 +1075,13 @@ void methodOopDesc::init_intrinsic_id() {
|
|||||||
if (is_static() || !is_native()) break;
|
if (is_static() || !is_native()) break;
|
||||||
switch (name_id) {
|
switch (name_id) {
|
||||||
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name):
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name):
|
||||||
id = vmIntrinsics::_invokeGeneric; break;
|
id = vmIntrinsics::_invokeGeneric;
|
||||||
default:
|
break;
|
||||||
if (is_method_handle_invoke_name(name()))
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name):
|
||||||
id = vmIntrinsics::_invokeExact;
|
id = vmIntrinsics::_invokeExact;
|
||||||
|
break;
|
||||||
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name):
|
||||||
|
if (AllowTransitionalJSR292) id = vmIntrinsics::_invokeExact;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -516,6 +516,8 @@ class methodOopDesc : public oopDesc {
|
|||||||
static int method_data_offset_in_bytes() { return offset_of(methodOopDesc, _method_data); }
|
static int method_data_offset_in_bytes() { return offset_of(methodOopDesc, _method_data); }
|
||||||
static int interpreter_invocation_counter_offset_in_bytes()
|
static int interpreter_invocation_counter_offset_in_bytes()
|
||||||
{ return offset_of(methodOopDesc, _interpreter_invocation_count); }
|
{ return offset_of(methodOopDesc, _interpreter_invocation_count); }
|
||||||
|
static int intrinsic_id_offset_in_bytes() { return offset_of(methodOopDesc, _intrinsic_id); }
|
||||||
|
static int intrinsic_id_size_in_bytes() { return sizeof(u1); }
|
||||||
|
|
||||||
// Static methods that are used to implement member methods where an exposed this pointer
|
// Static methods that are used to implement member methods where an exposed this pointer
|
||||||
// is needed due to possible GCs
|
// is needed due to possible GCs
|
||||||
|
@ -333,8 +333,7 @@ MethodHandleWalker::walk(TRAPS) {
|
|||||||
ArgToken arglist[2];
|
ArgToken arglist[2];
|
||||||
arglist[0] = arg; // outgoing value
|
arglist[0] = arg; // outgoing value
|
||||||
arglist[1] = ArgToken(); // sentinel
|
arglist[1] = ArgToken(); // sentinel
|
||||||
assert(false, "I think the argument count must be 1 instead of 0");
|
arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty));
|
||||||
arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 0, &arglist[0], CHECK_(empty));
|
|
||||||
change_argument(src, arg_slot, T_OBJECT, arg);
|
change_argument(src, arg_slot, T_OBJECT, arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1398,7 +1397,9 @@ public:
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
void print_method_handle(oop mh) {
|
void print_method_handle(oop mh) {
|
||||||
if (java_dyn_MethodHandle::is_instance(mh)) {
|
if (!mh->is_oop()) {
|
||||||
|
tty->print_cr("*** not a method handle: "INTPTR_FORMAT, (intptr_t)mh);
|
||||||
|
} else if (java_dyn_MethodHandle::is_instance(mh)) {
|
||||||
//MethodHandlePrinter::print(mh);
|
//MethodHandlePrinter::print(mh);
|
||||||
} else {
|
} else {
|
||||||
tty->print("*** not a method handle: ");
|
tty->print("*** not a method handle: ");
|
||||||
|
@ -446,6 +446,8 @@ class MethodHandles: AllStatic {
|
|||||||
RegisterOrConstant arg_slots,
|
RegisterOrConstant arg_slots,
|
||||||
Register argslot_reg,
|
Register argslot_reg,
|
||||||
Register temp_reg, Register temp2_reg, Register temp3_reg = noreg);
|
Register temp_reg, Register temp2_reg, Register temp3_reg = noreg);
|
||||||
|
|
||||||
|
static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1633,8 +1633,13 @@ char* SharedRuntime::generate_class_cast_message(
|
|||||||
char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
|
char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
|
||||||
oopDesc* required,
|
oopDesc* required,
|
||||||
oopDesc* actual) {
|
oopDesc* actual) {
|
||||||
|
if (TraceMethodHandles) {
|
||||||
|
tty->print_cr("WrongMethodType thread="PTR_FORMAT" req="PTR_FORMAT" act="PTR_FORMAT"",
|
||||||
|
thread, required, actual);
|
||||||
|
}
|
||||||
assert(EnableMethodHandles, "");
|
assert(EnableMethodHandles, "");
|
||||||
oop singleKlass = wrong_method_type_is_for_single_argument(thread, required);
|
oop singleKlass = wrong_method_type_is_for_single_argument(thread, required);
|
||||||
|
char* message = NULL;
|
||||||
if (singleKlass != NULL) {
|
if (singleKlass != NULL) {
|
||||||
const char* objName = "argument or return value";
|
const char* objName = "argument or return value";
|
||||||
if (actual != NULL) {
|
if (actual != NULL) {
|
||||||
@ -1647,7 +1652,7 @@ char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
|
|||||||
Klass* targetKlass = Klass::cast(required->is_klass()
|
Klass* targetKlass = Klass::cast(required->is_klass()
|
||||||
? (klassOop)required
|
? (klassOop)required
|
||||||
: java_lang_Class::as_klassOop(required));
|
: java_lang_Class::as_klassOop(required));
|
||||||
return generate_class_cast_message(objName, targetKlass->external_name());
|
message = generate_class_cast_message(objName, targetKlass->external_name());
|
||||||
} else {
|
} else {
|
||||||
// %%% need to get the MethodType string, without messing around too much
|
// %%% need to get the MethodType string, without messing around too much
|
||||||
// Get a signature from the invoke instruction
|
// Get a signature from the invoke instruction
|
||||||
@ -1679,9 +1684,13 @@ char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
|
|||||||
if (mhName[0] == '$')
|
if (mhName[0] == '$')
|
||||||
mhName = actual_method->signature()->as_C_string();
|
mhName = actual_method->signature()->as_C_string();
|
||||||
}
|
}
|
||||||
return generate_class_cast_message(mhName, targetType,
|
message = generate_class_cast_message(mhName, targetType,
|
||||||
" cannot be called as ");
|
" cannot be called as ");
|
||||||
}
|
}
|
||||||
|
if (TraceMethodHandles) {
|
||||||
|
tty->print_cr("WrongMethodType => message=%s", message);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
oop SharedRuntime::wrong_method_type_is_for_single_argument(JavaThread* thr,
|
oop SharedRuntime::wrong_method_type_is_for_single_argument(JavaThread* thr,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user