src/cpu/x86/vm/methodHandles_x86.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 7141329 Sdiff src/cpu/x86/vm

src/cpu/x86/vm/methodHandles_x86.cpp

Print this page




1001     RicochetFrame* rf = (RicochetFrame*)(bp - sender_link_offset_in_bytes());
1002 
1003     // ricochet slots
1004     DESCRIBE_RICOCHET_OFFSET(rf, exact_sender_sp);
1005     DESCRIBE_RICOCHET_OFFSET(rf, conversion);
1006     DESCRIBE_RICOCHET_OFFSET(rf, saved_args_base);
1007     DESCRIBE_RICOCHET_OFFSET(rf, saved_args_layout);
1008     DESCRIBE_RICOCHET_OFFSET(rf, saved_target);
1009     DESCRIBE_RICOCHET_OFFSET(rf, continuation);
1010 
1011     // relevant ricochet targets (in caller frame)
1012     values.describe(-1, rf->saved_args_base(),  err_msg("*saved_args_base for #%d", frame_no));
1013 }
1014 #endif // ASSERT
1015 
1016 #ifndef PRODUCT
1017 extern "C" void print_method_handle(oop mh);
1018 void trace_method_handle_stub(const char* adaptername,
1019                               oop mh,
1020                               intptr_t* saved_regs,
1021                               intptr_t* entry_sp,
1022                               intptr_t* saved_sp,
1023                               intptr_t* saved_bp) {
1024   // called as a leaf from native code: do not block the JVM!
1025   bool has_mh = (strstr(adaptername, "return/") == NULL);  // return adapters don't have rcx_mh


1026 
1027   intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset];
1028   intptr_t* base_sp = last_sp;
1029   typedef MethodHandles::RicochetFrame RicochetFrame;
1030   RicochetFrame* rfp = (RicochetFrame*)((address)saved_bp - RicochetFrame::sender_link_offset_in_bytes());
1031   if (Universe::heap()->is_in((address) rfp->saved_args_base())) {
1032     // Probably an interpreter frame.
1033     base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset];
1034   }
1035   intptr_t    mh_reg = (intptr_t)mh;
1036   const char* mh_reg_name = "rcx_mh";
1037   if (!has_mh)  mh_reg_name = "rcx";
1038   tty->print_cr("MH %s %s="PTR_FORMAT" sp=("PTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="PTR_FORMAT,
1039                 adaptername, mh_reg_name, mh_reg,
1040                 (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp);
1041   if (Verbose) {
1042     tty->print(" reg dump: ");
1043     int saved_regs_count = (entry_sp-1) - saved_regs;
1044     // 32 bit: rdi rsi rbp rsp; rbx rdx rcx (*) rax
1045     int i;
1046     for (i = 0; i <= saved_regs_count; i++) {
1047       if (i > 0 && i % 4 == 0 && i != saved_regs_count) {

1048         tty->cr();
1049         tty->print("   + dump: ");

1050       }
1051       tty->print(" %d: "PTR_FORMAT, i, saved_regs[i]);
1052     }
1053     tty->cr();
1054     if (last_sp != saved_sp && last_sp != NULL)
1055       tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp);
1056 
1057     {
1058      // dumping last frame with frame::describe
1059 
1060       JavaThread* p = JavaThread::active();
1061 
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).


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);
1114     }
1115     if (has_mh)
1116       print_method_handle(mh);
1117   }
1118 }
1119 
1120 // The stub wraps the arguments in a struct on the stack to avoid
1121 // dealing with the different calling conventions for passing 6
1122 // arguments.
1123 struct MethodHandleStubArguments {
1124   const char* adaptername;
1125   oopDesc* mh;
1126   intptr_t* saved_regs;
1127   intptr_t* entry_sp;
1128   intptr_t* saved_sp;
1129   intptr_t* saved_bp;
1130 };
1131 void trace_method_handle_stub_wrapper(MethodHandleStubArguments* args) {
1132   trace_method_handle_stub(args->adaptername,
1133                            args->mh,
1134                            args->saved_regs,
1135                            args->entry_sp,
1136                            args->saved_sp,
1137                            args->saved_bp);
1138 }
1139 
1140 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
1141   if (!TraceMethodHandles)  return;
1142   BLOCK_COMMENT("trace_method_handle {");
1143   __ enter();
1144   __ andptr(rsp, -16); // align stack if needed for FPU state
1145   __ pusha();
1146   __ mov(rbx, rsp); // for retreiving saved_regs
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 
1160   // incoming state:
1161   // rcx: method handle
1162   // r13 or rsi: saved sp
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
1165   __ push(rbp);               // saved_bp
1166   __ push(saved_last_sp_register()); // saved_sp
1167   __ push(rbp);               // entry_sp (with extra align space)
1168   __ push(rbx);               // pusha saved_regs
1169   __ push(rcx);               // mh
1170   __ push(rcx);               // slot for adaptername
1171   __ movptr(Address(rsp, 0), (intptr_t) adaptername);
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();
1185   __ leave();
1186   BLOCK_COMMENT("} trace_method_handle");
1187 }
1188 #endif //PRODUCT
1189 
1190 // which conversion op types are implemented here?
1191 int MethodHandles::adapter_conversion_ops_supported_mask() {
1192   return ((1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY)
1193          |(1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW)




1001     RicochetFrame* rf = (RicochetFrame*)(bp - sender_link_offset_in_bytes());
1002 
1003     // ricochet slots
1004     DESCRIBE_RICOCHET_OFFSET(rf, exact_sender_sp);
1005     DESCRIBE_RICOCHET_OFFSET(rf, conversion);
1006     DESCRIBE_RICOCHET_OFFSET(rf, saved_args_base);
1007     DESCRIBE_RICOCHET_OFFSET(rf, saved_args_layout);
1008     DESCRIBE_RICOCHET_OFFSET(rf, saved_target);
1009     DESCRIBE_RICOCHET_OFFSET(rf, continuation);
1010 
1011     // relevant ricochet targets (in caller frame)
1012     values.describe(-1, rf->saved_args_base(),  err_msg("*saved_args_base for #%d", frame_no));
1013 }
1014 #endif // ASSERT
1015 
1016 #ifndef PRODUCT
1017 extern "C" void print_method_handle(oop mh);
1018 void trace_method_handle_stub(const char* adaptername,
1019                               oop mh,
1020                               intptr_t* saved_regs,
1021                               intptr_t* entry_sp) {


1022   // 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
1024   const char* mh_reg_name = has_mh ? "rcx_mh" : "rcx";
1025   tty->print_cr("MH %s %s="PTR_FORMAT" sp="PTR_FORMAT, adaptername, mh_reg_name, mh, entry_sp);
1026 














1027   if (Verbose) {
1028     tty->print_cr("Registers:");
1029     const int saved_regs_count = RegisterImpl::number_of_registers;
1030     for (int i = 0; i < saved_regs_count; i++) {
1031       Register r = as_Register(i);
1032       // The registers are stored in reverse order on the stack (by pusha).
1033       tty->print("%3s=" PTR_FORMAT, r->name(), saved_regs[((saved_regs_count - 1) - i)]);
1034       if ((i + 1) % 4 == 0) {
1035         tty->cr();
1036       } else {
1037         tty->print(", ");
1038       }

1039     }
1040     tty->cr();


1041 
1042     {
1043      // dumping last frame with frame::describe
1044 
1045       JavaThread* p = JavaThread::active();
1046 
1047       ResourceMark rm;
1048       PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here
1049       FrameValues values;
1050 
1051       // Note: We want to allow trace_method_handle from any call site.
1052       // While trace_method_handle creates a frame, it may be entered
1053       // without a PC on the stack top (e.g. not just after a call).
1054       // Walking that frame could lead to failures due to that invalid PC.
1055       // => carefully detect that frame when doing the stack walking
1056 
1057       // Current C frame
1058       frame cur_frame = os::current_frame();
1059 
1060       // Robust search of trace_calling_frame (independant of inlining).


1070       intptr_t *dump_fp = trace_calling_frame.link();
1071 
1072       bool walkable = has_mh; // whether the traced frame shoud be walkable
1073 
1074       if (walkable) {
1075         // The previous definition of walkable may have to be refined
1076         // if new call sites cause the next frame constructor to start
1077         // failing. Alternatively, frame constructors could be
1078         // modified to support the current or future non walkable
1079         // frames (but this is more intrusive and is not considered as
1080         // part of this RFE, which will instead use a simpler output).
1081         frame dump_frame = frame(dump_sp, dump_fp);
1082         dump_frame.describe(values, 1);
1083       } else {
1084         // Stack may not be walkable (invalid PC above FP):
1085         // Add descriptions without building a Java frame to avoid issues
1086         values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>");
1087         values.describe(-1, dump_sp, "sp for #1");
1088       }
1089 
1090       tty->print_cr("Stack layout:");







1091       values.print(p);
1092     }
1093     if (has_mh)
1094       print_method_handle(mh);
1095   }
1096 }
1097 
1098 // The stub wraps the arguments in a struct on the stack to avoid
1099 // dealing with the different calling conventions for passing 6
1100 // arguments.
1101 struct MethodHandleStubArguments {
1102   const char* adaptername;
1103   oopDesc* mh;
1104   intptr_t* saved_regs;
1105   intptr_t* entry_sp;


1106 };
1107 void trace_method_handle_stub_wrapper(MethodHandleStubArguments* args) {
1108   trace_method_handle_stub(args->adaptername,
1109                            args->mh,
1110                            args->saved_regs,
1111                            args->entry_sp);


1112 }
1113 
1114 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) {
1115   if (!TraceMethodHandles)  return;
1116   BLOCK_COMMENT("trace_method_handle {");
1117   __ enter();
1118   __ andptr(rsp, -16); // align stack if needed for FPU state
1119   __ pusha();
1120   __ mov(rbx, rsp); // for retreiving saved_regs
1121   // Note: saved_regs must be in the entered frame for the
1122   // robust stack walking implemented in trace_method_handle_stub.
1123 
1124   // save FP result, valid at some call sites (adapter_opt_return_float, ...)
1125   __ increment(rsp, -2 * wordSize);
1126   if  (UseSSE >= 2) {
1127     __ movdbl(Address(rsp, 0), xmm0);
1128   } else if (UseSSE == 1) {
1129     __ movflt(Address(rsp, 0), xmm0);
1130   } else {
1131     __ fst_d(Address(rsp, 0));
1132   }
1133 
1134   // Incoming state:
1135   // rcx: method handle
1136   //
1137   // To avoid calling convention issues, build a record on the stack
1138   // and pass the pointer to that instead.


1139   __ push(rbp);               // entry_sp (with extra align space)
1140   __ push(rbx);               // pusha saved_regs
1141   __ push(rcx);               // mh
1142   __ push(rcx);               // slot for adaptername
1143   __ movptr(Address(rsp, 0), (intptr_t) adaptername);
1144   __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp);
1145   __ increment(rsp, sizeof(MethodHandleStubArguments));
1146 
1147   if  (UseSSE >= 2) {
1148     __ movdbl(xmm0, Address(rsp, 0));
1149   } else if (UseSSE == 1) {
1150     __ movflt(xmm0, Address(rsp, 0));
1151   } else {
1152     __ fld_d(Address(rsp, 0));
1153   }
1154   __ increment(rsp, 2 * wordSize);
1155 
1156   __ popa();
1157   __ leave();
1158   BLOCK_COMMENT("} trace_method_handle");
1159 }
1160 #endif //PRODUCT
1161 
1162 // which conversion op types are implemented here?
1163 int MethodHandles::adapter_conversion_ops_supported_mask() {
1164   return ((1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY)
1165          |(1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW)


src/cpu/x86/vm/methodHandles_x86.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File