changeset 56202:d657fe9599f8 fibers

Merge
author rpressler
date Fri, 26 Jul 2019 17:26:36 +0100
parents 266550213f5e d96849b90380
children fb161fcd032a
files src/hotspot/cpu/x86/stubGenerator_x86_64.cpp src/hotspot/share/runtime/continuation.hpp
diffstat 11 files changed, 109 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/cpu/x86/abstractInterpreter_x86.cpp	Fri Jul 26 17:26:36 2019 +0100
@@ -90,7 +90,7 @@
     if (locals >= caller->fp() + frame::interpreter_frame_initial_sp_offset) {
       tty->print("method: "); method->print_on(tty);
       tty->print("caller: "); caller->print_on(tty);
-      tty->print_cr("locals: " INTPTR_FORMAT " max_locals: %d caller.fp: " INTPTR_FORMAT " caller.initial_sp: " INTPTR_FORMAT, p2i(locals), max_locals, p2i(caller->fp()), p2i(caller->fp() + frame::interpreter_frame_initial_sp_offset));
+      tty->print_cr("sender_sp: " INTPTR_FORMAT " locals: " INTPTR_FORMAT " max_locals: %d caller.fp: " INTPTR_FORMAT " caller.initial_sp: " INTPTR_FORMAT, p2i(interpreter_frame->sender_sp()), p2i(locals), max_locals, p2i(caller->fp()), p2i(caller->fp() + frame::interpreter_frame_initial_sp_offset));
     }
     assert(locals < caller->fp() + frame::interpreter_frame_initial_sp_offset, "bad placement");
   }
--- a/src/hotspot/cpu/x86/continuation_x86.inline.hpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/cpu/x86/continuation_x86.inline.hpp	Fri Jul 26 17:26:36 2019 +0100
@@ -29,10 +29,11 @@
 #include "runtime/frame.hpp"
 #include "runtime/frame.inline.hpp"
 
+template<bool indirect>
 static void set_anchor(JavaThread* thread, const FrameInfo* fi) {
   JavaFrameAnchor* anchor = thread->frame_anchor();
   anchor->set_last_Java_sp((intptr_t*)fi->sp);
-  anchor->set_last_Java_fp((intptr_t*)fi->fp);
+  anchor->set_last_Java_fp(indirect ? *(intptr_t**)fi->fp : (intptr_t*)fi->fp); // there is an indirection in fi->fp in the FrameInfo created by Freeze::setup_jump
   anchor->set_last_Java_pc(fi->pc);
 
   assert (thread->has_last_Java_frame(), "");
@@ -658,18 +659,14 @@
   fi->fp = f.fp();
 }
 
+template<bool indirect>
 inline frame ContinuationHelper::to_frame(FrameInfo* fi) {
   address pc = fi->pc;
   int slot;
   CodeBlob* cb = ContinuationCodeBlobLookup::find_blob_and_oopmap(pc, slot);
-  return frame(fi->sp, fi->sp, fi->fp, pc, cb, slot == -1 ? NULL : cb->oop_map_for_slot(slot, pc));
-}
-
-inline frame ContinuationHelper::to_frame_indirect(FrameInfo* fi) {
-  address pc = fi->pc;
-  int slot;
-  CodeBlob* cb = ContinuationCodeBlobLookup::find_blob_and_oopmap(pc, slot);
-  return frame(fi->sp, fi->sp, (intptr_t*)*fi->fp, pc, cb, slot == -1 ? NULL : cb->oop_map_for_slot(slot, pc));
+  return frame(fi->sp, fi->sp, 
+    indirect ? *(intptr_t**)fi->fp : fi->fp, 
+    pc, cb, slot == -1 ? NULL : cb->oop_map_for_slot(slot, pc));
 }
 
 // creates the yield stub frame faster than JavaThread::last_frame
@@ -825,10 +822,13 @@
 
 template <typename ConfigT, op_mode mode>
 template <bool bottom>
