1.1 --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu Jan 26 09:38:28 2012 +0100 1.2 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu Jan 26 16:49:22 2012 +0100 1.3 @@ -177,7 +177,7 @@ 1.4 BLOCK_COMMENT("ricochet_blob.bounce"); 1.5 1.6 if (VerifyMethodHandles) RicochetFrame::verify_clean(_masm); 1.7 - trace_method_handle(_masm, "ricochet_blob.bounce"); 1.8 + trace_method_handle(_masm, "return/ricochet_blob.bounce"); 1.9 1.10 __ JMP(L1_continuation, 0); 1.11 __ delayed()->nop(); 1.12 @@ -268,14 +268,16 @@ 1.13 } 1.14 1.15 // Emit code to verify that FP is pointing at a valid ricochet frame. 1.16 -#ifdef ASSERT 1.17 +#ifndef PRODUCT 1.18 enum { 1.19 ARG_LIMIT = 255, SLOP = 45, 1.20 // use this parameter for checking for garbage stack movements: 1.21 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP) 1.22 // the slop defends against false alarms due to fencepost errors 1.23 }; 1.24 +#endif 1.25 1.26 +#ifdef ASSERT 1.27 void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) { 1.28 // The stack should look like this: 1.29 // ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF] 1.30 @@ -1000,7 +1002,7 @@ 1.31 BLOCK_COMMENT("} move_return_value"); 1.32 } 1.33 1.34 -#ifdef ASSERT 1.35 +#ifndef PRODUCT 1.36 void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) { 1.37 RicochetFrame* rf = new RicochetFrame(*fr); 1.38 1.39 @@ -1022,28 +1024,121 @@ 1.40 extern "C" void print_method_handle(oop mh); 1.41 void trace_method_handle_stub(const char* adaptername, 1.42 oopDesc* mh, 1.43 - intptr_t* saved_sp) { 1.44 + intptr_t* saved_sp, 1.45 + intptr_t* args, 1.46 + intptr_t* tracing_fp) { 1.47 bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have mh 1.48 - tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp); 1.49 - if (has_mh) 1.50 + 1.51 + tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT " args=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp, args); 1.52 + 1.53 + if (Verbose) { 1.54 + // dumping last frame with frame::describe 1.55 + 1.56 + JavaThread* p = JavaThread::active(); 1.57 + 1.58 + ResourceMark rm; 1.59 + PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here 1.60 + FrameValues values; 1.61 + 1.62 + // Note: We want to allow trace_method_handle from any call site. 1.63 + // While trace_method_handle creates a frame, it may be entered 1.64 + // without a valid return PC in O7 (e.g. not just after a call). 1.65 + // Walking that frame could lead to failures due to that invalid PC. 1.66 + // => carefully detect that frame when doing the stack walking 1.67 + 1.68 + // walk up to the right frame using the "tracing_fp" argument 1.69 + intptr_t* cur_sp = StubRoutines::Sparc::flush_callers_register_windows_func()(); 1.70 + frame cur_frame(cur_sp, frame::unpatchable, NULL); 1.71 + 1.72 + while (cur_frame.fp() != (intptr_t *)(STACK_BIAS+(uintptr_t)tracing_fp)) { 1.73 + cur_frame = os::get_sender_for_C_frame(&cur_frame); 1.74 + } 1.75 + 1.76 + // safely create a frame and call frame::describe 1.77 + intptr_t *dump_sp = cur_frame.sender_sp(); 1.78 + intptr_t *dump_fp = cur_frame.link(); 1.79 + 1.80 + bool walkable = has_mh; // whether the traced frame shoud be walkable 1.81 + 1.82 + // the sender for cur_frame is the caller of trace_method_handle 1.83 + if (walkable) { 1.84 + // The previous definition of walkable may have to be refined 1.85 + // if new call sites cause the next frame constructor to start 1.86 + // failing. Alternatively, frame constructors could be 1.87 + // modified to support the current or future non walkable 1.88 + // frames (but this is more intrusive and is not considered as 1.89 + // part of this RFE, which will instead use a simpler output). 1.90 + frame dump_frame = frame(dump_sp, 1.91 + cur_frame.sp(), // younger_sp 1.92 + false); // no adaptation 1.93 + dump_frame.describe(values, 1); 1.94 + } else { 1.95 + // Robust dump for frames which cannot be constructed from sp/younger_sp 1.96 + // Add descriptions without building a Java frame to avoid issues 1.97 + values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>"); 1.98 + values.describe(-1, dump_sp, "sp"); 1.99 + } 1.100 + 1.101 + bool has_args = has_mh; // whether Gargs is meaningful 1.102 + 1.103 + // mark args, if seems valid (may not be valid for some adapters) 1.104 + if (has_args) { 1.105 + if ((args >= dump_sp) && (args < dump_fp)) { 1.106 + values.describe(-1, args, "*G4_args"); 1.107 + } 1.108 + } 1.109 + 1.110 + // mark saved_sp, if seems valid (may not be valid for some adapters) 1.111 + intptr_t *unbiased_sp = (intptr_t *)(STACK_BIAS+(uintptr_t)saved_sp); 1.112 + if ((unbiased_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (unbiased_sp < dump_fp)) { 1.113 + values.describe(-1, unbiased_sp, "*saved_sp+STACK_BIAS"); 1.114 + } 1.115 + 1.116 + // Note: the unextended_sp may not be correct 1.117 + tty->print_cr(" stack layout:"); 1.118 + values.print(p); 1.119 + } 1.120 + 1.121 + if (has_mh) { 1.122 print_method_handle(mh); 1.123 + } 1.124 } 1.125 + 1.126 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { 1.127 if (!TraceMethodHandles) return; 1.128 BLOCK_COMMENT("trace_method_handle {"); 1.129 // save: Gargs, O5_savedSP 1.130 - __ save_frame(16); 1.131 + __ save_frame(16); // need space for saving required FPU state 1.132 + 1.133 __ set((intptr_t) adaptername, O0); 1.134 __ mov(G3_method_handle, O1); 1.135 __ mov(I5_savedSP, O2); 1.136 + __ mov(Gargs, O3); 1.137 + __ mov(I6, O4); // frame identifier for safe stack walking 1.138 + 1.139 + // Save scratched registers that might be needed. Robustness is more 1.140 + // important than optimizing the saves for this debug only code. 1.141 + 1.142 + // save FP result, valid at some call sites (adapter_opt_return_float, ...) 1.143 + Address d_save(FP, -sizeof(jdouble) + STACK_BIAS); 1.144 + __ stf(FloatRegisterImpl::D, Ftos_d, d_save); 1.145 + // Safely save all globals but G2 (handled by call_VM_leaf) and G7 1.146 + // (OS reserved). 1.147 __ mov(G3_method_handle, L3); 1.148 __ mov(Gargs, L4); 1.149 __ mov(G5_method_type, L5); 1.150 - __ call_VM_leaf(L7, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); 1.151 + __ mov(G6, L6); 1.152 + __ mov(G1, L1); 1.153 + 1.154 + __ call_VM_leaf(L2 /* for G2 */, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); 1.155 1.156 __ mov(L3, G3_method_handle); 1.157 __ mov(L4, Gargs); 1.158 __ mov(L5, G5_method_type); 1.159 + __ mov(L6, G6); 1.160 + __ mov(L1, G1); 1.161 + __ ldf(FloatRegisterImpl::D, d_save, Ftos_d); 1.162 + 1.163 __ restore(); 1.164 BLOCK_COMMENT("} trace_method_handle"); 1.165 } 1.166 @@ -1268,7 +1363,7 @@ 1.167 move_typed_arg(_masm, arg_type, false, 1.168 prim_value_addr, 1.169 Address(O0_argslot, 0), 1.170 - O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) 1.171 + O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) 1.172 } 1.173 1.174 if (direct_to_method) {