7120468: SPARC/x86: use frame::describe to enhance trace_method_handle
Improvements of TraceMethodHandles for JSR292 Reviewed-by: never, twisti
This commit is contained in:
parent
de3ed511b1
commit
070f9108ff
@ -810,7 +810,7 @@ intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
|
|
||||||
#define DESCRIBE_FP_OFFSET(name) \
|
#define DESCRIBE_FP_OFFSET(name) \
|
||||||
values.describe(frame_no, fp() + frame::name##_offset, #name)
|
values.describe(frame_no, fp() + frame::name##_offset, #name)
|
||||||
|
@ -177,7 +177,7 @@ void MethodHandles::RicochetFrame::generate_ricochet_blob(MacroAssembler* _masm,
|
|||||||
BLOCK_COMMENT("ricochet_blob.bounce");
|
BLOCK_COMMENT("ricochet_blob.bounce");
|
||||||
|
|
||||||
if (VerifyMethodHandles) RicochetFrame::verify_clean(_masm);
|
if (VerifyMethodHandles) RicochetFrame::verify_clean(_masm);
|
||||||
trace_method_handle(_masm, "ricochet_blob.bounce");
|
trace_method_handle(_masm, "return/ricochet_blob.bounce");
|
||||||
|
|
||||||
__ JMP(L1_continuation, 0);
|
__ JMP(L1_continuation, 0);
|
||||||
__ delayed()->nop();
|
__ delayed()->nop();
|
||||||
@ -268,14 +268,16 @@ void MethodHandles::RicochetFrame::leave_ricochet_frame(MacroAssembler* _masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emit code to verify that FP is pointing at a valid ricochet frame.
|
// Emit code to verify that FP is pointing at a valid ricochet frame.
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
enum {
|
enum {
|
||||||
ARG_LIMIT = 255, SLOP = 45,
|
ARG_LIMIT = 255, SLOP = 45,
|
||||||
// use this parameter for checking for garbage stack movements:
|
// use this parameter for checking for garbage stack movements:
|
||||||
UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
|
UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
|
||||||
// the slop defends against false alarms due to fencepost errors
|
// the slop defends against false alarms due to fencepost errors
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
|
void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
|
||||||
// The stack should look like this:
|
// The stack should look like this:
|
||||||
// ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF]
|
// ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF]
|
||||||
@ -1000,7 +1002,7 @@ void MethodHandles::move_return_value(MacroAssembler* _masm, BasicType type,
|
|||||||
BLOCK_COMMENT("} move_return_value");
|
BLOCK_COMMENT("} move_return_value");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) {
|
void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) {
|
||||||
RicochetFrame* rf = new RicochetFrame(*fr);
|
RicochetFrame* rf = new RicochetFrame(*fr);
|
||||||
|
|
||||||
@ -1022,28 +1024,121 @@ void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values
|
|||||||
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,
|
||||||
oopDesc* mh,
|
oopDesc* mh,
|
||||||
intptr_t* saved_sp) {
|
intptr_t* saved_sp,
|
||||||
|
intptr_t* args,
|
||||||
|
intptr_t* tracing_fp) {
|
||||||
bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have mh
|
bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have mh
|
||||||
tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp);
|
|
||||||
if (has_mh)
|
tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT " args=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp, args);
|
||||||
|
|
||||||
|
if (Verbose) {
|
||||||
|
// dumping last frame with frame::describe
|
||||||
|
|
||||||
|
JavaThread* p = JavaThread::active();
|
||||||
|
|
||||||
|
ResourceMark rm;
|
||||||
|
PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here
|
||||||
|
FrameValues values;
|
||||||
|
|
||||||
|
// Note: We want to allow trace_method_handle from any call site.
|
||||||
|
// While trace_method_handle creates a frame, it may be entered
|
||||||
|
// without a valid return PC in O7 (e.g. not just after a call).
|
||||||
|
// Walking that frame could lead to failures due to that invalid PC.
|
||||||
|
// => carefully detect that frame when doing the stack walking
|
||||||
|
|
||||||
|
// walk up to the right frame using the "tracing_fp" argument
|
||||||
|
intptr_t* cur_sp = StubRoutines::Sparc::flush_callers_register_windows_func()();
|
||||||
|
frame cur_frame(cur_sp, frame::unpatchable, NULL);
|
||||||
|
|
||||||
|
while (cur_frame.fp() != (intptr_t *)(STACK_BIAS+(uintptr_t)tracing_fp)) {
|
||||||
|
cur_frame = os::get_sender_for_C_frame(&cur_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
// safely create a frame and call frame::describe
|
||||||
|
intptr_t *dump_sp = cur_frame.sender_sp();
|
||||||
|
intptr_t *dump_fp = cur_frame.link();
|
||||||
|
|
||||||
|
bool walkable = has_mh; // whether the traced frame shoud be walkable
|
||||||
|
|
||||||
|
// the sender for cur_frame is the caller of trace_method_handle
|
||||||
|
if (walkable) {
|
||||||
|
// The previous definition of walkable may have to be refined
|
||||||
|
// if new call sites cause the next frame constructor to start
|
||||||
|
// failing. Alternatively, frame constructors could be
|
||||||
|
// modified to support the current or future non walkable
|
||||||
|
// frames (but this is more intrusive and is not considered as
|
||||||
|
// part of this RFE, which will instead use a simpler output).
|
||||||
|
frame dump_frame = frame(dump_sp,
|
||||||
|
cur_frame.sp(), // younger_sp
|
||||||
|
false); // no adaptation
|
||||||
|
dump_frame.describe(values, 1);
|
||||||
|
} else {
|
||||||
|
// Robust dump for frames which cannot be constructed from sp/younger_sp
|
||||||
|
// Add descriptions without building a Java frame to avoid issues
|
||||||
|
values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>");
|
||||||
|
values.describe(-1, dump_sp, "sp");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_args = has_mh; // whether Gargs is meaningful
|
||||||
|
|
||||||
|
// mark args, if seems valid (may not be valid for some adapters)
|
||||||
|
if (has_args) {
|
||||||
|
if ((args >= dump_sp) && (args < dump_fp)) {
|
||||||
|
values.describe(-1, args, "*G4_args");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark saved_sp, if seems valid (may not be valid for some adapters)
|
||||||
|
intptr_t *unbiased_sp = (intptr_t *)(STACK_BIAS+(uintptr_t)saved_sp);
|
||||||
|
if ((unbiased_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (unbiased_sp < dump_fp)) {
|
||||||
|
values.describe(-1, unbiased_sp, "*saved_sp+STACK_BIAS");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: the unextended_sp may not be correct
|
||||||
|
tty->print_cr(" stack layout:");
|
||||||
|
values.print(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_mh) {
|
||||||
print_method_handle(mh);
|
print_method_handle(mh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
|
void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
|
||||||
if (!TraceMethodHandles) return;
|
if (!TraceMethodHandles) return;
|
||||||
BLOCK_COMMENT("trace_method_handle {");
|
BLOCK_COMMENT("trace_method_handle {");
|
||||||
// save: Gargs, O5_savedSP
|
// save: Gargs, O5_savedSP
|
||||||
__ save_frame(16);
|
__ save_frame(16); // need space for saving required FPU state
|
||||||
|
|
||||||
__ set((intptr_t) adaptername, O0);
|
__ set((intptr_t) adaptername, O0);
|
||||||
__ mov(G3_method_handle, O1);
|
__ mov(G3_method_handle, O1);
|
||||||
__ mov(I5_savedSP, O2);
|
__ mov(I5_savedSP, O2);
|
||||||
|
__ mov(Gargs, O3);
|
||||||
|
__ mov(I6, O4); // frame identifier for safe stack walking
|
||||||
|
|
||||||
|
// Save scratched registers that might be needed. Robustness is more
|
||||||
|
// important than optimizing the saves for this debug only code.
|
||||||
|
|
||||||
|
// save FP result, valid at some call sites (adapter_opt_return_float, ...)
|
||||||
|
Address d_save(FP, -sizeof(jdouble) + STACK_BIAS);
|
||||||
|
__ stf(FloatRegisterImpl::D, Ftos_d, d_save);
|
||||||
|
// Safely save all globals but G2 (handled by call_VM_leaf) and G7
|
||||||
|
// (OS reserved).
|
||||||
__ mov(G3_method_handle, L3);
|
__ mov(G3_method_handle, L3);
|
||||||
__ mov(Gargs, L4);
|
__ mov(Gargs, L4);
|
||||||
__ mov(G5_method_type, L5);
|
__ mov(G5_method_type, L5);
|
||||||
__ call_VM_leaf(L7, CAST_FROM_FN_PTR(address, trace_method_handle_stub));
|
__ mov(G6, L6);
|
||||||
|
__ mov(G1, L1);
|
||||||
|
|
||||||
|
__ call_VM_leaf(L2 /* for G2 */, CAST_FROM_FN_PTR(address, trace_method_handle_stub));
|
||||||
|
|
||||||
__ mov(L3, G3_method_handle);
|
__ mov(L3, G3_method_handle);
|
||||||
__ mov(L4, Gargs);
|
__ mov(L4, Gargs);
|
||||||
__ mov(L5, G5_method_type);
|
__ mov(L5, G5_method_type);
|
||||||
|
__ mov(L6, G6);
|
||||||
|
__ mov(L1, G1);
|
||||||
|
__ ldf(FloatRegisterImpl::D, d_save, Ftos_d);
|
||||||
|
|
||||||
__ restore();
|
__ restore();
|
||||||
BLOCK_COMMENT("} trace_method_handle");
|
BLOCK_COMMENT("} trace_method_handle");
|
||||||
}
|
}
|
||||||
@ -1268,7 +1363,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
|
|||||||
move_typed_arg(_masm, arg_type, false,
|
move_typed_arg(_masm, arg_type, false,
|
||||||
prim_value_addr,
|
prim_value_addr,
|
||||||
Address(O0_argslot, 0),
|
Address(O0_argslot, 0),
|
||||||
O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3)
|
O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (direct_to_method) {
|
if (direct_to_method) {
|
||||||
|
@ -146,7 +146,7 @@ class RicochetFrame : public ResourceObj {
|
|||||||
|
|
||||||
static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN;
|
static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN;
|
||||||
|
|
||||||
static void describe(const frame* fr, FrameValues& values, int frame_no) NOT_DEBUG_RETURN;
|
static void describe(const frame* fr, FrameValues& values, int frame_no) PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Additional helper methods for MethodHandles code generation:
|
// Additional helper methods for MethodHandles code generation:
|
||||||
|
@ -651,7 +651,7 @@ intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
|
|||||||
return &interpreter_frame_tos_address()[index];
|
return &interpreter_frame_tos_address()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
|
|
||||||
#define DESCRIBE_FP_OFFSET(name) \
|
#define DESCRIBE_FP_OFFSET(name) \
|
||||||
values.describe(frame_no, fp() + frame::name##_offset, #name)
|
values.describe(frame_no, fp() + frame::name##_offset, #name)
|
||||||
|
@ -279,14 +279,16 @@ void MethodHandles::RicochetFrame::leave_ricochet_frame(MacroAssembler* _masm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emit code to verify that RBP is pointing at a valid ricochet frame.
|
// Emit code to verify that RBP is pointing at a valid ricochet frame.
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
enum {
|
enum {
|
||||||
ARG_LIMIT = 255, SLOP = 4,
|
ARG_LIMIT = 255, SLOP = 4,
|
||||||
// use this parameter for checking for garbage stack movements:
|
// use this parameter for checking for garbage stack movements:
|
||||||
UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
|
UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
|
||||||
// the slop defends against false alarms due to fencepost errors
|
// the slop defends against false alarms due to fencepost errors
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
|
void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
|
||||||
// The stack should look like this:
|
// The stack should look like this:
|
||||||
// ... keep1 | dest=42 | keep2 | RF | magic | handler | magic | recursive args |
|
// ... keep1 | dest=42 | keep2 | RF | magic | handler | magic | recursive args |
|
||||||
@ -990,7 +992,7 @@ void MethodHandles::move_return_value(MacroAssembler* _masm, BasicType type,
|
|||||||
BLOCK_COMMENT("} move_return_value");
|
BLOCK_COMMENT("} move_return_value");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
#define DESCRIBE_RICOCHET_OFFSET(rf, name) \
|
#define DESCRIBE_RICOCHET_OFFSET(rf, name) \
|
||||||
values.describe(frame_no, (intptr_t *) (((uintptr_t)rf) + MethodHandles::RicochetFrame::name##_offset_in_bytes()), #name)
|
values.describe(frame_no, (intptr_t *) (((uintptr_t)rf) + MethodHandles::RicochetFrame::name##_offset_in_bytes()), #name)
|
||||||
|
|
||||||
@ -1021,6 +1023,7 @@ void trace_method_handle_stub(const char* adaptername,
|
|||||||
intptr_t* saved_bp) {
|
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!
|
||||||
bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have rcx_mh
|
bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have rcx_mh
|
||||||
|
|
||||||
intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
|
intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
|
||||||
intptr_t* base_sp = last_sp;
|
intptr_t* base_sp = last_sp;
|
||||||
typedef MethodHandles::RicochetFrame RicochetFrame;
|
typedef MethodHandles::RicochetFrame RicochetFrame;
|
||||||
@ -1050,13 +1053,64 @@ void trace_method_handle_stub(const char* adaptername,
|
|||||||
tty->cr();
|
tty->cr();
|
||||||
if (last_sp != saved_sp && last_sp != NULL)
|
if (last_sp != saved_sp && last_sp != NULL)
|
||||||
tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp);
|
tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp);
|
||||||
int stack_dump_count = 16;
|
|
||||||
if (stack_dump_count < (int)(saved_bp + 2 - saved_sp))
|
{
|
||||||
stack_dump_count = (int)(saved_bp + 2 - saved_sp);
|
// dumping last frame with frame::describe
|
||||||
if (stack_dump_count > 64) stack_dump_count = 48;
|
|
||||||
for (i = 0; i < stack_dump_count; i += 4) {
|
JavaThread* p = JavaThread::active();
|
||||||
tty->print_cr(" dump at SP[%d] "PTR_FORMAT": "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT,
|
|
||||||
i, (intptr_t) &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]);
|
ResourceMark rm;
|
||||||
|
PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here
|
||||||
|
FrameValues values;
|
||||||
|
|
||||||
|
// Note: We want to allow trace_method_handle from any call site.
|
||||||
|
// While trace_method_handle creates a frame, it may be entered
|
||||||
|
// without a PC on the stack top (e.g. not just after a call).
|
||||||
|
// Walking that frame could lead to failures due to that invalid PC.
|
||||||
|
// => carefully detect that frame when doing the stack walking
|
||||||
|
|
||||||
|
// Current C frame
|
||||||
|
frame cur_frame = os::current_frame();
|
||||||
|
|
||||||
|
// Robust search of trace_calling_frame (independant of inlining).
|
||||||
|
// Assumes saved_regs comes from a pusha in the trace_calling_frame.
|
||||||
|
assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?");
|
||||||
|
frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame);
|
||||||
|
while (trace_calling_frame.fp() < saved_regs) {
|
||||||
|
trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
// safely create a frame and call frame::describe
|
||||||
|
intptr_t *dump_sp = trace_calling_frame.sender_sp();
|
||||||
|
intptr_t *dump_fp = trace_calling_frame.link();
|
||||||
|
|
||||||
|
bool walkable = has_mh; // whether the traced frame shoud be walkable
|
||||||
|
|
||||||
|
if (walkable) {
|
||||||
|
// The previous definition of walkable may have to be refined
|
||||||
|
// if new call sites cause the next frame constructor to start
|
||||||
|
// failing. Alternatively, frame constructors could be
|
||||||
|
// modified to support the current or future non walkable
|
||||||
|
// frames (but this is more intrusive and is not considered as
|
||||||
|
// part of this RFE, which will instead use a simpler output).
|
||||||
|
frame dump_frame = frame(dump_sp, dump_fp);
|
||||||
|
dump_frame.describe(values, 1);
|
||||||
|
} else {
|
||||||
|
// Stack may not be walkable (invalid PC above FP):
|
||||||
|
// Add descriptions without building a Java frame to avoid issues
|
||||||
|
values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>");
|
||||||
|
values.describe(-1, dump_sp, "sp for #1");
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark saved_sp if seems valid
|
||||||
|
if (has_mh) {
|
||||||
|
if ((saved_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (saved_sp < dump_fp)) {
|
||||||
|
values.describe(-1, saved_sp, "*saved_sp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tty->print_cr(" stack layout:");
|
||||||
|
values.print(p);
|
||||||
}
|
}
|
||||||
if (has_mh)
|
if (has_mh)
|
||||||
print_method_handle(mh);
|
print_method_handle(mh);
|
||||||
@ -1086,26 +1140,49 @@ void trace_method_handle_stub_wrapper(MethodHandleStubArguments* args) {
|
|||||||
void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
|
void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
|
||||||
if (!TraceMethodHandles) return;
|
if (!TraceMethodHandles) return;
|
||||||
BLOCK_COMMENT("trace_method_handle {");
|
BLOCK_COMMENT("trace_method_handle {");
|
||||||
__ push(rax);
|
|
||||||
__ lea(rax, Address(rsp, wordSize * NOT_LP64(6) LP64_ONLY(14))); // entry_sp __ pusha();
|
|
||||||
__ pusha();
|
|
||||||
__ mov(rbx, rsp);
|
|
||||||
__ enter();
|
__ enter();
|
||||||
|
__ andptr(rsp, -16); // align stack if needed for FPU state
|
||||||
|
__ pusha();
|
||||||
|
__ mov(rbx, rsp); // for retreiving saved_regs
|
||||||
|
// Note: saved_regs must be in the entered frame for the
|
||||||
|
// robust stack walking implemented in trace_method_handle_stub.
|
||||||
|
|
||||||
|
// save FP result, valid at some call sites (adapter_opt_return_float, ...)
|
||||||
|
__ increment(rsp, -2 * wordSize);
|
||||||
|
if (UseSSE >= 2) {
|
||||||
|
__ movdbl(Address(rsp, 0), xmm0);
|
||||||
|
} else if (UseSSE == 1) {
|
||||||
|
__ movflt(Address(rsp, 0), xmm0);
|
||||||
|
} else {
|
||||||
|
__ fst_d(Address(rsp, 0));
|
||||||
|
}
|
||||||
|
|
||||||
// incoming state:
|
// incoming state:
|
||||||
// rcx: method handle
|
// rcx: method handle
|
||||||
// r13 or rsi: saved sp
|
// r13 or rsi: saved sp
|
||||||
// To avoid calling convention issues, build a record on the stack and pass the pointer to that instead.
|
// To avoid calling convention issues, build a record on the stack and pass the pointer to that instead.
|
||||||
|
// Note: fix the increment below if pushing more arguments
|
||||||
__ push(rbp); // saved_bp
|
__ push(rbp); // saved_bp
|
||||||
__ push(rsi); // saved_sp
|
__ push(saved_last_sp_register()); // saved_sp
|
||||||
__ push(rax); // entry_sp
|
__ push(rbp); // entry_sp (with extra align space)
|
||||||
__ push(rbx); // pusha saved_regs
|
__ push(rbx); // pusha saved_regs
|
||||||
__ push(rcx); // mh
|
__ push(rcx); // mh
|
||||||
__ push(rcx); // adaptername
|
__ push(rcx); // slot for adaptername
|
||||||
__ movptr(Address(rsp, 0), (intptr_t) adaptername);
|
__ movptr(Address(rsp, 0), (intptr_t) adaptername);
|
||||||
__ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp);
|
__ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp);
|
||||||
__ leave();
|
__ increment(rsp, 6 * wordSize); // MethodHandleStubArguments
|
||||||
|
|
||||||
|
if (UseSSE >= 2) {
|
||||||
|
__ movdbl(xmm0, Address(rsp, 0));
|
||||||
|
} else if (UseSSE == 1) {
|
||||||
|
__ movflt(xmm0, Address(rsp, 0));
|
||||||
|
} else {
|
||||||
|
__ fld_d(Address(rsp, 0));
|
||||||
|
}
|
||||||
|
__ increment(rsp, 2 * wordSize);
|
||||||
|
|
||||||
__ popa();
|
__ popa();
|
||||||
__ pop(rax);
|
__ leave();
|
||||||
BLOCK_COMMENT("} trace_method_handle");
|
BLOCK_COMMENT("} trace_method_handle");
|
||||||
}
|
}
|
||||||
#endif //PRODUCT
|
#endif //PRODUCT
|
||||||
|
@ -225,7 +225,7 @@ class RicochetFrame {
|
|||||||
|
|
||||||
static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN;
|
static void verify_clean(MacroAssembler* _masm) NOT_DEBUG_RETURN;
|
||||||
|
|
||||||
static void describe(const frame* fr, FrameValues& values, int frame_no) NOT_DEBUG_RETURN;
|
static void describe(const frame* fr, FrameValues& values, int frame_no) PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Additional helper methods for MethodHandles code generation:
|
// Additional helper methods for MethodHandles code generation:
|
||||||
|
@ -418,7 +418,7 @@ void ZeroFrame::identify_vp_word(int frame_index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
|
|
||||||
void frame::describe_pd(FrameValues& values, int frame_no) {
|
void frame::describe_pd(FrameValues& values, int frame_no) {
|
||||||
|
|
||||||
|
@ -1315,7 +1315,6 @@ bool frame::verify_return_pc(address x) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const {
|
void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const {
|
||||||
assert(is_interpreted_frame(), "Not an interpreted frame");
|
assert(is_interpreted_frame(), "Not an interpreted frame");
|
||||||
@ -1331,8 +1330,9 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const {
|
|||||||
guarantee((current - low_mark) % monitor_size == 0 , "Misaligned bottom of BasicObjectLock*");
|
guarantee((current - low_mark) % monitor_size == 0 , "Misaligned bottom of BasicObjectLock*");
|
||||||
guarantee( current >= low_mark , "Current BasicObjectLock* below than low_mark");
|
guarantee( current >= low_mark , "Current BasicObjectLock* below than low_mark");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
void frame::describe(FrameValues& values, int frame_no) {
|
void frame::describe(FrameValues& values, int frame_no) {
|
||||||
// boundaries: sp and the 'real' frame pointer
|
// boundaries: sp and the 'real' frame pointer
|
||||||
values.describe(-1, sp(), err_msg("sp for #%d", frame_no), 1);
|
values.describe(-1, sp(), err_msg("sp for #%d", frame_no), 1);
|
||||||
@ -1436,7 +1436,7 @@ StackFrameStream::StackFrameStream(JavaThread *thread, bool update) : _reg_map(t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
|
|
||||||
void FrameValues::describe(int owner, intptr_t* location, const char* description, int priority) {
|
void FrameValues::describe(int owner, intptr_t* location, const char* description, int priority) {
|
||||||
FrameValue fv;
|
FrameValue fv;
|
||||||
@ -1449,6 +1449,7 @@ void FrameValues::describe(int owner, intptr_t* location, const char* descriptio
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
void FrameValues::validate() {
|
void FrameValues::validate() {
|
||||||
_values.sort(compare);
|
_values.sort(compare);
|
||||||
bool error = false;
|
bool error = false;
|
||||||
@ -1474,7 +1475,7 @@ void FrameValues::validate() {
|
|||||||
}
|
}
|
||||||
assert(!error, "invalid layout");
|
assert(!error, "invalid layout");
|
||||||
}
|
}
|
||||||
|
#endif // ASSERT
|
||||||
|
|
||||||
void FrameValues::print(JavaThread* thread) {
|
void FrameValues::print(JavaThread* thread) {
|
||||||
_values.sort(compare);
|
_values.sort(compare);
|
||||||
@ -1523,4 +1524,4 @@ void FrameValues::print(JavaThread* thread) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // ndef PRODUCT
|
||||||
|
@ -494,7 +494,7 @@ class frame VALUE_OBJ_CLASS_SPEC {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifndef PRODUCT
|
||||||
// A simple class to describe a location on the stack
|
// A simple class to describe a location on the stack
|
||||||
class FrameValue VALUE_OBJ_CLASS_SPEC {
|
class FrameValue VALUE_OBJ_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
@ -524,7 +524,9 @@ class FrameValues {
|
|||||||
// Used by frame functions to describe locations.
|
// Used by frame functions to describe locations.
|
||||||
void describe(int owner, intptr_t* location, const char* description, int priority = 0);
|
void describe(int owner, intptr_t* location, const char* description, int priority = 0);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
void validate();
|
void validate();
|
||||||
|
#endif
|
||||||
void print(JavaThread* thread);
|
void print(JavaThread* thread);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user