src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp
changeset 48332 651a95f30dfb
parent 47795 5a69ba3a4fd1
child 48557 2e867226b914
child 48626 9f6f48d4f9a1
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp	Thu Dec 14 12:02:16 2017 +0100
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp	Thu Dec 14 13:05:20 2017 +0100
@@ -214,6 +214,7 @@
   // StackFrameStream construction (needed for deoptimization; see
   // compiledVFrame::create_stack_value).
   // If return_pc_adjustment != 0 adjust the return pc by return_pc_adjustment.
+  // Updated return pc is returned in R31 (if not return_pc_is_pre_saved).
 
   int i;
   int offset;
@@ -233,16 +234,17 @@
 
   BLOCK_COMMENT("push_frame_reg_args_and_save_live_registers {");
 
-  // Save r31 in the last slot of the not yet pushed frame so that we
-  // can use it as scratch reg.
-  __ std(R31, -reg_size, R1_SP);
+  // Save some registers in the last slots of the not yet pushed frame so that we
+  // can use them as scratch regs.
+  __ std(R31, -  reg_size, R1_SP);
+  __ std(R30, -2*reg_size, R1_SP);
   assert(-reg_size == register_save_offset - frame_size_in_bytes + ((regstosave_num-1)*reg_size),
          "consistency check");
 
   // save the flags
   // Do the save_LR_CR by hand and adjust the return pc if requested.
-  __ mfcr(R31);
-  __ std(R31, _abi(cr), R1_SP);
+  __ mfcr(R30);
+  __ std(R30, _abi(cr), R1_SP);
   switch (return_pc_location) {
     case return_pc_is_lr: __ mflr(R31); break;
     case return_pc_is_pre_saved: assert(return_pc_adjustment == 0, "unsupported"); break;
@@ -257,7 +259,7 @@
   }
 
   // push a new frame
-  __ push_frame(frame_size_in_bytes, R31);
+  __ push_frame(frame_size_in_bytes, R30);
 
   // save all registers (ints and floats)
   offset = register_save_offset;
@@ -267,7 +269,7 @@
 
     switch (reg_type) {
       case RegisterSaver::int_reg: {
-        if (reg_num != 31) { // We spilled R31 right at the beginning.
+        if (reg_num < 30) { // We spilled R30-31 right at the beginning.
           __ std(as_Register(reg_num), offset, R1_SP);
         }
         break;
@@ -278,8 +280,8 @@
       }
       case RegisterSaver::special_reg: {
         if (reg_num == SR_CTR_SpecialRegisterEnumValue) {
-          __ mfctr(R31);
-          __ std(R31, offset, R1_SP);
+          __ mfctr(R30);
+          __ std(R30, offset, R1_SP);
         } else {
           Unimplemented();
         }
@@ -2364,23 +2366,14 @@
     Register sync_state      = r_temp_5;
     Register suspend_flags   = r_temp_6;
 
-    __ load_const(sync_state_addr, SafepointSynchronize::address_of_state(), /*temp*/ sync_state);
-
-    // TODO: PPC port assert(4 == SafepointSynchronize::sz_state(), "unexpected field size");
-    __ lwz(sync_state, 0, sync_state_addr);
-
+    // No synchronization in progress nor yet synchronized
+    // (cmp-br-isync on one path, release (same as acquire on PPC64) on the other path).
+    __ safepoint_poll(sync, sync_state);
+
+    // Not suspended.
     // TODO: PPC port assert(4 == Thread::sz_suspend_flags(), "unexpected field size");
     __ lwz(suspend_flags, thread_(suspend_flags));
-
-    __ acquire();
-
-    Label do_safepoint;
-    // No synchronization in progress nor yet synchronized.
-    __ cmpwi(CCR0, sync_state, SafepointSynchronize::_not_synchronized);
-    // Not suspended.
     __ cmpwi(CCR1, suspend_flags, 0);
-
-    __ bne(CCR0, sync);
     __ beq(CCR1, no_block);
 
     // Block. Save any potential method result value before the operation and
@@ -2388,6 +2381,7 @@
     // lets us share the oopMap we used when we went native rather than create
     // a distinct one for this pc.
     __ bind(sync);
+    __ isync();
 
     address entry_point = is_critical_native
       ? CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition)
@@ -2410,7 +2404,7 @@
 
   // Transition from _thread_in_native_trans to _thread_in_Java.
   __ li(R0, _thread_in_Java);
-  __ release();
+  __ lwsync(); // Acquire safepoint and suspend state, release thread state.
   // TODO: PPC port assert(4 == JavaThread::sz_thread_state(), "unexpected field size");
   __ stw(R0, thread_(thread_state));
   __ bind(after_transition);
@@ -3093,7 +3087,7 @@
     return_pc_location = RegisterSaver::return_pc_is_thread_saved_exception_pc;
   }
 
-  // Save registers, fpu state, and flags.
+  // Save registers, fpu state, and flags. Set R31 = return pc.
   map = RegisterSaver::push_frame_reg_args_and_save_live_registers(masm,
                                                                    &frame_size_in_bytes,
                                                                    /*generate_oop_map=*/ true,
@@ -3142,6 +3136,19 @@
   // No exception case.
   __ BIND(noException);
 
+  if (SafepointMechanism::uses_thread_local_poll() && !cause_return) {
+    Label no_adjust;
+    // If our stashed return pc was modified by the runtime we avoid touching it
+    __ ld(R0, frame_size_in_bytes + _abi(lr), R1_SP);
+    __ cmpd(CCR0, R0, R31);
+    __ bne(CCR0, no_adjust);
+
+    // Adjust return pc forward to step over the safepoint poll instruction
+    __ addi(R31, R31, 4);
+    __ std(R31, frame_size_in_bytes + _abi(lr), R1_SP);
+
+    __ bind(no_adjust);
+  }
 
   // Normal exit, restore registers and exit.
   RegisterSaver::restore_live_registers_and_pop_frame(masm,