1.1 --- a/src/cpu/x86/vm/methodHandles_x86.cpp Thu Jan 26 09:38:28 2012 +0100 1.2 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Thu Jan 26 16:49:22 2012 +0100 1.3 @@ -279,14 +279,16 @@ 1.4 } 1.5 1.6 // Emit code to verify that RBP is pointing at a valid ricochet frame. 1.7 -#ifdef ASSERT 1.8 +#ifndef PRODUCT 1.9 enum { 1.10 ARG_LIMIT = 255, SLOP = 4, 1.11 // use this parameter for checking for garbage stack movements: 1.12 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP) 1.13 // the slop defends against false alarms due to fencepost errors 1.14 }; 1.15 +#endif 1.16 1.17 +#ifdef ASSERT 1.18 void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) { 1.19 // The stack should look like this: 1.20 // ... keep1 | dest=42 | keep2 | RF | magic | handler | magic | recursive args | 1.21 @@ -990,7 +992,7 @@ 1.22 BLOCK_COMMENT("} move_return_value"); 1.23 } 1.24 1.25 -#ifdef ASSERT 1.26 +#ifndef PRODUCT 1.27 #define DESCRIBE_RICOCHET_OFFSET(rf, name) \ 1.28 values.describe(frame_no, (intptr_t *) (((uintptr_t)rf) + MethodHandles::RicochetFrame::name##_offset_in_bytes()), #name) 1.29 1.30 @@ -1021,6 +1023,7 @@ 1.31 intptr_t* saved_bp) { 1.32 // called as a leaf from native code: do not block the JVM! 1.33 bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have rcx_mh 1.34 + 1.35 intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset]; 1.36 intptr_t* base_sp = last_sp; 1.37 typedef MethodHandles::RicochetFrame RicochetFrame; 1.38 @@ -1050,13 +1053,64 @@ 1.39 tty->cr(); 1.40 if (last_sp != saved_sp && last_sp != NULL) 1.41 tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp); 1.42 - int stack_dump_count = 16; 1.43 - if (stack_dump_count < (int)(saved_bp + 2 - saved_sp)) 1.44 - stack_dump_count = (int)(saved_bp + 2 - saved_sp); 1.45 - if (stack_dump_count > 64) stack_dump_count = 48; 1.46 - for (i = 0; i < stack_dump_count; i += 4) { 1.47 - tty->print_cr(" dump at SP[%d] "PTR_FORMAT": "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT, 1.48 - i, (intptr_t) &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]); 1.49 + 1.50 + { 1.51 + // dumping last frame with frame::describe 1.52 + 1.53 + JavaThread* p = JavaThread::active(); 1.54 + 1.55 + ResourceMark rm; 1.56 + PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here 1.57 + FrameValues values; 1.58 + 1.59 + // Note: We want to allow trace_method_handle from any call site. 1.60 + // While trace_method_handle creates a frame, it may be entered 1.61 + // without a PC on the stack top (e.g. not just after a call). 1.62 + // Walking that frame could lead to failures due to that invalid PC. 1.63 + // => carefully detect that frame when doing the stack walking 1.64 + 1.65 + // Current C frame 1.66 + frame cur_frame = os::current_frame(); 1.67 + 1.68 + // Robust search of trace_calling_frame (independant of inlining). 1.69 + // Assumes saved_regs comes from a pusha in the trace_calling_frame. 1.70 + assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?"); 1.71 + frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame); 1.72 + while (trace_calling_frame.fp() < saved_regs) { 1.73 + trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame); 1.74 + } 1.75 + 1.76 + // safely create a frame and call frame::describe 1.77 + intptr_t *dump_sp = trace_calling_frame.sender_sp(); 1.78 + intptr_t *dump_fp = trace_calling_frame.link(); 1.79 + 1.80 + bool walkable = has_mh; // whether the traced frame shoud be walkable 1.81 + 1.82 + if (walkable) { 1.83 + // The previous definition of walkable may have to be refined 1.84 + // if new call sites cause the next frame constructor to start 1.85 + // failing. Alternatively, frame constructors could be 1.86 + // modified to support the current or future non walkable 1.87 + // frames (but this is more intrusive and is not considered as 1.88 + // part of this RFE, which will instead use a simpler output). 1.89 + frame dump_frame = frame(dump_sp, dump_fp); 1.90 + dump_frame.describe(values, 1); 1.91 + } else { 1.92 + // Stack may not be walkable (invalid PC above FP): 1.93 + // Add descriptions without building a Java frame to avoid issues 1.94 + values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>"); 1.95 + values.describe(-1, dump_sp, "sp for #1"); 1.96 + } 1.97 + 1.98 + // mark saved_sp if seems valid 1.99 + if (has_mh) { 1.100 + if ((saved_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (saved_sp < dump_fp)) { 1.101 + values.describe(-1, saved_sp, "*saved_sp"); 1.102 + } 1.103 + } 1.104 + 1.105 + tty->print_cr(" stack layout:"); 1.106 + values.print(p); 1.107 } 1.108 if (has_mh) 1.109 print_method_handle(mh); 1.110 @@ -1086,26 +1140,49 @@ 1.111 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { 1.112 if (!TraceMethodHandles) return; 1.113 BLOCK_COMMENT("trace_method_handle {"); 1.114 - __ push(rax); 1.115 - __ lea(rax, Address(rsp, wordSize * NOT_LP64(6) LP64_ONLY(14))); // entry_sp __ pusha(); 1.116 + __ enter(); 1.117 + __ andptr(rsp, -16); // align stack if needed for FPU state 1.118 __ pusha(); 1.119 - __ mov(rbx, rsp); 1.120 - __ enter(); 1.121 + __ mov(rbx, rsp); // for retreiving saved_regs 1.122 + // Note: saved_regs must be in the entered frame for the 1.123 + // robust stack walking implemented in trace_method_handle_stub. 1.124 + 1.125 + // save FP result, valid at some call sites (adapter_opt_return_float, ...) 1.126 + __ increment(rsp, -2 * wordSize); 1.127 + if (UseSSE >= 2) { 1.128 + __ movdbl(Address(rsp, 0), xmm0); 1.129 + } else if (UseSSE == 1) { 1.130 + __ movflt(Address(rsp, 0), xmm0); 1.131 + } else { 1.132 + __ fst_d(Address(rsp, 0)); 1.133 + } 1.134 + 1.135 // incoming state: 1.136 // rcx: method handle 1.137 // r13 or rsi: saved sp 1.138 // To avoid calling convention issues, build a record on the stack and pass the pointer to that instead. 1.139 + // Note: fix the increment below if pushing more arguments 1.140 __ push(rbp); // saved_bp 1.141 - __ push(rsi); // saved_sp 1.142 - __ push(rax); // entry_sp 1.143 + __ push(saved_last_sp_register()); // saved_sp 1.144 + __ push(rbp); // entry_sp (with extra align space) 1.145 __ push(rbx); // pusha saved_regs 1.146 __ push(rcx); // mh 1.147 - __ push(rcx); // adaptername 1.148 + __ push(rcx); // slot for adaptername 1.149 __ movptr(Address(rsp, 0), (intptr_t) adaptername); 1.150 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp); 1.151 + __ increment(rsp, 6 * wordSize); // MethodHandleStubArguments 1.152 + 1.153 + if (UseSSE >= 2) { 1.154 + __ movdbl(xmm0, Address(rsp, 0)); 1.155 + } else if (UseSSE == 1) { 1.156 + __ movflt(xmm0, Address(rsp, 0)); 1.157 + } else { 1.158 + __ fld_d(Address(rsp, 0)); 1.159 + } 1.160 + __ increment(rsp, 2 * wordSize); 1.161 + 1.162 + __ popa(); 1.163 __ leave(); 1.164 - __ popa(); 1.165 - __ pop(rax); 1.166 BLOCK_COMMENT("} trace_method_handle"); 1.167 } 1.168 #endif //PRODUCT