Mercurial > hg > truffle
comparison src/cpu/sparc/vm/methodHandles_sparc.cpp @ 4824:5dbed2f542ff
7120468: SPARC/x86: use frame::describe to enhance trace_method_handle
Summary: improvements of TraceMethodHandles for JSR292
Reviewed-by: never, twisti
author | bdelsart |
---|---|
date | Thu, 26 Jan 2012 16:49:22 +0100 |
parents | 82e5a84b7436 |
children | 33df1aeaebbf 1d7922586cf6 |
comparison
equal
deleted
inserted
replaced
4823:9a28ddfc1f4a | 4824:5dbed2f542ff |
---|---|
175 | 175 |
176 (*bounce_offset) = __ pc() - start; | 176 (*bounce_offset) = __ pc() - start; |
177 BLOCK_COMMENT("ricochet_blob.bounce"); | 177 BLOCK_COMMENT("ricochet_blob.bounce"); |
178 | 178 |
179 if (VerifyMethodHandles) RicochetFrame::verify_clean(_masm); | 179 if (VerifyMethodHandles) RicochetFrame::verify_clean(_masm); |
180 trace_method_handle(_masm, "ricochet_blob.bounce"); | 180 trace_method_handle(_masm, "return/ricochet_blob.bounce"); |
181 | 181 |
182 __ JMP(L1_continuation, 0); | 182 __ JMP(L1_continuation, 0); |
183 __ delayed()->nop(); | 183 __ delayed()->nop(); |
184 __ illtrap(0); | 184 __ illtrap(0); |
185 | 185 |
266 __ mov(L2_saved_target, recv_reg); | 266 __ mov(L2_saved_target, recv_reg); |
267 BLOCK_COMMENT("} end_ricochet_frame"); | 267 BLOCK_COMMENT("} end_ricochet_frame"); |
268 } | 268 } |
269 | 269 |
270 // Emit code to verify that FP is pointing at a valid ricochet frame. | 270 // Emit code to verify that FP is pointing at a valid ricochet frame. |
271 #ifdef ASSERT | 271 #ifndef PRODUCT |
272 enum { | 272 enum { |
273 ARG_LIMIT = 255, SLOP = 45, | 273 ARG_LIMIT = 255, SLOP = 45, |
274 // use this parameter for checking for garbage stack movements: | 274 // use this parameter for checking for garbage stack movements: |
275 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP) | 275 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP) |
276 // the slop defends against false alarms due to fencepost errors | 276 // the slop defends against false alarms due to fencepost errors |
277 }; | 277 }; |
278 | 278 #endif |
279 | |
280 #ifdef ASSERT | |
279 void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) { | 281 void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) { |
280 // The stack should look like this: | 282 // The stack should look like this: |
281 // ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF] | 283 // ... keep1 | dest=42 | keep2 | magic | handler | magic | recursive args | [RF] |
282 // Check various invariants. | 284 // Check various invariants. |
283 | 285 |
998 ShouldNotReachHere(); | 1000 ShouldNotReachHere(); |
999 } | 1001 } |
1000 BLOCK_COMMENT("} move_return_value"); | 1002 BLOCK_COMMENT("} move_return_value"); |
1001 } | 1003 } |
1002 | 1004 |
1003 #ifdef ASSERT | 1005 #ifndef PRODUCT |
1004 void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) { | 1006 void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) { |
1005 RicochetFrame* rf = new RicochetFrame(*fr); | 1007 RicochetFrame* rf = new RicochetFrame(*fr); |
1006 | 1008 |
1007 // ricochet slots (kept in registers for sparc) | 1009 // ricochet slots (kept in registers for sparc) |
1008 values.describe(frame_no, rf->register_addr(I5_savedSP), err_msg("exact_sender_sp reg for #%d", frame_no)); | 1010 values.describe(frame_no, rf->register_addr(I5_savedSP), err_msg("exact_sender_sp reg for #%d", frame_no)); |
1020 | 1022 |
1021 #ifndef PRODUCT | 1023 #ifndef PRODUCT |
1022 extern "C" void print_method_handle(oop mh); | 1024 extern "C" void print_method_handle(oop mh); |
1023 void trace_method_handle_stub(const char* adaptername, | 1025 void trace_method_handle_stub(const char* adaptername, |
1024 oopDesc* mh, | 1026 oopDesc* mh, |
1025 intptr_t* saved_sp) { | 1027 intptr_t* saved_sp, |
1028 intptr_t* args, | |
1029 intptr_t* tracing_fp) { | |
1026 bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have mh | 1030 bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have mh |
1027 tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp); | 1031 |
1028 if (has_mh) | 1032 tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT " args=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp, args); |
1033 | |
1034 if (Verbose) { | |
1035 // dumping last frame with frame::describe | |
1036 | |
1037 JavaThread* p = JavaThread::active(); | |
1038 | |
1039 ResourceMark rm; | |
1040 PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here | |
1041 FrameValues values; | |
1042 | |
1043 // Note: We want to allow trace_method_handle from any call site. | |
1044 // While trace_method_handle creates a frame, it may be entered | |
1045 // without a valid return PC in O7 (e.g. not just after a call). | |
1046 // Walking that frame could lead to failures due to that invalid PC. | |
1047 // => carefully detect that frame when doing the stack walking | |
1048 | |
1049 // walk up to the right frame using the "tracing_fp" argument | |
1050 intptr_t* cur_sp = StubRoutines::Sparc::flush_callers_register_windows_func()(); | |
1051 frame cur_frame(cur_sp, frame::unpatchable, NULL); | |
1052 | |
1053 while (cur_frame.fp() != (intptr_t *)(STACK_BIAS+(uintptr_t)tracing_fp)) { | |
1054 cur_frame = os::get_sender_for_C_frame(&cur_frame); | |
1055 } | |
1056 | |
1057 // safely create a frame and call frame::describe | |
1058 intptr_t *dump_sp = cur_frame.sender_sp(); | |
1059 intptr_t *dump_fp = cur_frame.link(); | |
1060 | |
1061 bool walkable = has_mh; // whether the traced frame shoud be walkable | |
1062 | |
1063 // the sender for cur_frame is the caller of trace_method_handle | |
1064 if (walkable) { | |
1065 // The previous definition of walkable may have to be refined | |
1066 // if new call sites cause the next frame constructor to start | |
1067 // failing. Alternatively, frame constructors could be | |
1068 // modified to support the current or future non walkable | |
1069 // frames (but this is more intrusive and is not considered as | |
1070 // part of this RFE, which will instead use a simpler output). | |
1071 frame dump_frame = frame(dump_sp, | |
1072 cur_frame.sp(), // younger_sp | |
1073 false); // no adaptation | |
1074 dump_frame.describe(values, 1); | |
1075 } else { | |
1076 // Robust dump for frames which cannot be constructed from sp/younger_sp | |
1077 // Add descriptions without building a Java frame to avoid issues | |
1078 values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>"); | |
1079 values.describe(-1, dump_sp, "sp"); | |
1080 } | |
1081 | |
1082 bool has_args = has_mh; // whether Gargs is meaningful | |
1083 | |
1084 // mark args, if seems valid (may not be valid for some adapters) | |
1085 if (has_args) { | |
1086 if ((args >= dump_sp) && (args < dump_fp)) { | |
1087 values.describe(-1, args, "*G4_args"); | |
1088 } | |
1089 } | |
1090 | |
1091 // mark saved_sp, if seems valid (may not be valid for some adapters) | |
1092 intptr_t *unbiased_sp = (intptr_t *)(STACK_BIAS+(uintptr_t)saved_sp); | |
1093 if ((unbiased_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (unbiased_sp < dump_fp)) { | |
1094 values.describe(-1, unbiased_sp, "*saved_sp+STACK_BIAS"); | |
1095 } | |
1096 | |
1097 // Note: the unextended_sp may not be correct | |
1098 tty->print_cr(" stack layout:"); | |
1099 values.print(p); | |
1100 } | |
1101 | |
1102 if (has_mh) { | |
1029 print_method_handle(mh); | 1103 print_method_handle(mh); |
1030 } | 1104 } |
1105 } | |
1106 | |
1031 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { | 1107 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { |
1032 if (!TraceMethodHandles) return; | 1108 if (!TraceMethodHandles) return; |
1033 BLOCK_COMMENT("trace_method_handle {"); | 1109 BLOCK_COMMENT("trace_method_handle {"); |
1034 // save: Gargs, O5_savedSP | 1110 // save: Gargs, O5_savedSP |
1035 __ save_frame(16); | 1111 __ save_frame(16); // need space for saving required FPU state |
1112 | |
1036 __ set((intptr_t) adaptername, O0); | 1113 __ set((intptr_t) adaptername, O0); |
1037 __ mov(G3_method_handle, O1); | 1114 __ mov(G3_method_handle, O1); |
1038 __ mov(I5_savedSP, O2); | 1115 __ mov(I5_savedSP, O2); |
1116 __ mov(Gargs, O3); | |
1117 __ mov(I6, O4); // frame identifier for safe stack walking | |
1118 | |
1119 // Save scratched registers that might be needed. Robustness is more | |
1120 // important than optimizing the saves for this debug only code. | |
1121 | |
1122 // save FP result, valid at some call sites (adapter_opt_return_float, ...) | |
1123 Address d_save(FP, -sizeof(jdouble) + STACK_BIAS); | |
1124 __ stf(FloatRegisterImpl::D, Ftos_d, d_save); | |
1125 // Safely save all globals but G2 (handled by call_VM_leaf) and G7 | |
1126 // (OS reserved). | |
1039 __ mov(G3_method_handle, L3); | 1127 __ mov(G3_method_handle, L3); |
1040 __ mov(Gargs, L4); | 1128 __ mov(Gargs, L4); |
1041 __ mov(G5_method_type, L5); | 1129 __ mov(G5_method_type, L5); |
1042 __ call_VM_leaf(L7, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); | 1130 __ mov(G6, L6); |
1131 __ mov(G1, L1); | |
1132 | |
1133 __ call_VM_leaf(L2 /* for G2 */, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); | |
1043 | 1134 |
1044 __ mov(L3, G3_method_handle); | 1135 __ mov(L3, G3_method_handle); |
1045 __ mov(L4, Gargs); | 1136 __ mov(L4, Gargs); |
1046 __ mov(L5, G5_method_type); | 1137 __ mov(L5, G5_method_type); |
1138 __ mov(L6, G6); | |
1139 __ mov(L1, G1); | |
1140 __ ldf(FloatRegisterImpl::D, d_save, Ftos_d); | |
1141 | |
1047 __ restore(); | 1142 __ restore(); |
1048 BLOCK_COMMENT("} trace_method_handle"); | 1143 BLOCK_COMMENT("} trace_method_handle"); |
1049 } | 1144 } |
1050 #endif // PRODUCT | 1145 #endif // PRODUCT |
1051 | 1146 |
1266 } else { | 1361 } else { |
1267 Address prim_value_addr(O1_scratch, java_lang_boxing_object::value_offset_in_bytes(arg_type)); | 1362 Address prim_value_addr(O1_scratch, java_lang_boxing_object::value_offset_in_bytes(arg_type)); |
1268 move_typed_arg(_masm, arg_type, false, | 1363 move_typed_arg(_masm, arg_type, false, |
1269 prim_value_addr, | 1364 prim_value_addr, |
1270 Address(O0_argslot, 0), | 1365 Address(O0_argslot, 0), |
1271 O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) | 1366 O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) |
1272 } | 1367 } |
1273 | 1368 |
1274 if (direct_to_method) { | 1369 if (direct_to_method) { |
1275 __ load_heap_oop(G3_mh_vmtarget, G5_method); // target is a methodOop | 1370 __ load_heap_oop(G3_mh_vmtarget, G5_method); // target is a methodOop |
1276 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); | 1371 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); |