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);