-inline void Freeze<ConfigT, mode>::align(const hframe& caller) {
+inline void Freeze<ConfigT, mode>::align(const hframe& caller, int argsize) {
   assert (mode != mode_fast || bottom || !Interpreter::contains(caller.pc()), "");
   if ((mode != mode_fast || bottom) && caller.is_interpreted_frame()) {
-    _cont.add_size(sizeof(intptr_t));
+    assert (argsize >= 0, "");
+    _cont.add_size((2  // one for alignment, one for extra word between interpreted and compiled
+                   + ((argsize /* / 2*/) >> LogBytesPerWord)) // SharedRuntime::gen_i2c_adapter makes room that's twice as big as required for the stack-passed arguments by counting slots but subtracting words from rsp
+                   * sizeof(intptr_t));
   }
 }
 
@@ -851,6 +851,7 @@
 
 template <typename ConfigT, op_mode mode>
 inline frame Thaw<ConfigT, mode>::new_entry_frame() {
+  // if (Interpreter::contains(_cont.entryPC())) _cont.set_entrySP(_cont.entrySP() - 1);
   return frame(_cont.entrySP(), _cont.entryFP(), _cont.entryPC()); // TODO PERF: This finds code blob and computes deopt state
 }
 
@@ -885,22 +886,42 @@
   assert (mode != mode_fast || bottom, "");
 
   if (!FKind::interpreted && !FKind::stub) {
+    int addedWords = 0;
     assert (_cont.is_flag(FLAG_LAST_FRAME_INTERPRETED) == Interpreter::contains(_cont.pc()), "");
-    if ((!bottom && mode != mode_fast && caller.is_interpreted_frame())
+    if (((bottom || mode != mode_fast) && caller.is_interpreted_frame()) 
         || (bottom && _cont.is_flag(FLAG_LAST_FRAME_INTERPRETED))) {
-      _cont.sub_size(sizeof(intptr_t)); // we do this whether or not we've aligned because we add it in freeze_interpreted_frame
+
+      addedWords = 1; // add room between interpreted and compiled; deopt code depends on it.
+
+      // SharedRuntime::gen_i2c_adapter makes room that's twice as big as required for the stack-passed arguments by counting slots but subtracting words from rsp 
+      assert (VMRegImpl::stack_slot_size == 4, "");
+      int argsize = hf.compiled_frame_stack_argsize();
+      assert (argsize >= 0, "");
+      addedWords += (argsize /* / 2*/) >> LogBytesPerWord;
+
+      if (!bottom || _cont.is_flag(FLAG_LAST_FRAME_INTERPRETED)) {
+        _cont.sub_size((1 + addedWords) * sizeof(intptr_t)); // we add one whether or not we've aligned because we add it in freeze_interpreted_frame
+      } 
+      if (!bottom || caller.is_interpreted_frame()) {
+        log_develop_trace(jvmcont)("Aligning compiled frame 0: " INTPTR_FORMAT " -> " INTPTR_FORMAT, p2i(vsp), p2i(vsp - addedWords));
+        vsp -= addedWords;
+      } else {
+        addedWords = 0;
+      }
     }
-
   #ifdef _LP64
     if ((intptr_t)vsp % 16 != 0) {
-      log_develop_trace(jvmcont)("Aligning compiled frame: " INTPTR_FORMAT " -> " INTPTR_FORMAT, p2i(vsp), p2i(vsp - 1));
+      log_develop_trace(jvmcont)("Aligning compiled frame 1: " INTPTR_FORMAT " -> " INTPTR_FORMAT, p2i(vsp), p2i(vsp - 1));
       assert(caller.is_interpreted_frame() 
         || (bottom && !FKind::stub && hf.compiled_frame_stack_argsize() % 16 != 0), "");
+      addedWords++;
       vsp--;
-      caller.set_sp(caller.sp() - 1);
     }
     assert((intptr_t)vsp % 16 == 0, "");
   #endif
+
+   log_develop_trace(jvmcont)("Aligning sender sp: " INTPTR_FORMAT " -> " INTPTR_FORMAT, p2i(caller.sp()), p2i(caller.sp() - addedWords));
+    caller.set_sp(caller.sp() - addedWords);
   }
 
   return vsp;
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Fri Jul 26 17:26:36 2019 +0100
@@ -5952,6 +5952,7 @@
 
     __ subq(rsp, rax);             // make room for the thawed frames
     __ subptr(rsp, wordSize);      // make room for return address
+    __ andptr(rsp, -16); // align
     if (return_barrier) {
       __ push(rdx); __ push_d(xmm0); // save original return value -- again
     }
--- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp	Fri Jul 26 17:26:36 2019 +0100
@@ -812,6 +812,7 @@
   address entry = __ pc();
   assert(StubRoutines::cont_thaw() != NULL, "stub not yet generated");
 
+  __ movl(c_rarg1, 1); // from interpreter
   __ jump(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::cont_thaw())));
 
   return entry;
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp	Fri Jul 26 17:26:36 2019 +0100
@@ -53,6 +53,7 @@
 #include "runtime/atomic.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/compilationPolicy.hpp"
