comparison src/cpu/x86/vm/methodHandles_x86.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 392a3f07d567
comparison
equal deleted inserted replaced
4823:9a28ddfc1f4a 4824:5dbed2f542ff
277 __ mov(rsp, new_sp_reg); 277 __ mov(rsp, new_sp_reg);
278 BLOCK_COMMENT("} end_ricochet_frame"); 278 BLOCK_COMMENT("} end_ricochet_frame");
279 } 279 }
280 280
281 // Emit code to verify that RBP is pointing at a valid ricochet frame. 281 // Emit code to verify that RBP is pointing at a valid ricochet frame.
282 #ifdef ASSERT 282 #ifndef PRODUCT
283 enum { 283 enum {
284 ARG_LIMIT = 255, SLOP = 4, 284 ARG_LIMIT = 255, SLOP = 4,
285 // use this parameter for checking for garbage stack movements: 285 // use this parameter for checking for garbage stack movements:
286 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP) 286 UNREASONABLE_STACK_MOVE = (ARG_LIMIT + SLOP)
287 // the slop defends against false alarms due to fencepost errors 287 // the slop defends against false alarms due to fencepost errors
288 }; 288 };
289 289 #endif
290
291 #ifdef ASSERT
290 void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) { 292 void MethodHandles::RicochetFrame::verify_clean(MacroAssembler* _masm) {
291 // The stack should look like this: 293 // The stack should look like this:
292 // ... keep1 | dest=42 | keep2 | RF | magic | handler | magic | recursive args | 294 // ... keep1 | dest=42 | keep2 | RF | magic | handler | magic | recursive args |
293 // Check various invariants. 295 // Check various invariants.
294 verify_offsets(); 296 verify_offsets();
988 ShouldNotReachHere(); 990 ShouldNotReachHere();
989 } 991 }
990 BLOCK_COMMENT("} move_return_value"); 992 BLOCK_COMMENT("} move_return_value");
991 } 993 }
992 994
993 #ifdef ASSERT 995 #ifndef PRODUCT
994 #define DESCRIBE_RICOCHET_OFFSET(rf, name) \ 996 #define DESCRIBE_RICOCHET_OFFSET(rf, name) \
995 values.describe(frame_no, (intptr_t *) (((uintptr_t)rf) + MethodHandles::RicochetFrame::name##_offset_in_bytes()), #name) 997 values.describe(frame_no, (intptr_t *) (((uintptr_t)rf) + MethodHandles::RicochetFrame::name##_offset_in_bytes()), #name)
996 998
997 void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) { 999 void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) {
998 address bp = (address) fr->fp(); 1000 address bp = (address) fr->fp();
1019 intptr_t* entry_sp, 1021 intptr_t* entry_sp,
1020 intptr_t* saved_sp, 1022 intptr_t* saved_sp,
1021 intptr_t* saved_bp) { 1023 intptr_t* saved_bp) {
1022 // called as a leaf from native code: do not block the JVM! 1024 // called as a leaf from native code: do not block the JVM!
1023 bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have rcx_mh 1025 bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have rcx_mh
1026
1024 intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset]; 1027 intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
1025 intptr_t* base_sp = last_sp; 1028 intptr_t* base_sp = last_sp;
1026 typedef MethodHandles::RicochetFrame RicochetFrame; 1029 typedef MethodHandles::RicochetFrame RicochetFrame;
1027 RicochetFrame* rfp = (RicochetFrame*)((address)saved_bp - RicochetFrame::sender_link_offset_in_bytes()); 1030 RicochetFrame* rfp = (RicochetFrame*)((address)saved_bp - RicochetFrame::sender_link_offset_in_bytes());
1028 if (Universe::heap()->is_in((address) rfp->saved_args_base())) { 1031 if (Universe::heap()->is_in((address) rfp->saved_args_base())) {
1048 tty->print(" %d: "PTR_FORMAT, i, saved_regs[i]); 1051 tty->print(" %d: "PTR_FORMAT, i, saved_regs[i]);
1049 } 1052 }
1050 tty->cr(); 1053 tty->cr();
1051 if (last_sp != saved_sp && last_sp != NULL) 1054 if (last_sp != saved_sp && last_sp != NULL)
1052 tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp); 1055 tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp);
1053 int stack_dump_count = 16; 1056
1054 if (stack_dump_count < (int)(saved_bp + 2 - saved_sp)) 1057 {
1055 stack_dump_count = (int)(saved_bp + 2 - saved_sp); 1058 // dumping last frame with frame::describe
1056 if (stack_dump_count > 64) stack_dump_count = 48; 1059
1057 for (i = 0; i < stack_dump_count; i += 4) { 1060 JavaThread* p = JavaThread::active();
1058 tty->print_cr(" dump at SP[%d] "PTR_FORMAT": "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT" "PTR_FORMAT, 1061
1059 i, (intptr_t) &entry_sp[i+0], entry_sp[i+0], entry_sp[i+1], entry_sp[i+2], entry_sp[i+3]); 1062 ResourceMark rm;
1063 PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here
1064 FrameValues values;
1065
1066 // Note: We want to allow trace_method_handle from any call site.
1067 // While trace_method_handle creates a frame, it may be entered
1068 // without a PC on the stack top (e.g. not just after a call).
1069 // Walking that frame could lead to failures due to that invalid PC.
1070 // => carefully detect that frame when doing the stack walking
1071
1072 // Current C frame
1073 frame cur_frame = os::current_frame();
1074
1075 // Robust search of trace_calling_frame (independant of inlining).
1076 // Assumes saved_regs comes from a pusha in the trace_calling_frame.
1077 assert(cur_frame.sp() < saved_regs, "registers not saved on stack ?");
1078 frame trace_calling_frame = os::get_sender_for_C_frame(&cur_frame);
1079 while (trace_calling_frame.fp() < saved_regs) {
1080 trace_calling_frame = os::get_sender_for_C_frame(&trace_calling_frame);
1081 }
1082
1083 // safely create a frame and call frame::describe
1084 intptr_t *dump_sp = trace_calling_frame.sender_sp();
1085 intptr_t *dump_fp = trace_calling_frame.link();
1086
1087 bool walkable = has_mh; // whether the traced frame shoud be walkable
1088
1089 if (walkable) {
1090 // The previous definition of walkable may have to be refined
1091 // if new call sites cause the next frame constructor to start
1092 // failing. Alternatively, frame constructors could be
1093 // modified to support the current or future non walkable
1094 // frames (but this is more intrusive and is not considered as
1095 // part of this RFE, which will instead use a simpler output).
1096 frame dump_frame = frame(dump_sp, dump_fp);
1097 dump_frame.describe(values, 1);
1098 } else {
1099 // Stack may not be walkable (invalid PC above FP):
1100 // Add descriptions without building a Java frame to avoid issues
1101 values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>");
1102 values.describe(-1, dump_sp, "sp for #1");
1103 }
1104
1105 // mark saved_sp if seems valid
1106 if (has_mh) {
1107 if ((saved_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (saved_sp < dump_fp)) {
1108 values.describe(-1, saved_sp, "*saved_sp");
1109 }
1110 }
1111
1112 tty->print_cr(" stack layout:");
1113 values.print(p);
1060 } 1114 }
1061 if (has_mh) 1115 if (has_mh)
1062 print_method_handle(mh); 1116 print_method_handle(mh);
1063 } 1117 }
1064 } 1118 }
1084 } 1138 }
1085 1139
1086 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { 1140 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
1087 if (!TraceMethodHandles) return; 1141 if (!TraceMethodHandles) return;
1088 BLOCK_COMMENT("trace_method_handle {"); 1142 BLOCK_COMMENT("trace_method_handle {");
1089 __ push(rax); 1143 __ enter();
1090 __ lea(rax, Address(rsp, wordSize * NOT_LP64(6) LP64_ONLY(14))); // entry_sp __ pusha(); 1144 __ andptr(rsp, -16); // align stack if needed for FPU state
1091 __ pusha(); 1145 __ pusha();
1092 __ mov(rbx, rsp); 1146 __ mov(rbx, rsp); // for retreiving saved_regs
1093 __ enter(); 1147 // Note: saved_regs must be in the entered frame for the
1148 // robust stack walking implemented in trace_method_handle_stub.
1149
1150 // save FP result, valid at some call sites (adapter_opt_return_float, ...)
1151 __ increment(rsp, -2 * wordSize);
1152 if (UseSSE >= 2) {
1153 __ movdbl(Address(rsp, 0), xmm0);
1154 } else if (UseSSE == 1) {
1155 __ movflt(Address(rsp, 0), xmm0);
1156 } else {
1157 __ fst_d(Address(rsp, 0));
1158 }
1159
1094 // incoming state: 1160 // incoming state:
1095 // rcx: method handle 1161 // rcx: method handle
1096 // r13 or rsi: saved sp 1162 // r13 or rsi: saved sp
1097 // To avoid calling convention issues, build a record on the stack and pass the pointer to that instead. 1163 // To avoid calling convention issues, build a record on the stack and pass the pointer to that instead.
1164 // Note: fix the increment below if pushing more arguments
1098 __ push(rbp); // saved_bp 1165 __ push(rbp); // saved_bp
1099 __ push(rsi); // saved_sp 1166 __ push(saved_last_sp_register()); // saved_sp
1100 __ push(rax); // entry_sp 1167 __ push(rbp); // entry_sp (with extra align space)
1101 __ push(rbx); // pusha saved_regs 1168 __ push(rbx); // pusha saved_regs
1102 __ push(rcx); // mh 1169 __ push(rcx); // mh
1103 __ push(rcx); // adaptername 1170 __ push(rcx); // slot for adaptername
1104 __ movptr(Address(rsp, 0), (intptr_t) adaptername); 1171 __ movptr(Address(rsp, 0), (intptr_t) adaptername);
1105 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp); 1172 __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp);
1173 __ increment(rsp, 6 * wordSize); // MethodHandleStubArguments
1174
1175 if (UseSSE >= 2) {
1176 __ movdbl(xmm0, Address(rsp, 0));
1177 } else if (UseSSE == 1) {
1178 __ movflt(xmm0, Address(rsp, 0));
1179 } else {
1180 __ fld_d(Address(rsp, 0));
1181 }
1182 __ increment(rsp, 2 * wordSize);
1183
1184 __ popa();
1106 __ leave(); 1185 __ leave();
1107 __ popa();
1108 __ pop(rax);
1109 BLOCK_COMMENT("} trace_method_handle"); 1186 BLOCK_COMMENT("} trace_method_handle");
1110 } 1187 }
1111 #endif //PRODUCT 1188 #endif //PRODUCT
1112 1189
1113 // which conversion op types are implemented here? 1190 // which conversion op types are implemented here?