Mercurial > hg > truffle
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? |