+#include "runtime/continuation.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/frame.inline.hpp"
@@ -1310,7 +1311,7 @@
 
 JRT_LEAF(int, InterpreterRuntime::interpreter_contains(address pc))
 {
-  return (Interpreter::contains(pc) ? 1 : 0);
+  return (Interpreter::contains(Continuation::get_top_return_pc_post_barrier(JavaThread::current(), pc)) ? 1 : 0);
 }
 JRT_END
 
--- a/src/hotspot/share/runtime/continuation.cpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/share/runtime/continuation.cpp	Fri Jul 26 17:26:36 2019 +0100
@@ -146,6 +146,7 @@
 #define RUN_SIG    "java.lang.Continuation.run()V"
 
 static bool is_stub(CodeBlob* cb);
+template<bool indirect>
 static void set_anchor(JavaThread* thread, const FrameInfo* fi);
 // static void set_anchor(JavaThread* thread, const frame& f); -- unused
 
@@ -1069,8 +1070,8 @@
   static inline void to_frame_info(const frame& f, const frame& callee, FrameInfo* fi);
   template<typename FKind> static inline void to_frame_info_pd(const frame& f, const frame& callee, FrameInfo* fi);
   static inline void to_frame_info_pd(const frame& f, FrameInfo* fi);
+  template<bool indirect>
   static inline frame to_frame(FrameInfo* fi);
-  static inline frame to_frame_indirect(FrameInfo* fi);
   static inline void set_last_vstack_frame(RegisterMap* map, const frame& callee);
   static inline void clear_last_vstack_frame(RegisterMap* map);
 };
@@ -1299,7 +1300,7 @@
 #ifdef ASSERT
 static void set_anchor(ContMirror& cont) {
   FrameInfo fi = { cont.entryPC(), cont.entryFP(), cont.entrySP() };
-  set_anchor(cont.thread(), &fi);
+  set_anchor<false>(cont.thread(), &fi);
 }
 #endif
 
@@ -1566,7 +1567,7 @@
 
   template<typename FKind> static inline frame sender(const frame& f);
   template <typename FKind, bool top, bool bottom> inline void patch_pd(const frame& f, hframe& callee, const hframe& caller);
-  template <bool bottom> inline void align(const hframe& caller);
+  template <bool bottom> inline void align(const hframe& caller, int argsize);
   inline void relativize_interpreted_frame_metadata(const frame& f, intptr_t* vsp, const hframe& hf);
   template<bool cont_empty> hframe new_bottom_hframe(int sp, int ref_sp, address pc, bool interpreted);
   template<typename FKind> hframe new_hframe(const frame& f, intptr_t* vsp, const hframe& caller, int fsize, int num_oops, int argsize);
