< prev index next >

src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp

Print this page
@@ -125,10 +125,15 @@
    if (real_unextended_sp != nullptr) {
      f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint
    }
  }
  
+ inline void FreezeBase::prepare_freeze_interpreted_top_frame(frame& f) {
+   assert(f.interpreter_frame_last_sp() == nullptr, "should be null for top frame");
+   f.interpreter_frame_set_last_sp(f.unextended_sp());
+ }
+ 
  inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) {
    assert(hf.fp() == hf.unextended_sp() + (f.fp() - f.unextended_sp()), "");
    assert((f.at(frame::interpreter_frame_last_sp_offset) != 0)
      || (f.unextended_sp() == f.sp()), "");
    assert(f.fp() > (intptr_t*)f.at_relative(frame::interpreter_frame_initial_sp_offset), "");

@@ -145,14 +150,20 @@
    assert(hf.at_absolute(frame::interpreter_frame_monitor_block_top_offset) <= frame::interpreter_frame_initial_sp_offset, "");
  
    // extended_sp is already relativized by TemplateInterpreterGenerator::generate_normal_entry or
    // AbstractInterpreter::layout_activation
  
+   // The interpreter native wrapper code adds space in the stack equal to size_of_parameters()
+   // after the fixed part of the frame. For wait0 this is equal to 3 words (this + long parameter).
+   // We adjust by this size since otherwise the saved last sp will be less than the extended_sp.
+   DEBUG_ONLY(Method* m = hf.interpreter_frame_method();)
+   DEBUG_ONLY(int extra_space = m->is_object_wait0() ? m->size_of_parameters() : 0;)
+ 
    assert((hf.fp() - hf.unextended_sp()) == (f.fp() - f.unextended_sp()), "");
    assert(hf.unextended_sp() == (intptr_t*)hf.at(frame::interpreter_frame_last_sp_offset), "");
    assert(hf.unextended_sp() <= (intptr_t*)hf.at(frame::interpreter_frame_initial_sp_offset), "");
-   assert(hf.unextended_sp() >  (intptr_t*)hf.at(frame::interpreter_frame_extended_sp_offset), "");
+   assert(hf.unextended_sp() + extra_space >  (intptr_t*)hf.at(frame::interpreter_frame_extended_sp_offset), "");
    assert(hf.fp()            >  (intptr_t*)hf.at(frame::interpreter_frame_initial_sp_offset), "");
  #ifdef ASSERT
    if (f.interpreter_frame_method()->max_locals() > 0) {
      assert(hf.fp()          <= (intptr_t*)hf.at(frame::interpreter_frame_locals_offset), "");
    }

@@ -201,11 +212,12 @@
  
  // Slow path
  
  inline frame ThawBase::new_entry_frame() {
    intptr_t* sp = _cont.entrySP();
-   return frame(sp, sp, _cont.entryFP(), _cont.entryPC()); // TODO PERF: This finds code blob and computes deopt state
+   // TODO PERF: This finds code blob and computes deopt state
+   return frame(sp, sp, _cont.entryFP(), _cont.entryPC());
  }
  
  template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) {
    assert(FKind::is_instance(hf), "");
    // The values in the returned frame object will be written into the callee's stack in patch.

@@ -213,11 +225,10 @@
    if (FKind::interpreted) {
      intptr_t* heap_sp = hf.unextended_sp();
      // If caller is interpreted it already made room for the callee arguments
      int overlap = caller.is_interpreted_frame() ? ContinuationHelper::InterpretedFrame::stack_argsize(hf) : 0;
      const int fsize = (int)(ContinuationHelper::InterpretedFrame::frame_bottom(hf) - hf.unextended_sp() - overlap);
-     const int locals = hf.interpreter_frame_method()->max_locals();
      intptr_t* frame_sp = caller.unextended_sp() - fsize;
      intptr_t* fp = frame_sp + (hf.fp() - heap_sp);
      if ((intptr_t)fp % frame::frame_alignment != 0) {
        fp--;
        frame_sp--;

@@ -235,11 +246,11 @@
      return f;
    } else {
      int fsize = FKind::size(hf);
      intptr_t* frame_sp = caller.unextended_sp() - fsize;
      if (bottom || caller.is_interpreted_frame()) {
-       int argsize = hf.compiled_frame_stack_argsize();
+       int argsize = FKind::stack_argsize(hf);
  
        fsize += argsize;
        frame_sp -= argsize;
        caller.set_sp(caller.sp() - argsize);
        assert(caller.sp() == frame_sp + (fsize-argsize), "");

@@ -250,17 +261,20 @@
      assert(hf.cb() != nullptr, "");
      assert(hf.oop_map() != nullptr, "");
      intptr_t* fp;
      if (PreserveFramePointer) {
        // we need to recreate a "real" frame pointer, pointing into the stack
-       fp = frame_sp + FKind::size(hf) - 2;
+       fp = frame_sp + FKind::size(hf) - frame::sender_sp_offset;
      } else {
-       fp = FKind::stub
-         ? frame_sp + fsize - 2 // On RISCV, this value is used for the safepoint stub
-         : *(intptr_t**)(hf.sp() - 2); // we need to re-read fp because it may be an oop and we might have fixed the frame.
+       fp = FKind::stub || FKind::native
+         // fp always points to the address above the pushed return pc. We need correct address.
+         ? frame_sp + fsize - frame::sender_sp_offset
+         // we need to re-read fp because it may be an oop and we might have fixed the frame.
+         : *(intptr_t**)(hf.sp() - 2);
      }
-     return frame(frame_sp, frame_sp, fp, hf.pc(), hf.cb(), hf.oop_map(), false); // TODO PERF : this computes deopt state; is it necessary?
+     // TODO PERF : this computes deopt state; is it necessary?
+     return frame(frame_sp, frame_sp, fp, hf.pc(), hf.cb(), hf.oop_map(), false);
    }
  }
  
  inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& caller, bool bottom) {
  #ifdef _LP64

@@ -277,17 +291,36 @@
  
  inline void ThawBase::patch_pd(frame& f, const frame& caller) {
    patch_callee_link(caller, caller.fp());
  }
  
+ inline void ThawBase::patch_pd(frame& f, intptr_t* caller_sp) {
+   intptr_t* fp = caller_sp - frame::sender_sp_offset;
+   patch_callee_link(f, fp);
+ }
+ 
+ inline intptr_t* ThawBase::push_cleanup_continuation() {
+   frame enterSpecial = new_entry_frame();
+   intptr_t* sp = enterSpecial.sp();
+ 
+   sp[-1] = (intptr_t)ContinuationEntry::cleanup_pc();
+   sp[-2] = (intptr_t)enterSpecial.fp();
+ 
+   log_develop_trace(continuations, preempt)("push_cleanup_continuation initial sp: " INTPTR_FORMAT " final sp: " INTPTR_FORMAT, p2i(sp + 2 * frame::metadata_words), p2i(sp));
+   return sp;
+ }
+ 
  inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) {
    // Make sure that last_sp is kept relativized.
    assert((intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset) == f.unextended_sp(), "");
  
    // Make sure that monitor_block_top is still relativized.
    assert(f.at_absolute(frame::interpreter_frame_monitor_block_top_offset) <= frame::interpreter_frame_initial_sp_offset, "");
  
+   DEBUG_ONLY(Method* m = hf.interpreter_frame_method();)
+   DEBUG_ONLY(int extra_space = m->is_object_wait0() ? m->size_of_parameters() : 0;) // see comment in relativize_interpreted_frame_metadata()
+ 
    // Make sure that extended_sp is kept relativized.
-   assert((intptr_t*)f.at_relative(frame::interpreter_frame_extended_sp_offset) < f.unextended_sp(), "");
+   assert((intptr_t*)f.at_relative(frame::interpreter_frame_extended_sp_offset) < f.unextended_sp() + extra_space, "");
  }
  
  #endif // CPU_RISCV_CONTINUATIONFREEZETHAW_RISCV_INLINE_HPP
< prev index next >