< prev index next >

src/hotspot/cpu/arm/sharedRuntime_arm.cpp

Print this page

 752                                                 VMRegPair* in_regs,
 753                                                 BasicType ret_type) {
 754   if (method->is_method_handle_intrinsic()) {
 755     vmIntrinsics::ID iid = method->intrinsic_id();
 756     intptr_t start = (intptr_t)__ pc();
 757     int vep_offset = ((intptr_t)__ pc()) - start;
 758     gen_special_dispatch(masm,
 759                          method,
 760                          in_sig_bt,
 761                          in_regs);
 762     int frame_complete = ((intptr_t)__ pc()) - start;  // not complete, period
 763     __ flush();
 764     int stack_slots = SharedRuntime::out_preserve_stack_slots();  // no out slots at all, actually
 765     return nmethod::new_native_nmethod(method,
 766                                        compile_id,
 767                                        masm->code(),
 768                                        vep_offset,
 769                                        frame_complete,
 770                                        stack_slots / VMRegImpl::slots_per_word,
 771                                        in_ByteSize(-1),
 772                                        in_ByteSize(-1),
 773                                        (OopMapSet*)NULL);
 774   }
 775   // Arguments for JNI method include JNIEnv and Class if static
 776 
 777   // Usage of Rtemp should be OK since scratched by native call
 778 
 779   bool method_is_static = method->is_static();
 780 
 781   const int total_in_args = method->size_of_parameters();
 782   int total_c_args = total_in_args + (method_is_static ? 2 : 1);
 783 
 784   BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args);
 785   VMRegPair* out_regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args);
 786 
 787   int argc = 0;
 788   out_sig_bt[argc++] = T_ADDRESS;
 789   if (method_is_static) {
 790     out_sig_bt[argc++] = T_OBJECT;
 791   }
 792 
 793   int i;
 794   for (i = 0; i < total_in_args; i++) {
 795     out_sig_bt[argc++] = in_sig_bt[i];
 796   }
 797 
 798   int out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args);
 799   int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots;
 800   // Since object arguments need to be wrapped, we must preserve space
 801   // for those object arguments which come in registers (GPR_PARAMS maximum)
 802   // plus one more slot for Klass handle (for static methods)
 803   int oop_handle_offset = stack_slots;
 804   stack_slots += (GPR_PARAMS + 1) * VMRegImpl::slots_per_word;
 805 
 806   // Plus a lock if needed
 807   int lock_slot_offset = 0;
 808   if (method->is_synchronized()) {
 809     lock_slot_offset = stack_slots;
 810     assert(sizeof(BasicLock) == wordSize, "adjust this code");
 811     stack_slots += VMRegImpl::slots_per_word;
 812   }
 813 
 814   // Space to save return address and FP
 815   stack_slots += 2 * VMRegImpl::slots_per_word;
 816 
 817   // Calculate the final stack size taking account of alignment
 818   stack_slots = align_up(stack_slots, StackAlignmentInBytes / VMRegImpl::stack_slot_size);
 819   int stack_size = stack_slots * VMRegImpl::stack_slot_size;
 820   int lock_slot_fp_offset = stack_size - 2 * wordSize -
 821     lock_slot_offset * VMRegImpl::stack_slot_size;
 822 
 823   // Unverified entry point
 824   address start = __ pc();
 825 
 826   // Inline cache check, same as in C1_MacroAssembler::inline_cache_check()
 827   const Register receiver = R0; // see receiverOpr()
 828   __ load_klass(Rtemp, receiver);
 829   __ cmp(Rtemp, Ricklass);
 830   Label verified;
 831 
 832   __ b(verified, eq); // jump over alignment no-ops too
 833   __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, Rtemp);
 834   __ align(CodeEntryAlignment);
 835 
 836   // Verified entry point
 837   __ bind(verified);
 838   int vep_offset = __ pc() - start;
 839 
 840 
 841   if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {

1132   if (log_is_enabled(Trace, redefine, class, obsolete)) {
1133     __ save_caller_save_registers();
1134     __ mov(R0, Rthread);
1135     __ mov_metadata(R1, method());
1136     __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), R0, R1);
1137     __ restore_caller_save_registers();
1138   }
1139 
1140   const Register sync_handle = R5;
1141   const Register sync_obj    = R6;
1142   const Register disp_hdr    = altFP_7_11;
1143   const Register tmp         = R8;
1144 
1145   Label slow_lock, lock_done, fast_lock;
1146   if (method->is_synchronized()) {
1147     // The first argument is a handle to sync object (a class or an instance)
1148     __ ldr(sync_obj, Address(R1));
1149     // Remember the handle for the unlocking code
1150     __ mov(sync_handle, R1);
1151 
1152     const Register mark = tmp;
1153     // On MP platforms the next load could return a 'stale' value if the memory location has been modified by another thread.
1154     // That would be acceptable as either CAS or slow case path is taken in that case
1155 
1156     __ ldr(mark, Address(sync_obj, oopDesc::mark_offset_in_bytes()));
1157     __ sub(disp_hdr, FP, lock_slot_fp_offset);
1158     __ tst(mark, markWord::unlocked_value);
1159     __ b(fast_lock, ne);
1160 
1161     // Check for recursive lock
1162     // See comments in InterpreterMacroAssembler::lock_object for
1163     // explanations on the fast recursive locking check.
1164     // Check independently the low bits and the distance to SP
1165     // -1- test low 2 bits
1166     __ movs(Rtemp, AsmOperand(mark, lsl, 30));
1167     // -2- test (hdr - SP) if the low two bits are 0
1168     __ sub(Rtemp, mark, SP, eq);
1169     __ movs(Rtemp, AsmOperand(Rtemp, lsr, exact_log2(os::vm_page_size())), eq);
1170     // If still 'eq' then recursive locking OK
1171     // set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8267042)
1172     __ str(Rtemp, Address(disp_hdr, BasicLock::displaced_header_offset_in_bytes()));
1173     __ b(lock_done, eq);
1174     __ b(slow_lock);
1175 
1176     __ bind(fast_lock);
1177     __ str(mark, Address(disp_hdr, BasicLock::displaced_header_offset_in_bytes()));
1178 
1179     __ cas_for_lock_acquire(mark, disp_hdr, sync_obj, Rtemp, slow_lock);
1180 
1181     __ bind(lock_done);
1182   }
1183 
1184   // Get JNIEnv*
1185   __ add(c_rarg0, Rthread, in_bytes(JavaThread::jni_environment_offset()));
1186 
1187   // Perform thread state transition
1188   __ mov(Rtemp, _thread_in_native);
1189   __ str(Rtemp, Address(Rthread, JavaThread::thread_state_offset()));
1190 
1191   // Finally, call the native method
1192   __ call(method->native_function());
1193 
1194   // Set FPSCR/FPCR to a known state
1195   if (AlwaysRestoreFPU) {
1196     __ restore_default_fp_mode();
1197   }
1198 
1199   // Ensure a Boolean result is mapped to 0..1
1200   if (ret_type == T_BOOLEAN) {

1212   __ safepoint_poll(R2, call_safepoint_runtime);
1213   __ ldr_u32(R3, Address(Rthread, JavaThread::suspend_flags_offset()));
1214   __ cmp(R3, 0);
1215   __ b(call_safepoint_runtime, ne);
1216 
1217   __ bind(return_to_java);
1218 
1219   // Perform thread state transition and reguard stack yellow pages if needed
1220   Label reguard, reguard_done;
1221   __ mov(Rtemp, _thread_in_Java);
1222   __ ldr_s32(R2, Address(Rthread, JavaThread::stack_guard_state_offset()));
1223   __ str_32(Rtemp, Address(Rthread, JavaThread::thread_state_offset()));
1224 
1225   __ cmp(R2, StackOverflow::stack_guard_yellow_reserved_disabled);
1226   __ b(reguard, eq);
1227   __ bind(reguard_done);
1228 
1229   Label slow_unlock, unlock_done;
1230   if (method->is_synchronized()) {
1231     __ ldr(sync_obj, Address(sync_handle));
1232 
1233     // See C1_MacroAssembler::unlock_object() for more comments
1234     __ ldr(R2, Address(disp_hdr, BasicLock::displaced_header_offset_in_bytes()));
1235     __ cbz(R2, unlock_done);
1236 
1237     __ cas_for_lock_release(disp_hdr, R2, sync_obj, Rtemp, slow_unlock);
1238 
1239     __ bind(unlock_done);
1240   }
1241 
1242   // Set last java frame and handle block to zero
1243   __ ldr(LR, Address(Rthread, JavaThread::active_handles_offset()));
1244   __ reset_last_Java_frame(Rtemp); // sets Rtemp to 0 on 32-bit ARM
1245 
1246   __ str_32(Rtemp, Address(LR, JNIHandleBlock::top_offset_in_bytes()));
1247   if (CheckJNICalls) {
1248     __ str(__ zero_register(Rtemp), Address(Rthread, JavaThread::pending_jni_exception_check_fn_offset()));
1249   }
1250 
1251   // Unbox oop result, e.g. JNIHandles::resolve value in R0.
1252   if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
1253     __ resolve_jobject(R0,      // value
1254                        Rtemp,   // tmp1
1255                        R1_tmp); // tmp2
1256   }
1257 
1258   // Any exception pending?

