< prev index next >

src/hotspot/share/runtime/deoptimization.cpp

Print this page

        

@@ -47,10 +47,11 @@
 #include "oops/typeArrayOop.inline.hpp"
 #include "oops/verifyOopClosure.hpp"
 #include "prims/jvmtiThreadState.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/compilationPolicy.hpp"
+#include "runtime/continuation.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/jniHandles.inline.hpp"

@@ -155,10 +156,11 @@
   thread->inc_in_deopt_handler();
 
   return fetch_unroll_info_helper(thread, exec_mode);
 JRT_END
 
+extern "C" void pfl();
 
 // This is factored, since it is both called from a JRT_LEAF (deoptimization) and a JRT_ENTRY (uncommon_trap)
 Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread* thread, int exec_mode) {
 
   // Note: there is a safepoint safety issue here. No matter whether we enter

@@ -417,10 +419,14 @@
       // caller has for locals.
       caller_was_method_handle = true;
     }
   }
 
+  // If the caller is a continuation entry and the callee has a return barrier
+  // then we cannot use the parameters in the caller.
+  bool caller_was_continuation_entry = Continuation::is_cont_post_barrier_entry_frame(deopt_sender);
+
   //
   // frame_sizes/frame_pcs[0] oldest frame (int or c2i)
   // frame_sizes/frame_pcs[1] next oldest frame (int)
   // frame_sizes/frame_pcs[n] youngest frame (int)
   //

@@ -475,24 +481,26 @@
   // may not even be enough space).
 
   // QQQ I'd rather see this pushed down into last_frame_adjust
   // and have it take the sender (aka caller).
 
-  if (deopt_sender.is_compiled_frame() || caller_was_method_handle) {
+  // TODO LOOM: consider *always* adjusting instead of the conditionals below. 
+  // That would simplify the alignment code in continuation freeze and particularly thaw, but it makes hotspot/jtreg/vmTestbase/nsk/jvmti/PopFrame/popframe005 fail.
+  // caller_adjustment = last_frame_adjust(0, callee_locals);
+  if (deopt_sender.is_compiled_frame() || caller_was_method_handle || caller_was_continuation_entry) {
     caller_adjustment = last_frame_adjust(0, callee_locals);
   } else if (callee_locals > callee_parameters) {
-    // The caller frame may need extending to accommodate
-    // non-parameter locals of the first unpacked interpreted frame.
-    // Compute that adjustment.
+    // The caller frame may need extending to accommodate non-parameter locals of the first unpacked interpreted frame.
     caller_adjustment = last_frame_adjust(callee_parameters, callee_locals);
   }
 
   // If the sender is deoptimized the we must retrieve the address of the handler
   // since the frame will "magically" show the original pc before the deopt
   // and we'd undo the deopt.
 
-  frame_pcs[0] = deopt_sender.raw_pc();
+  frame_pcs[0] = Continuation::is_cont_barrier_frame(deoptee) ? StubRoutines::cont_returnBarrier() : deopt_sender.raw_pc();
+  // if (Continuation::is_cont_barrier_frame(deoptee)) tty->print_cr("WOWEE Continuation::is_cont_barrier_frame(deoptee)");
 
   assert(CodeCache::find_blob_unsafe(frame_pcs[0]) != NULL, "bad pc");
 
 #if INCLUDE_JVMCI
   if (exceptionObject() != NULL) {

@@ -617,10 +625,11 @@
   // but makes the entry a little slower. There is however a little dance we have to
   // do in debug mode to get around the NoHandleMark code in the JRT_LEAF macro
   ResetNoHandleMark rnhm; // No-op in release/product versions
   HandleMark hm;
 
+  thread->set_cont_fastpath(false);
   frame stub_frame = thread->last_frame();
 
   // Since the frame to unpack is the top frame of this thread, the vframe_array_head
   // must point to the vframeArray for the unpack frame.
   vframeArray* array = thread->vframe_array_head();

@@ -1409,14 +1418,14 @@
   // the places we want to call this routine so we need to walk the
   // stack again to update the register map.
   if (map == NULL || !map->update_map()) {
     StackFrameStream sfs(thread, true);
     bool found = false;
-    while (!found && !sfs.is_done()) {
+    for (; !found && !sfs.is_done(); sfs.next()) {
       frame* cur = sfs.current();
-      sfs.next();
       found = cur->id() == fr.id();
+      if (found) break; // we must not call sfs.next
     }
     assert(found, "frame to be deoptimized not found on target thread's stack");
     map = sfs.register_map();
   }
 

@@ -1457,10 +1466,13 @@
       if (sd->is_top())  break;
     }
     xtty->tail("deoptimized");
   }
 
+  // For simplicity, we currently clear the fast path if the frame is on _any_ continuation
+  if (Continuation::is_frame_in_continuation(thread, fr)) thread->set_cont_fastpath(false);
+
   // Patch the compiled method so that when execution returns to it we will
   // deopt the execution state and return to the interpreter.
   fr.deoptimize(thread);
 }
 

@@ -1769,10 +1781,11 @@
         xtty->end_head();
       }
       if (TraceDeoptimization) {  // make noise on the tty
         tty->print("Uncommon trap occurred in");
         nm->method()->print_short_name(tty);
+        // nm->method()->print_codes_on(tty);
         tty->print(" compiler=%s compile_id=%d", nm->compiler_name(), nm->compile_id());
 #if INCLUDE_JVMCI
         if (nm->is_nmethod()) {
           const char* installed_code_name = nm->as_nmethod()->jvmci_name();
           if (installed_code_name != NULL) {
< prev index next >