hotspot/src/cpu/x86/vm/methodHandles_x86.cpp
changeset 11571 23f825a42a85
parent 11565 713a0398ca58
child 11638 68657fd5d7b4
equal deleted inserted replaced
11570:25f3e9348905 11571:23f825a42a85
   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?