1274   __ mov(R0, Rthread);
1275   __ call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans));
1276   pop_result_registers(masm, ret_type);
1277   __ b(return_to_java);
1278 
1279   // Reguard stack pages. Save native results around a call to C runtime.
1280   __ bind(reguard);
1281   push_result_registers(masm, ret_type);
1282   __ call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages));
1283   pop_result_registers(masm, ret_type);
1284   __ b(reguard_done);
1285 
1286   if (method->is_synchronized()) {
1287     // Locking slow case
1288     __ bind(slow_lock);
1289 
1290     push_param_registers(masm, fp_regs_in_arguments);
1291 
1292     // last_Java_frame is already set, so do call_VM manually; no exception can occur
1293     __ mov(R0, sync_obj);
1294     __ mov(R1, disp_hdr);
1295     __ mov(R2, Rthread);
1296     __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C));
1297 
1298     pop_param_registers(masm, fp_regs_in_arguments);
1299 
1300     __ b(lock_done);
1301 
1302     // Unlocking slow case
1303     __ bind(slow_unlock);
1304 
1305     push_result_registers(masm, ret_type);
1306 
1307     // Clear pending exception before reentering VM.
1308     // Can store the oop in register since it is a leaf call.
1309     assert_different_registers(Rtmp_save1, sync_obj, disp_hdr);
1310     __ ldr(Rtmp_save1, Address(Rthread, Thread::pending_exception_offset()));
1311     Register zero = __ zero_register(Rtemp);
1312     __ str(zero, Address(Rthread, Thread::pending_exception_offset()));
1313     __ mov(R0, sync_obj);
1314     __ mov(R1, disp_hdr);
1315     __ mov(R2, Rthread);
1316     __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C));
1317     __ str(Rtmp_save1, Address(Rthread, Thread::pending_exception_offset()));
1318 
1319     pop_result_registers(masm, ret_type);
1320 
1321     __ b(unlock_done);
1322   }
1323 
1324   __ flush();
1325   return nmethod::new_native_nmethod(method,
1326                                      compile_id,
1327                                      masm->code(),
1328                                      vep_offset,
1329                                      frame_complete,
1330                                      stack_slots / VMRegImpl::slots_per_word,
1331                                      in_ByteSize(method_is_static ? klass_offset : receiver_offset),
1332                                      in_ByteSize(lock_slot_offset * VMRegImpl::stack_slot_size),
1333                                      oop_maps);
1334 }
1335 
1336 // this function returns the adjust size (in number of words) to a c2i adapter
1337 // activation for use during deoptimization
1338 int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) {
1339   int extra_locals_size = (callee_locals - callee_parameters) * Interpreter::stackElementWords;
1340   return extra_locals_size;
1341 }
1342 
1343 
1344 // Number of stack slots between incoming argument block and the start of
1345 // a new frame.  The PROLOG must add this many slots to the stack.  The
1346 // EPILOG must remove this many slots.
1347 // FP + LR
1348 uint SharedRuntime::in_preserve_stack_slots() {
1349   return 2 * VMRegImpl::slots_per_word;
1350 }
1351 
1352 uint SharedRuntime::out_preserve_stack_slots() {

 752                                                 VMRegPair* in_regs,
 753                                                 BasicType ret_type) {
 754   if (method->is_method_handle_intrinsic()) {
 755     vmIntrinsics::ID iid = method->intrinsic_id();
 756     intptr_t start = (intptr_t)__ pc();
 757     int vep_offset = ((intptr_t)__ pc()) - start;
 758     gen_special_dispatch(masm,
 759                          method,
 760                          in_sig_bt,
 761                          in_regs);
 762     int frame_complete = ((intptr_t)__ pc()) - start;  // not complete, period
 763     __ flush();
 764     int stack_slots = SharedRuntime::out_preserve_stack_slots();  // no out slots at all, actually
 765     return nmethod::new_native_nmethod(method,
 766                                        compile_id,
 767                                        masm->code(),
 768                                        vep_offset,
 769                                        frame_complete,
 770                                        stack_slots / VMRegImpl::slots_per_word,
 771                                        in_ByteSize(-1),

 772                                        (OopMapSet*)NULL);
 773   }
 774   // Arguments for JNI method include JNIEnv and Class if static
 775 
 776   // Usage of Rtemp should be OK since scratched by native call
 777 
 778   bool method_is_static = method->is_static();
 779 
 780   const int total_in_args = method->size_of_parameters();
 781   int total_c_args = total_in_args + (method_is_static ? 2 : 1);
 782 
 783   BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args);
 784   VMRegPair* out_regs   = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args);
 785 
 786   int argc = 0;
 787   out_sig_bt[argc++] = T_ADDRESS;
 788   if (method_is_static) {
 789     out_sig_bt[argc++] = T_OBJECT;
 790   }
 791 
 792   int i;
 793   for (i = 0; i < total_in_args; i++) {
 794     out_sig_bt[argc++] = in_sig_bt[i];
 795   }
 796 
 797   int out_arg_slots = c_calling_convention(out_sig_bt, out_regs, NULL, total_c_args);
 798   int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots;
 799   // Since object arguments need to be wrapped, we must preserve space
 800   // for those object arguments which come in registers (GPR_PARAMS maximum)
 801   // plus one more slot for Klass handle (for static methods)
 802   int oop_handle_offset = stack_slots;
 803   stack_slots += (GPR_PARAMS + 1) * VMRegImpl::slots_per_word;
 804 








 805   // Space to save return address and FP
 806   stack_slots += 2 * VMRegImpl::slots_per_word;
 807 
 808   // Calculate the final stack size taking account of alignment
 809   stack_slots = align_up(stack_slots, StackAlignmentInBytes / VMRegImpl::stack_slot_size);
 810   int stack_size = stack_slots * VMRegImpl::stack_slot_size;


 811 
 812   // Unverified entry point
 813   address start = __ pc();
 814 
 815   // Inline cache check, same as in C1_MacroAssembler::inline_cache_check()
 816   const Register receiver = R0; // see receiverOpr()
 817   __ load_klass(Rtemp, receiver);
 818   __ cmp(Rtemp, Ricklass);
 819   Label verified;
 820 
 821   __ b(verified, eq); // jump over alignment no-ops too
 822   __ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, Rtemp);
 823   __ align(CodeEntryAlignment);
 824 
 825   // Verified entry point
 826   __ bind(verified);
 827   int vep_offset = __ pc() - start;
 828 
 829 
 830   if ((InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) || (method->intrinsic_id() == vmIntrinsics::_identityHashCode)) {

1121   if (log_is_enabled(Trace, redefine, class, obsolete)) {
1122     __ save_caller_save_registers();
1123     __ mov(R0, Rthread);
1124     __ mov_metadata(R1, method());
1125     __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::rc_trace_method_entry), R0, R1);
1126     __ restore_caller_save_registers();
1127   }
1128 
1129   const Register sync_handle = R5;
1130   const Register sync_obj    = R6;
1131   const Register disp_hdr    = altFP_7_11;
1132   const Register tmp         = R8;
1133 
1134   Label slow_lock, lock_done, fast_lock;
1135   if (method->is_synchronized()) {
1136     // The first argument is a handle to sync object (a class or an instance)
1137     __ ldr(sync_obj, Address(R1));
1138     // Remember the handle for the unlocking code
1139     __ mov(sync_handle, R1);
1140 
1141     // TODO: Implement fast-locking.





















1142     __ b(slow_lock);






1143     __ bind(lock_done);
1144   }
1145 
1146   // Get JNIEnv*
1147   __ add(c_rarg0, Rthread, in_bytes(JavaThread::jni_environment_offset()));
1148 
1149   // Perform thread state transition
1150   __ mov(Rtemp, _thread_in_native);
1151   __ str(Rtemp, Address(Rthread, JavaThread::thread_state_offset()));
1152 
1153   // Finally, call the native method
1154   __ call(method->native_function());
1155 
1156   // Set FPSCR/FPCR to a known state
1157   if (AlwaysRestoreFPU) {
1158     __ restore_default_fp_mode();
1159   }
1160 
1161   // Ensure a Boolean result is mapped to 0..1
1162   if (ret_type == T_BOOLEAN) {

1174   __ safepoint_poll(R2, call_safepoint_runtime);
1175   __ ldr_u32(R3, Address(Rthread, JavaThread::suspend_flags_offset()));
1176   __ cmp(R3, 0);
1177   __ b(call_safepoint_runtime, ne);
1178 
1179   __ bind(return_to_java);
1180 
1181   // Perform thread state transition and reguard stack yellow pages if needed
1182   Label reguard, reguard_done;
1183   __ mov(Rtemp, _thread_in_Java);
1184   __ ldr_s32(R2, Address(Rthread, JavaThread::stack_guard_state_offset()));
1185   __ str_32(Rtemp, Address(Rthread, JavaThread::thread_state_offset()));
1186 
1187   __ cmp(R2, StackOverflow::stack_guard_yellow_reserved_disabled);
1188   __ b(reguard, eq);
1189   __ bind(reguard_done);
1190 
1191   Label slow_unlock, unlock_done;
1192   if (method->is_synchronized()) {
1193     __ ldr(sync_obj, Address(sync_handle));
1194     // TODO: Implement fast-unlocking.
1195     __ b(slow_unlock);





1196     __ bind(unlock_done);
1197   }
1198 
1199   // Set last java frame and handle block to zero
1200   __ ldr(LR, Address(Rthread, JavaThread::active_handles_offset()));
1201   __ reset_last_Java_frame(Rtemp); // sets Rtemp to 0 on 32-bit ARM
1202 
1203   __ str_32(Rtemp, Address(LR, JNIHandleBlock::top_offset_in_bytes()));
1204   if (CheckJNICalls) {
1205     __ str(__ zero_register(Rtemp), Address(Rthread, JavaThread::pending_jni_exception_check_fn_offset()));
1206   }
1207 
1208   // Unbox oop result, e.g. JNIHandles::resolve value in R0.
1209   if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
1210     __ resolve_jobject(R0,      // value
1211                        Rtemp,   // tmp1
1212                        R1_tmp); // tmp2
1213   }
1214 
1215   // Any exception pending?