@@ -1846,7 +1847,7 @@
   #ifdef ASSERT
     // if (f.pc() != real_pc(f)) tty->print_cr("Continuation.run deopted!");
     log_develop_debug(jvmcont)("Jumping to frame (freeze): [%ld] (%d)", java_tid(_thread), _thread->has_pending_exception());
-    frame f1 = ContinuationHelper::to_frame_indirect(_fi);
+    frame f1 = ContinuationHelper::to_frame<true>(_fi);
     if (log_develop_is_enabled(Debug, jvmcont)) f1.print_on(tty);
     assert_top_java_frame_name(f1, RUN_SIG);
   #endif
@@ -2022,7 +2023,7 @@
       }
       log_develop_trace(jvmcont)("freeze_compiled_frame add argsize: fsize: %d argsize: %d fsize: %d", fsize, argsize, fsize + argsize);
       fsize += argsize;
-      align<bottom>(caller); // TODO PERF
+      align<bottom>(caller, argsize); // TODO PERF
     }
 
     hframe hf = new_hframe<FKind>(f, vsp, caller, fsize, oops, argsize);
@@ -2336,8 +2337,9 @@
   }
 }
 
-static void post_JVMTI_yield(JavaThread* thread, ContMirror& cont) {
+static void post_JVMTI_yield(JavaThread* thread, ContMirror& cont, const FrameInfo* fi) {
   if (JvmtiExport::should_post_continuation_yield() || JvmtiExport::can_post_frame_pop()) {
+    set_anchor<true>(thread, fi); // ensure frozen frames are invisible
     JvmtiExport::post_continuation_yield(JavaThread::current(), num_java_frames(cont));
   }
 
@@ -2397,7 +2399,7 @@
   cont.write(); // commit the freeze
 
   cont.post_jfr_event(&event);
-  post_JVMTI_yield(thread, cont); // can safepoint
+  post_JVMTI_yield(thread, cont, fi); // can safepoint
 
   // set_anchor(thread, fi);
   thread->set_cont_yield(false);
@@ -2598,7 +2600,7 @@
   if (size == 0) { // no more frames
     return 0;
   }
-  size += sizeof(intptr_t); // just in case we have an interpreted entry after which we need to align
+  size += 2 * sizeof(intptr_t); // just in case we have an interpreted entry after which we need to align
 
   const address bottom = (address)fi->sp; // os::current_stack_pointer(); points to the entry frame
   if (!stack_overflow_check(thread, size + 300, bottom)) {
@@ -2785,6 +2787,7 @@
     caller = FKind::interpreted ? thaw_interpreted_frame    <top, bottom>(hf, caller, (InterpreterOopMap*)extra)
                                 : thaw_compiled_frame<FKind, top, bottom>(hf, caller, (ThawFnT)extra);
 
+    log_develop_trace(jvmcont)("thawed frame:");
     DEBUG_ONLY(print_vframe(caller, &dmap);)
   }
 
@@ -3037,6 +3040,7 @@
     assert (!f.is_compiled_frame() || f.is_deoptimized_frame() == f.cb()->as_compiled_method()->is_deopt_pc(f.raw_pc()), "");
     assert (!f.is_compiled_frame() || f.is_deoptimized_frame() == (f.pc() != f.raw_pc()), "");
 
+    assert ((address)(_fi + 1) <= (address)f.sp(), "");
     _fi->sp = f.sp();
     address pc = f.raw_pc();
     _fi->pc = pc;
@@ -3145,7 +3149,7 @@
 
 static void post_JVMTI_continue(JavaThread* thread, FrameInfo* fi, int java_frame_count) {
   if (JvmtiExport::should_post_continuation_run()) {
-    set_anchor(thread, fi); // ensure thawed frames are visible
+    set_anchor<false>(thread, fi); // ensure thawed frames are visible
     JvmtiExport::post_continuation_run(JavaThread::current(), java_frame_count);
     clear_anchor(thread);
   }
@@ -3208,7 +3212,7 @@
   log_develop_trace(jvmcont)("fi->sp: " INTPTR_FORMAT " fi->fp: " INTPTR_FORMAT " fi->pc: " INTPTR_FORMAT, p2i(fi->sp), p2i(fi->fp), p2i(fi->pc));
 
 #ifndef PRODUCT
-  set_anchor(thread, fi);
+  set_anchor<false>(thread, fi);
   print_frames(thread, tty); // must be done after write(), as frame walking reads fields off the Java objects.
   clear_anchor(thread);
 #endif
@@ -3259,7 +3263,7 @@
   assert(thread == JavaThread::current(), "");
 
   thaw0(thread, fi, return_barrier);
-  set_anchor(thread, fi); // we're in a full transition that expects last_java_frame
+  set_anchor<false>(thread, fi); // we're in a full transition that expects last_java_frame
 
   if (exception) {
     // TODO: handle deopt. see TemplateInterpreterGenerator::generate_throw_exception, OptoRuntime::handle_exception_C, OptoRuntime::handle_exception_helper
@@ -3282,6 +3286,10 @@
   return m->intrinsic_id() == vmIntrinsics::_Continuation_enter;
 }
 
+bool Continuation::is_cont_post_barrier_entry_frame(const frame& f) {
+  return is_return_barrier_entry(Frame::real_pc(f));
+}
+
 // When walking the virtual stack, this method returns true
 // iff the frame is a thawed continuation frame whose
 // caller is still frozen on the h-stack.
@@ -3294,7 +3302,6 @@
 #endif
   assert (f.is_interpreted_frame() || f.cb() != NULL, "");
   return is_return_barrier_entry(f.is_interpreted_frame() ? Interpreted::return_pc(f) : Compiled::return_pc(f));
-  // return is_return_barrier_entry(CHOOSE1(f.is_interpreted_frame(), return_pc, f));
 }
 
 bool Continuation::is_return_barrier_entry(const address pc) {
@@ -3358,7 +3365,6 @@
   assert (pc != NULL, "");
   return pc;
 }
-
 bool Continuation::fix_continuation_bottom_sender(RegisterMap* map, const frame& callee, address* sender_pc, intptr_t** sender_sp) {
   bool res = fix_continuation_bottom_sender(map->thread(), callee, sender_pc, sender_sp);
   if (res && !callee.is_interpreted_frame()) {
@@ -3370,10 +3376,11 @@
 }
 
 bool Continuation::fix_continuation_bottom_sender(JavaThread* thread, const frame& callee, address* sender_pc, intptr_t** sender_sp) {
-  // tty->print_cr(">>> fix_continuation_bottom_sender: %p", *sender_pc);
   if (thread != NULL && is_return_barrier_entry(*sender_pc)) {
-    *sender_pc = get_entry_pc_past_barrier(thread, callee);
-    if (callee.is_compiled_frame()) {
+    address new_pc = get_entry_pc_past_barrier(thread, callee);
+    log_develop_trace(jvmcont)("fix_continuation_bottom_sender: sender_pc: " INTPTR_FORMAT " -> " INTPTR_FORMAT, p2i(*sender_pc), p2i(new_pc));
+    *sender_pc = new_pc; 
+    if (callee.is_compiled_frame() && !Interpreter::contains(*sender_pc)) {
       // The callee's stack arguments (part of the caller frame) are also thawed to the stack when using lazy-copy
       int argsize = callee.cb()->as_compiled_method()->method()->num_stack_arg_slots() * VMRegImpl::stack_slot_size;
       assert ((argsize & WordAlignmentMask) == 0, "must be");
@@ -3382,10 +3389,9 @@
       if (argsize % 2 != 0)
         argsize++; // 16-byte alignment for compiled frame sp
     #endif
-      // tty->print_cr(">>> fix_continuation_bottom_sender sp0: %p sp1: %p", *sender_sp, *sender_sp + argsize);
+      log_develop_trace(jvmcont)("fix_continuation_bottom_sender: sender_sp: " INTPTR_FORMAT " -> " INTPTR_FORMAT, p2i(*sender_sp), p2i(*sender_sp + argsize));
       *sender_sp += argsize;
     }
-    // tty->print_cr(">>> fix_continuation_bottom_sender 2: %p", *sender_pc);
     return true;
   }
   return false;
@@ -3410,6 +3416,14 @@
   return f;
 }
 
+address Continuation::get_top_return_pc_post_barrier(JavaThread* thread, address pc) {
+  oop cont;
+  if (thread != NULL && is_return_barrier_entry(pc) && (cont = get_continuation(thread)) != NULL) {
+    pc = java_lang_Continuation::entryPC(cont);
+  }
+  return pc;
+}
+
 bool Continuation::is_scope_bottom(oop cont_scope, const frame& f, const RegisterMap* map) {
   if (cont_scope == NULL || !is_continuation_entry_frame(f, map))
     return false;
@@ -4436,7 +4450,7 @@
   int i = 0;
   for (frame f = thread->last_frame(); !f.is_entry_frame(); f = f.sender(&map)) {
 #ifndef PRODUCT
-    // print_vframe(f, &map, st);
+    print_vframe(f, &map, st);
     f.describe(values, i, &map);
 #else
     print_vframe(f, &map, st);
--- a/src/hotspot/share/runtime/continuation.hpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/share/runtime/continuation.hpp	Fri Jul 26 17:26:36 2019 +0100
@@ -78,6 +78,7 @@
 
   static oop  get_continutation_for_frame(JavaThread* thread, const frame& f);
   static bool is_continuation_entry_frame(const frame& f, const RegisterMap* map);
+  static bool is_cont_post_barrier_entry_frame(const frame& f);
   static bool is_cont_barrier_frame(const frame& f);
   static bool is_return_barrier_entry(const address pc);
   static bool is_frame_in_continuation(const frame& f, oop cont);
@@ -86,6 +87,7 @@
   static bool fix_continuation_bottom_sender(RegisterMap* map, const frame& callee, address* sender_pc, intptr_t** sender_sp);
   static frame fix_continuation_bottom_sender(const frame& callee, RegisterMap* map, frame f);
   static address* get_continuation_entry_pc_for_sender(Thread* thread, const frame& f, address* pc_addr);
+  static address get_top_return_pc_post_barrier(JavaThread* thread, address pc);
 
   static frame top_frame(const frame& callee, RegisterMap* map);
   static frame sender_for_interpreter_frame(const frame& callee, RegisterMap* map);
--- a/src/hotspot/share/runtime/deoptimization.cpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Fri Jul 26 17:26:36 2019 +0100
@@ -158,6 +158,7 @@
   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) {
@@ -422,7 +423,7 @@
 
   // 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_barrier_frame(deopt_sender);
+  bool caller_was_continuation_entry = Continuation::is_cont_post_barrier_entry_frame(deopt_sender);
 
   //
   // frame_sizes/frame_pcs[0] oldest frame (int or c2i)
@@ -482,16 +483,15 @@
   // QQQ I'd rather see this pushed down into last_frame_adjust
   // and have it take the sender (aka caller).
 
-  // TODO LOOM: consider *always* adjusting instead of the conditionals below. What's the harm?
-  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.
-  //   caller_adjustment = last_frame_adjust(callee_parameters, callee_locals);
-  // }
+  // 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.
+    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
--- a/src/hotspot/share/runtime/frame.cpp	Thu Jul 25 16:48:04 2019 -0700
+++ b/src/hotspot/share/runtime/frame.cpp	Fri Jul 26 17:26:36 2019 +0100
@@ -342,6 +342,8 @@
 }
 
 void frame::deoptimize(JavaThread* thread) {
+  // tty->print_cr(">>> frame::deoptimize");
+  // print_on(tty);
   assert(thread->frame_anchor()->has_last_Java_frame() &&
          thread->frame_anchor()->walkable(), "must be");
   // Schedule deoptimization of an nmethod activation with this frame.
--- a/test/jdk/java/lang/Continuation/Basic.java	Thu Jul 25 16:48:04 2019 -0700
+++ b/test/jdk/java/lang/Continuation/Basic.java	Fri Jul 26 17:26:36 2019 +0100
@@ -28,28 +28,28 @@
 * @summary Basic tests for java.lang.Continuation
 *
 * @run testng/othervm -Xint -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -Xint -XX:+UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=exclude,Basic.manyArgsDriver -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=exclude,java/lang/Continuation.enter -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=inline,java/lang/Continuation.run -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy -XX:CompileCommand=exclude,Basic.manyArgsDriver Basic
-* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy -XX:CompileCommand=exclude,java/lang/Continuation.enter Basic
-* @run testng/othervm -XX:TieredStopAtLevel=3 -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:TieredStopAtLevel=3 -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy Basic
+* @run testng/othervm -Xint -XX:+UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=exclude,Basic.manyArgsDriver -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=exclude,java/lang/Continuation.enter -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=inline,java/lang/Continuation.run -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy -XX:CompileCommand=exclude,Basic.manyArgsDriver Basic
+* @run testng/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy -XX:CompileCommand=exclude,java/lang/Continuation.enter Basic
+* @run testng/othervm -Xcomp -XX:TieredStopAtLevel=3 -XX:CompileOnly=java/lang/Continuation,Basic -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:TieredStopAtLevel=3 -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy Basic
 */
 
 /*
 Graal tests currently disabled until we can find the problem with monitor pinned tests.
 
-* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=exclude,Basic.manyArgsDriver -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=exclude,java/lang/Continuation.enter -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=inline,java/lang/Continuation.run -XX:-UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy Basic
-* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy -XX:CompileCommand=exclude,Basic.manyArgsDriver Basic
-* @run testng/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -Xcomp -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy -XX:CompileCommand=exclude,java/lang/Continuation.enter Basic
+* @run testng/othervm -Xcomp -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:CompileOnly=java/lang/Continuation,Basic -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=exclude,Basic.manyArgsDriver -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=exclude,java/lang/Continuation.enter -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:CompileCommand=inline,java/lang/Continuation.run -XX:-UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy Basic
+* @run testng/othervm -Xcomp -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy -XX:CompileCommand=exclude,Basic.manyArgsDriver Basic
+* @run testng/othervm -Xcomp -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler -XX:-TieredCompilation -XX:CompileOnly=java/lang/Continuation,Basic -XX:+UseContinuationLazyCopy -XX:CompileCommand=exclude,java/lang/Continuation.enter Basic
 */
 
 // Anything excluded or not compileonly is not compiled; see CompilerOracle::should_exclude
--- a/test/jdk/java/lang/Continuation/Scoped.java	Thu Jul 25 16:48:04 2019 -0700
+++ b/test/jdk/java/lang/Continuation/Scoped.java	Fri Jul 26 17:26:36 2019 +0100
@@ -26,9 +26,9 @@
  * @summary Nested continuations test
  * 
  * @run testng/othervm -Xint -XX:-UseContinuationLazyCopy Scoped
- * @run testng/othervm -Xint -XX:+UnlockDiagnosticVMOptions -XX:+UseContinuationLazyCopy Scoped
+ * @run testng/othervm -Xint -XX:+UseContinuationLazyCopy Scoped
  * @run testng/othervm -Xcomp -XX:CompileOnly=java/lang/Continuation,Scoped -XX:-UseContinuationLazyCopy Scoped
- * @run testng/othervm -Xcomp -XX:CompileOnly=java/lang/Continuation,Scoped -XX:+UnlockDiagnosticVMOptions -XX:+UseContinuationLazyCopy Scoped
+ * @run testng/othervm -Xcomp -XX:CompileOnly=java/lang/Continuation,Scoped -XX:+UseContinuationLazyCopy Scoped
  */
 
 import java.util.Arrays;