< prev index next >

src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp

Print this page
@@ -127,10 +127,16 @@
    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(const frame& f) {
+   assert(*f.addr_at(frame::interpreter_frame_last_sp_offset) == 0, "should be null for top frame");
+   intptr_t* lspp = f.addr_at(frame::interpreter_frame_last_sp_offset);
+   *lspp = f.unextended_sp() - f.fp();
+ }
+ 
  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), "");

@@ -233,11 +239,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), "");

@@ -251,11 +257,11 @@
      if (PreserveFramePointer) {
        // we need to recreate a "real" frame pointer, pointing into the stack
        fp = frame_sp + FKind::size(hf) - frame::sender_sp_offset;
      } else {
        fp = FKind::stub
-         ? frame_sp + fsize - frame::sender_sp_offset // on AArch64, this value is used for the safepoint stub
+         ? frame_sp + fsize - frame::sender_sp_offset // fp always points to the address below the pushed return pc. We need correct address.
          : *(intptr_t**)(hf.sp() - frame::sender_sp_offset); // we need to re-read fp because it may be an oop and we might have fixed the frame.
      }
      return frame(frame_sp, frame_sp, fp, hf.pc(), hf.cb(), hf.oop_map(), false); // TODO PERF : this computes deopt state; is it necessary?
    }
  }

@@ -275,10 +281,68 @@
  
  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) {
+   Unimplemented();
+ }
+ 
+ inline intptr_t* ThawBase::push_preempt_rerun_adapter(frame top, bool is_interpreted_frame) {
+   intptr_t* sp = top.sp();
+   CodeBlob* cb = top.cb();
+   if (!is_interpreted_frame && cb->frame_size() == 2) {
+     // C2 runtime stub case. For aarch64 the real size of the c2 runtime stub is 2 words bigger
+     // than what we think, i.e. size is 4. This is because the _last_Java_sp is not set to the
+     // sp right before making the call to the VM, but rather it is artificially set 2 words above
+     // this real sp so that we can store the return address at last_Java_sp[-1], and keep this
+     // property where we can retrieve the last_Java_pc from the last_Java_sp. But that means that
+     // once we return to the runtime stub, the code will adjust sp according to this real size.
+     // So we must adjust the frame size back here. We just copy lr/rfp again. These 2 top words
+     // will be the ones popped in generate_cont_preempt_rerun_compiler_adapter(). The other 2 words
+     // will just be discarded once back in the runtime stub (add sp, sp, #0x10).
+     sp -= 2;
+     sp[-2] = sp[0];
+     sp[-1] = sp[1];
+   }
+ 
+   intptr_t* fp = sp - frame::sender_sp_offset;
+   address pc = is_interpreted_frame ? Interpreter::cont_preempt_rerun_interpreter_adapter()
+                                     : StubRoutines::cont_preempt_rerun_compiler_adapter();
+ 
+   sp -= frame::metadata_words;
+   *(address*)(sp - frame::sender_sp_ret_address_offset()) = pc;
+   *(intptr_t**)(sp - frame::sender_sp_offset) = fp;
+ 
+   log_develop_trace(continuations, preempt)("push_preempt_rerun_%s_adapter() initial sp: " INTPTR_FORMAT " final sp: " INTPTR_FORMAT " fp: " INTPTR_FORMAT,
+     is_interpreted_frame ? "interpreter" : "safepointblob", p2i(sp + frame::metadata_words), p2i(sp), p2i(fp));
+   return sp;
+ }
+ 
+ inline intptr_t* ThawBase::push_preempt_monitorenter_redo(stackChunkOop chunk) {
+ 
+   // fprintf(stderr, "push_preempt_monitorenter_redo\n");
+   frame enterSpecial = new_entry_frame();
+   intptr_t* sp = enterSpecial.sp();
+ 
+   // First push the return barrier frame
+   sp -= frame::metadata_words;
+   sp[1] = (intptr_t)StubRoutines::cont_returnBarrier();
+   sp[0] = (intptr_t)enterSpecial.fp();
+ 
+   // Now push the ObjectMonitor*
+   sp -= frame::metadata_words;
+   sp[1] = (intptr_t)chunk->objectMonitor(); // alignment
+   sp[0] = (intptr_t)chunk->objectMonitor();
+ 
+   // Finally arrange to return to the monitorenter_redo stub
+   sp[-1] = (intptr_t)StubRoutines::cont_preempt_monitorenter_redo();
+   sp[-2] = (intptr_t)enterSpecial.fp();
+   log_develop_trace(continuations, preempt)("push_preempt_monitorenter_redo 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.
< prev index next >