1231   __ mov(R0, Rthread);
1232   __ call(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans));
1233   pop_result_registers(masm, ret_type);
1234   __ b(return_to_java);
1235 
1236   // Reguard stack pages. Save native results around a call to C runtime.
1237   __ bind(reguard);
1238   push_result_registers(masm, ret_type);
1239   __ call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages));
1240   pop_result_registers(masm, ret_type);
1241   __ b(reguard_done);
1242 
1243   if (method->is_synchronized()) {
1244     // Locking slow case
1245     __ bind(slow_lock);
1246 
1247     push_param_registers(masm, fp_regs_in_arguments);
1248 
1249     // last_Java_frame is already set, so do call_VM manually; no exception can occur
1250     __ mov(R0, sync_obj);
1251     __ mov(R1, Rthread);

1252     __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_locking_C));
1253 
1254     pop_param_registers(masm, fp_regs_in_arguments);
1255 
1256     __ b(lock_done);
1257 
1258     // Unlocking slow case
1259     __ bind(slow_unlock);
1260 
1261     push_result_registers(masm, ret_type);
1262 
1263     // Clear pending exception before reentering VM.
1264     // Can store the oop in register since it is a leaf call.
1265     assert_different_registers(Rtmp_save1, sync_obj, disp_hdr);
1266     __ ldr(Rtmp_save1, Address(Rthread, Thread::pending_exception_offset()));
1267     Register zero = __ zero_register(Rtemp);
1268     __ str(zero, Address(Rthread, Thread::pending_exception_offset()));
1269     __ mov(R0, sync_obj);
1270     __ mov(R1, Rthread);

