< prev index next >

src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp

Print this page
*** 930,11 ***
  //             which must be initialized with the object to lock.
  //   object  - Address of the object to be locked.
  //
  void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
    if (LockingMode == LM_MONITOR) {
!     call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), monitor);
    } else {
      // template code (for LM_LEGACY):
      //
      // markWord displaced_header = obj->mark().set_unlocked();
      // monitor->lock()->set_displaced_header(displaced_header);
--- 930,11 ---
  //             which must be initialized with the object to lock.
  //   object  - Address of the object to be locked.
  //
  void InterpreterMacroAssembler::lock_object(Register monitor, Register object) {
    if (LockingMode == LM_MONITOR) {
!     call_VM_preemptable(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), monitor);
    } else {
      // template code (for LM_LEGACY):
      //
      // markWord displaced_header = obj->mark().set_unlocked();
      // monitor->lock()->set_displaced_header(displaced_header);

*** 951,12 ***
      const Register header           = R7_ARG5;
      const Register object_mark_addr = R8_ARG6;
      const Register current_header   = R9_ARG7;
      const Register tmp              = R10_ARG8;
  
!     Label count_locking, done;
-     Label cas_failed, slow_case;
  
      assert_different_registers(header, object_mark_addr, current_header, tmp);
  
      // markWord displaced_header = obj->mark().set_unlocked();
  
--- 951,11 ---
      const Register header           = R7_ARG5;
      const Register object_mark_addr = R8_ARG6;
      const Register current_header   = R9_ARG7;
      const Register tmp              = R10_ARG8;
  
!     Label count_locking, done, slow_case, cas_failed;
  
      assert_different_registers(header, object_mark_addr, current_header, tmp);
  
      // markWord displaced_header = obj->mark().set_unlocked();
  

*** 967,11 ***
        bne(CCR0, slow_case);
      }
  
      if (LockingMode == LM_LIGHTWEIGHT) {
        lightweight_lock(monitor, object, header, tmp, slow_case);
!       b(count_locking);
      } else if (LockingMode == LM_LEGACY) {
        // Load markWord from object into header.
        ld(header, oopDesc::mark_offset_in_bytes(), object);
  
        // Set displaced_header to be (markWord of object | UNLOCK_VALUE).
--- 966,11 ---
        bne(CCR0, slow_case);
      }
  
      if (LockingMode == LM_LIGHTWEIGHT) {
        lightweight_lock(monitor, object, header, tmp, slow_case);
!       b(done);
      } else if (LockingMode == LM_LEGACY) {
        // Load markWord from object into header.
        ld(header, oopDesc::mark_offset_in_bytes(), object);
  
        // Set displaced_header to be (markWord of object | UNLOCK_VALUE).

*** 1033,16 ***
      //   InterpreterRuntime::monitorenter(THREAD, monitor);
  
      // None of the above fast optimizations worked so we have to get into the
      // slow case of monitor enter.
      bind(slow_case);
!     call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), monitor);
-     b(done);
      // }
!     align(32, 12);
!     bind(count_locking);
!     inc_held_monitor_count(current_header /*tmp*/);
      bind(done);
    }
  }
  
  // Unlocks an object. Used in monitorexit bytecode and remove_activation.
--- 1032,19 ---
      //   InterpreterRuntime::monitorenter(THREAD, monitor);
  
      // None of the above fast optimizations worked so we have to get into the
      // slow case of monitor enter.
      bind(slow_case);
!     call_VM_preemptable(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorenter), monitor);
      // }
! 
!     if (LockingMode == LM_LEGACY) {
!       b(done);
+       align(32, 12);
+       bind(count_locking);
+       inc_held_monitor_count(current_header /*tmp*/);
+     }
      bind(done);
    }
  }
  
  // Unlocks an object. Used in monitorexit bytecode and remove_activation.

*** 1135,11 ***
      // Exchange worked, do monitor->set_obj(nullptr);
      align(32, 12);
      bind(free_slot);
      li(R0, 0);
      std(R0, in_bytes(BasicObjectLock::obj_offset()), monitor);
!     dec_held_monitor_count(current_header /*tmp*/);
      bind(done);
    }
  }
  
  // Load compiled (i2c) or interpreter entry when calling from interpreted and
--- 1137,13 ---
      // Exchange worked, do monitor->set_obj(nullptr);
      align(32, 12);
      bind(free_slot);
      li(R0, 0);
      std(R0, in_bytes(BasicObjectLock::obj_offset()), monitor);
!     if (LockingMode == LM_LEGACY) {
+       dec_held_monitor_count(current_header /*tmp*/);
+     }
      bind(done);
    }
  }
  
  // Load compiled (i2c) or interpreter entry when calling from interpreted and

*** 2131,14 ***
  
    align(32, 12);
    bind(Ldone);
  }
  
