Mercurial > hg > truffle
comparison src/cpu/sparc/vm/methodHandles_sparc.cpp @ 4970:33df1aeaebbf
Merge with http://hg.openjdk.java.net/hsx/hsx24/hotspot/
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Mon, 27 Feb 2012 13:10:13 +0100 |
parents | 04b9a2566eec 5dbed2f542ff |
children | 18a5539bf19b |
comparison
equal
deleted
inserted
replaced
4703:2cfb7fb2dce7 | 4970:33df1aeaebbf |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
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 |
992 } | 994 } |
993 BLOCK_COMMENT("} move_return_value"); | 995 BLOCK_COMMENT("} move_return_value"); |
994 } | 996 } |
995 | 997 |
996 #ifndef PRODUCT | 998 #ifndef PRODUCT |
999 void MethodHandles::RicochetFrame::describe(const frame* fr, FrameValues& values, int frame_no) { | |
1000 RicochetFrame* rf = new RicochetFrame(*fr); | |
1001 | |
1002 // ricochet slots (kept in registers for sparc) | |
1003 values.describe(frame_no, rf->register_addr(I5_savedSP), err_msg("exact_sender_sp reg for #%d", frame_no)); | |
1004 values.describe(frame_no, rf->register_addr(L5_conversion), err_msg("conversion reg for #%d", frame_no)); | |
1005 values.describe(frame_no, rf->register_addr(L4_saved_args_base), err_msg("saved_args_base reg for #%d", frame_no)); | |
1006 values.describe(frame_no, rf->register_addr(L3_saved_args_layout), err_msg("saved_args_layout reg for #%d", frame_no)); | |
1007 values.describe(frame_no, rf->register_addr(L2_saved_target), err_msg("saved_target reg for #%d", frame_no)); | |
1008 values.describe(frame_no, rf->register_addr(L1_continuation), err_msg("continuation reg for #%d", frame_no)); | |
1009 | |
1010 // relevant ricochet targets (in caller frame) | |
1011 values.describe(-1, rf->saved_args_base(), err_msg("*saved_args_base for #%d", frame_no)); | |
1012 values.describe(-1, (intptr_t *)(STACK_BIAS+(uintptr_t)rf->exact_sender_sp()), err_msg("*exact_sender_sp+STACK_BIAS for #%d", frame_no)); | |
1013 } | |
1014 #endif // ASSERT | |
1015 | |
1016 #ifndef PRODUCT | |
997 extern "C" void print_method_handle(oop mh); | 1017 extern "C" void print_method_handle(oop mh); |
998 void trace_method_handle_stub(const char* adaptername, | 1018 void trace_method_handle_stub(const char* adaptername, |
999 oopDesc* mh, | 1019 oopDesc* mh, |
1000 intptr_t* saved_sp) { | 1020 intptr_t* saved_sp, |
1021 intptr_t* args, | |
1022 intptr_t* tracing_fp) { | |
1001 bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have mh | 1023 bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have mh |
1002 tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp); | 1024 |
1003 if (has_mh) | 1025 tty->print_cr("MH %s mh="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT " args=" INTPTR_FORMAT, adaptername, (intptr_t) mh, saved_sp, args); |
1026 | |
1027 if (Verbose) { | |
1028 // dumping last frame with frame::describe | |
1029 | |
1030 JavaThread* p = JavaThread::active(); | |
1031 | |
1032 ResourceMark rm; | |
1033 PRESERVE_EXCEPTION_MARK; // may not be needed by safer and unexpensive here | |
1034 FrameValues values; | |
1035 | |
1036 // Note: We want to allow trace_method_handle from any call site. | |
1037 // While trace_method_handle creates a frame, it may be entered | |
1038 // without a valid return PC in O7 (e.g. not just after a call). | |
1039 // Walking that frame could lead to failures due to that invalid PC. | |
1040 // => carefully detect that frame when doing the stack walking | |
1041 | |
1042 // walk up to the right frame using the "tracing_fp" argument | |
1043 intptr_t* cur_sp = StubRoutines::Sparc::flush_callers_register_windows_func()(); | |
1044 frame cur_frame(cur_sp, frame::unpatchable, NULL); | |
1045 | |
1046 while (cur_frame.fp() != (intptr_t *)(STACK_BIAS+(uintptr_t)tracing_fp)) { | |
1047 cur_frame = os::get_sender_for_C_frame(&cur_frame); | |
1048 } | |
1049 | |
1050 // safely create a frame and call frame::describe | |
1051 intptr_t *dump_sp = cur_frame.sender_sp(); | |
1052 intptr_t *dump_fp = cur_frame.link(); | |
1053 | |
1054 bool walkable = has_mh; // whether the traced frame shoud be walkable | |
1055 | |
1056 // the sender for cur_frame is the caller of trace_method_handle | |
1057 if (walkable) { | |
1058 // The previous definition of walkable may have to be refined | |
1059 // if new call sites cause the next frame constructor to start | |
1060 // failing. Alternatively, frame constructors could be | |
1061 // modified to support the current or future non walkable | |
1062 // frames (but this is more intrusive and is not considered as | |
1063 // part of this RFE, which will instead use a simpler output). | |
1064 frame dump_frame = frame(dump_sp, | |
1065 cur_frame.sp(), // younger_sp | |
1066 false); // no adaptation | |
1067 dump_frame.describe(values, 1); | |
1068 } else { | |
1069 // Robust dump for frames which cannot be constructed from sp/younger_sp | |
1070 // Add descriptions without building a Java frame to avoid issues | |
1071 values.describe(-1, dump_fp, "fp for #1 <not parsed, cannot trust pc>"); | |
1072 values.describe(-1, dump_sp, "sp"); | |
1073 } | |
1074 | |
1075 bool has_args = has_mh; // whether Gargs is meaningful | |
1076 | |
1077 // mark args, if seems valid (may not be valid for some adapters) | |
1078 if (has_args) { | |
1079 if ((args >= dump_sp) && (args < dump_fp)) { | |
1080 values.describe(-1, args, "*G4_args"); | |
1081 } | |
1082 } | |
1083 | |
1084 // mark saved_sp, if seems valid (may not be valid for some adapters) | |
1085 intptr_t *unbiased_sp = (intptr_t *)(STACK_BIAS+(uintptr_t)saved_sp); | |
1086 if ((unbiased_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (unbiased_sp < dump_fp)) { | |
1087 values.describe(-1, unbiased_sp, "*saved_sp+STACK_BIAS"); | |
1088 } | |
1089 | |
1090 // Note: the unextended_sp may not be correct | |
1091 tty->print_cr(" stack layout:"); | |
1092 values.print(p); | |
1093 } | |
1094 | |
1095 if (has_mh) { | |
1004 print_method_handle(mh); | 1096 print_method_handle(mh); |
1005 } | 1097 } |
1098 } | |
1099 | |
1006 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { | 1100 void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { |
1007 if (!TraceMethodHandles) return; | 1101 if (!TraceMethodHandles) return; |
1008 BLOCK_COMMENT("trace_method_handle {"); | 1102 BLOCK_COMMENT("trace_method_handle {"); |
1009 // save: Gargs, O5_savedSP | 1103 // save: Gargs, O5_savedSP |
1010 __ save_frame(16); | 1104 __ save_frame(16); // need space for saving required FPU state |
1105 | |
1011 __ set((intptr_t) adaptername, O0); | 1106 __ set((intptr_t) adaptername, O0); |
1012 __ mov(G3_method_handle, O1); | 1107 __ mov(G3_method_handle, O1); |
1013 __ mov(I5_savedSP, O2); | 1108 __ mov(I5_savedSP, O2); |
1109 __ mov(Gargs, O3); | |
1110 __ mov(I6, O4); // frame identifier for safe stack walking | |
1111 | |
1112 // Save scratched registers that might be needed. Robustness is more | |
1113 // important than optimizing the saves for this debug only code. | |
1114 | |
1115 // save FP result, valid at some call sites (adapter_opt_return_float, ...) | |
1116 Address d_save(FP, -sizeof(jdouble) + STACK_BIAS); | |
1117 __ stf(FloatRegisterImpl::D, Ftos_d, d_save); | |
1118 // Safely save all globals but G2 (handled by call_VM_leaf) and G7 | |
1119 // (OS reserved). | |
1014 __ mov(G3_method_handle, L3); | 1120 __ mov(G3_method_handle, L3); |
1015 __ mov(Gargs, L4); | 1121 __ mov(Gargs, L4); |
1016 __ mov(G5_method_type, L5); | 1122 __ mov(G5_method_type, L5); |
1017 __ call_VM_leaf(L7, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); | 1123 __ mov(G6, L6); |
1124 __ mov(G1, L1); | |
1125 | |
1126 __ call_VM_leaf(L2 /* for G2 */, CAST_FROM_FN_PTR(address, trace_method_handle_stub)); | |
1018 | 1127 |
1019 __ mov(L3, G3_method_handle); | 1128 __ mov(L3, G3_method_handle); |
1020 __ mov(L4, Gargs); | 1129 __ mov(L4, Gargs); |
1021 __ mov(L5, G5_method_type); | 1130 __ mov(L5, G5_method_type); |
1131 __ mov(L6, G6); | |
1132 __ mov(L1, G1); | |
1133 __ ldf(FloatRegisterImpl::D, d_save, Ftos_d); | |
1134 | |
1022 __ restore(); | 1135 __ restore(); |
1023 BLOCK_COMMENT("} trace_method_handle"); | 1136 BLOCK_COMMENT("} trace_method_handle"); |
1024 } | 1137 } |
1025 #endif // PRODUCT | 1138 #endif // PRODUCT |
1026 | 1139 |
1036 |(1<<java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS) | 1149 |(1<<java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS) |
1037 |(1<<java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS) | 1150 |(1<<java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS) |
1038 |(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS) | 1151 |(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS) |
1039 // OP_COLLECT_ARGS is below... | 1152 // OP_COLLECT_ARGS is below... |
1040 |(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) | 1153 |(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) |
1041 |(!UseRicochetFrames ? 0 : | 1154 |( |
1042 java_lang_invoke_MethodTypeForm::vmlayout_offset_in_bytes() <= 0 ? 0 : | 1155 java_lang_invoke_MethodTypeForm::vmlayout_offset_in_bytes() <= 0 ? 0 : |
1043 ((1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF) | 1156 ((1<<java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF) |
1044 |(1<<java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS) | 1157 |(1<<java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS) |
1045 |(1<<java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS) | 1158 |(1<<java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS) |
1046 ) | 1159 ) |
1089 | 1202 |
1090 Address G3_amh_vmargslot( G3_method_handle, java_lang_invoke_AdapterMethodHandle::vmargslot_offset_in_bytes()); | 1203 Address G3_amh_vmargslot( G3_method_handle, java_lang_invoke_AdapterMethodHandle::vmargslot_offset_in_bytes()); |
1091 Address G3_amh_argument ( G3_method_handle, java_lang_invoke_AdapterMethodHandle::argument_offset_in_bytes()); | 1204 Address G3_amh_argument ( G3_method_handle, java_lang_invoke_AdapterMethodHandle::argument_offset_in_bytes()); |
1092 Address G3_amh_conversion(G3_method_handle, java_lang_invoke_AdapterMethodHandle::conversion_offset_in_bytes()); | 1205 Address G3_amh_conversion(G3_method_handle, java_lang_invoke_AdapterMethodHandle::conversion_offset_in_bytes()); |
1093 | 1206 |
1094 const int java_mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes(); | 1207 const int java_mirror_offset = in_bytes(Klass::java_mirror_offset()); |
1095 | 1208 |
1096 if (have_entry(ek)) { | 1209 if (have_entry(ek)) { |
1097 __ nop(); // empty stubs make SG sick | 1210 __ nop(); // empty stubs make SG sick |
1098 return; | 1211 return; |
1099 } | 1212 } |
1241 } else { | 1354 } else { |
1242 Address prim_value_addr(O1_scratch, java_lang_boxing_object::value_offset_in_bytes(arg_type)); | 1355 Address prim_value_addr(O1_scratch, java_lang_boxing_object::value_offset_in_bytes(arg_type)); |
1243 move_typed_arg(_masm, arg_type, false, | 1356 move_typed_arg(_masm, arg_type, false, |
1244 prim_value_addr, | 1357 prim_value_addr, |
1245 Address(O0_argslot, 0), | 1358 Address(O0_argslot, 0), |
1246 O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) | 1359 O2_scratch); // must be an even register for !_LP64 long moves (uses O2/O3) |
1247 } | 1360 } |
1248 | 1361 |
1249 if (direct_to_method) { | 1362 if (direct_to_method) { |
1250 __ load_heap_oop(G3_mh_vmtarget, G5_method); // target is a methodOop | 1363 __ load_heap_oop(G3_mh_vmtarget, G5_method); // target is a methodOop |
1251 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); | 1364 jump_from_method_handle(_masm, G5_method, O1_scratch, O2_scratch); |