1271     __ call(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C));
1272     __ str(Rtmp_save1, Address(Rthread, Thread::pending_exception_offset()));
1273 
1274     pop_result_registers(masm, ret_type);
1275 
1276     __ b(unlock_done);
1277   }
1278 
1279   __ flush();
1280   return nmethod::new_native_nmethod(method,
1281                                      compile_id,
1282                                      masm->code(),
1283                                      vep_offset,
1284                                      frame_complete,
1285                                      stack_slots / VMRegImpl::slots_per_word,
1286                                      in_ByteSize(method_is_static ? klass_offset : receiver_offset),

1287                                      oop_maps);
1288 }
1289 
1290 // this function returns the adjust size (in number of words) to a c2i adapter
1291 // activation for use during deoptimization
1292 int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) {
1293   int extra_locals_size = (callee_locals - callee_parameters) * Interpreter::stackElementWords;
1294   return extra_locals_size;
1295 }
1296 
1297 
1298 // Number of stack slots between incoming argument block and the start of
1299 // a new frame.  The PROLOG must add this many slots to the stack.  The
1300 // EPILOG must remove this many slots.
1301 // FP + LR
1302 uint SharedRuntime::in_preserve_stack_slots() {
1303   return 2 * VMRegImpl::slots_per_word;
1304 }
1305 
1306 uint SharedRuntime::out_preserve_stack_slots() {
< prev index next >