! void InterpreterMacroAssembler::call_VM(Register oop_result, address entry_point, bool check_exceptions) {
    save_interpreter_state(R11_scratch1);
  
!   MacroAssembler::call_VM(oop_result, entry_point, false);
  
    restore_interpreter_state(R11_scratch1, /*bcp_and_mdx_only*/ true);
  
    check_and_handle_popframe(R11_scratch1);
    check_and_handle_earlyret(R11_scratch1);
--- 2135,14 ---
  
    align(32, 12);
    bind(Ldone);
  }
  
! void InterpreterMacroAssembler::call_VM(Register oop_result, address entry_point, bool check_exceptions, Label* last_java_pc) {
    save_interpreter_state(R11_scratch1);
  
!   MacroAssembler::call_VM(oop_result, entry_point, false /*check_exceptions*/, last_java_pc);
  
    restore_interpreter_state(R11_scratch1, /*bcp_and_mdx_only*/ true);
  
    check_and_handle_popframe(R11_scratch1);
    check_and_handle_earlyret(R11_scratch1);

*** 2153,10 ***
--- 2157,78 ---
    // ARG1 is reserved for the thread.
    mr_if_needed(R4_ARG2, arg_1);
    call_VM(oop_result, entry_point, check_exceptions);
  }
  
+ void InterpreterMacroAssembler::call_VM_preemptable(Register oop_result, address entry_point,
+                                         Register arg_1, bool check_exceptions) {
+   if (!Continuations::enabled()) {
+     call_VM(oop_result, entry_point, arg_1, check_exceptions);
+     return;
+   }
+ 
+   Label resume_pc, not_preempted;
+ 
+   DEBUG_ONLY(ld(R0, in_bytes(JavaThread::preempt_alternate_return_offset()), R16_thread));
+   DEBUG_ONLY(cmpdi(CCR0, R0, 0));
+   asm_assert_eq("Should not have alternate return address set");
+ 
+   // Preserve 2 registers
+   assert(nonvolatile_accross_vthread_preemtion(R31) && nonvolatile_accross_vthread_preemtion(R22), "");
+   ld(R3_ARG1, _abi0(callers_sp), R1_SP); // load FP
+   std(R31, _ijava_state_neg(lresult), R3_ARG1);
+   std(R22, _ijava_state_neg(fresult), R3_ARG1);
+ 
+   // We set resume_pc as last java pc. It will be saved if the vthread gets preempted.
+   // Later execution will continue right there.
+   mr_if_needed(R4_ARG2, arg_1);
+   push_cont_fastpath();
+   call_VM(oop_result, entry_point, false /*check_exceptions*/, &resume_pc /* last_java_pc */);
+   pop_cont_fastpath();
+ 
+   // Jump to handler if the call was preempted
+   ld(R0, in_bytes(JavaThread::preempt_alternate_return_offset()), R16_thread);
+   cmpdi(CCR0, R0, 0);
+   beq(CCR0, not_preempted);
+   mtlr(R0);
+   li(R0, 0);
+   std(R0, in_bytes(JavaThread::preempt_alternate_return_offset()), R16_thread);
+   blr();
+ 
+   bind(resume_pc); // Location to resume execution
+   restore_after_resume(noreg /* fp */);
+   bind(not_preempted);
+ }
+ 
+ void InterpreterMacroAssembler::restore_after_resume(Register fp) {
+   if (!Continuations::enabled()) return;
+ 
+   const address resume_adapter = TemplateInterpreter::cont_resume_interpreter_adapter();
+   add_const_optimized(R31, R29_TOC, MacroAssembler::offset_to_global_toc(resume_adapter));
+   mtctr(R31);
+   bctrl();
+   // Restore registers that are preserved across vthread preemption
+   assert(nonvolatile_accross_vthread_preemtion(R31) && nonvolatile_accross_vthread_preemtion(R22), "");
+   ld(R3_ARG1, _abi0(callers_sp), R1_SP); // load FP
+   ld(R31, _ijava_state_neg(lresult), R3_ARG1);
+   ld(R22, _ijava_state_neg(fresult), R3_ARG1);
+ #ifdef ASSERT
+   // Assert FP is in R11_scratch1 (see generate_cont_resume_interpreter_adapter())
+   {
+     Label ok;
+     ld(R12_scratch2, 0, R1_SP);  // load fp
+     cmpd(CCR0, R12_scratch2, R11_scratch1);
+     beq(CCR0, ok);
+     stop(FILE_AND_LINE ": FP is expected in R11_scratch1");
+     bind(ok);
+   }
+ #endif
+   if (fp != noreg && fp != R11_scratch1) {
+     mr(fp, R11_scratch1);
+   }
+ }
+ 
  void InterpreterMacroAssembler::call_VM(Register oop_result, address entry_point,
                                          Register arg_1, Register arg_2,
                                          bool check_exceptions) {
    // ARG1 is reserved for the thread.
    mr_if_needed(R4_ARG2, arg_1);
< prev index next >