diff a/src/hotspot/share/runtime/continuationHelper.inline.hpp b/src/hotspot/share/runtime/continuationHelper.inline.hpp
--- a/src/hotspot/share/runtime/continuationHelper.inline.hpp
+++ b/src/hotspot/share/runtime/continuationHelper.inline.hpp
@@ -30,10 +30,11 @@
 #include "code/scopeDesc.hpp"
 #include "compiler/oopMap.hpp"
 #include "compiler/oopMap.inline.hpp"
 #include "interpreter/oopMapCache.hpp"
 #include "runtime/frame.inline.hpp"
+#include "runtime/objectMonitor.hpp"
 #include "runtime/stackValue.hpp"
 #include "utilities/macros.hpp"
 
 #include CPU_HEADER_INLINE(continuationHelper)
 
@@ -51,11 +52,11 @@
 inline bool ContinuationHelper::NonInterpretedUnknownFrame::is_instance(const frame& f) {
   return !f.is_interpreted_frame();
 }
 
 inline bool ContinuationHelper::Frame::is_stub(CodeBlob* cb) {
-  return cb != nullptr && (cb->is_safepoint_stub() || cb->is_runtime_stub());
+  return cb != nullptr && cb->is_runtime_stub();
 }
 
 inline Method* ContinuationHelper::Frame::frame_method(const frame& f) {
   return f.is_interpreted_frame() ? f.interpreter_frame_method() : f.cb()->as_nmethod()->method();
 }
@@ -106,26 +107,54 @@
   assert(size <= f.interpreter_frame_expression_stack_size(), "size1: %d size2: %d", size, f.interpreter_frame_expression_stack_size());
   return size;
 }
 
 #ifdef ASSERT
-inline bool ContinuationHelper::InterpretedFrame::is_owning_locks(const frame& f) {
-  assert(f.interpreter_frame_monitor_end() <= f.interpreter_frame_monitor_begin(), "must be");
-  if (f.interpreter_frame_monitor_end() == f.interpreter_frame_monitor_begin()) {
-    return false;
+inline int ContinuationHelper::InterpretedFrame::monitors_to_fix(JavaThread* thread, const frame& f, ResourceHashtable<oopDesc*, bool> &table, stackChunkOop chunk) {
+  BasicObjectLock* first_mon = f.interpreter_frame_monitor_begin();
+  BasicObjectLock* last_mon = f.interpreter_frame_monitor_end();
+  assert(last_mon <= first_mon, "must be");
+
+  if (first_mon == last_mon) {
+    // No monitors in this frame
+    return 0;
   }
 
-  for (BasicObjectLock* current = f.previous_monitor_in_interpreter_frame(f.interpreter_frame_monitor_begin());
-        current >= f.interpreter_frame_monitor_end();
-        current = f.previous_monitor_in_interpreter_frame(current)) {
+  int monitor_count = 0;
+  oop monitorenter_oop = thread->is_on_monitorenter() ? thread->current_pending_monitor()->object() : nullptr;
 
-      oop obj = current->obj();
-      if (obj != nullptr) {
-        return true;
+  for (BasicObjectLock* current = f.previous_monitor_in_interpreter_frame(first_mon);
+       current >= last_mon; current = f.previous_monitor_in_interpreter_frame(current)) {
+    oop* obj_adr = current->obj_adr();
+
+    oop obj;
+    if (f.is_heap_frame()) {
+      assert(chunk != nullptr, "null stackChunk");
+      obj = chunk->has_bitmap() && UseCompressedOops ? chunk->load_oop((narrowOop*)obj_adr) : chunk->load_oop(obj_adr);
+    } else {
+      // We have already processed oops when getting this frame.
+      obj = *obj_adr;
+    }
+    assert(obj == nullptr || dbg_is_good_oop(obj), "obj_adr: " PTR_FORMAT " obj: " PTR_FORMAT, p2i(obj_adr), p2i(obj));
+
+    if (obj != nullptr && obj != monitorenter_oop) {
+      markWord mark = obj->mark();
+      if (mark.has_monitor() && !mark.monitor()->is_owner_anonymous()) {
+        // Nothing to do
+        assert(mark.monitor()->is_owner(thread), "invariant");
+        continue;
+      }
+      assert(!f.is_heap_frame() || LockingMode == LM_LIGHTWEIGHT,
+             "monitors found on heap frame that need to be fixed should only be those saved in the LockStack");
+      bool created;
+      table.put_if_absent(obj, true, &created);
+      if (created) {
+        monitor_count++;
       }
+    }
   }
-  return false;
+  return monitor_count;
 }
 #endif
 
 inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f) { // inclusive; this will be copied with the frame
   return f.unextended_sp();
@@ -154,46 +183,100 @@
 
 inline bool ContinuationHelper::CompiledFrame::is_instance(const frame& f) {
   return f.is_compiled_frame();
 }
 
+inline bool ContinuationHelper::NativeFrame::is_instance(const frame& f) {
+  return f.is_native_frame();
+}
+
 #ifdef ASSERT
 template<typename RegisterMapT>
-bool ContinuationHelper::CompiledFrame::is_owning_locks(JavaThread* thread, RegisterMapT* map, const frame& f) {
+int ContinuationHelper::CompiledFrame::monitors_to_fix(JavaThread* thread, RegisterMapT* map, const frame& f, ResourceHashtable<oopDesc*, bool> &table) {
   assert(!f.is_interpreted_frame(), "");
   assert(CompiledFrame::is_instance(f), "");
 
   nmethod* nm = f.cb()->as_nmethod();
-  assert(!nm->is_native_method(), ""); // See compiledVFrame::compiledVFrame(...) in vframe_hp.cpp
+  assert(!nm->is_nmethod() || !nm->as_nmethod()->is_native_method(), ""); // See compiledVFrame::compiledVFrame(...) in vframe_hp.cpp
 
   if (!nm->has_monitors()) {
-    return false;
+    // No monitors in this frame
+    return 0;
   }
 
-  frame::update_map_with_saved_link(map, Frame::callee_link_address(f)); // the monitor object could be stored in the link register
-  ResourceMark rm;
+  int monitor_count = 0;
+  oop monitorenter_oop = thread->is_on_monitorenter() ? thread->current_pending_monitor()->object() : nullptr;
+
   for (ScopeDesc* scope = nm->scope_desc_at(f.pc()); scope != nullptr; scope = scope->sender()) {
     GrowableArray<MonitorValue*>* mons = scope->monitors();
     if (mons == nullptr || mons->is_empty()) {
       continue;
     }
 
     for (int index = (mons->length()-1); index >= 0; index--) { // see compiledVFrame::monitors()
       MonitorValue* mon = mons->at(index);
       if (mon->eliminated()) {
-        continue; // we ignore scalar-replaced monitors
+        continue; // we ignore eliminated monitors
       }
+
       ScopeValue* ov = mon->owner();
       StackValue* owner_sv = StackValue::create_stack_value(&f, map, ov); // it is an oop
       oop owner = owner_sv->get_obj()();
-      if (owner != nullptr) {
-        //assert(nm->has_monitors(), "");
-        return true;
+      if (owner != nullptr && owner != monitorenter_oop) {
+        markWord mark = owner->mark();
+        if (mark.has_monitor() && !mark.monitor()->is_owner_anonymous()) {
+          // Nothing to do
+          assert(mark.monitor()->is_owner(thread), "invariant");
+          continue;
+        }
+        assert(!f.is_heap_frame() || LockingMode == LM_LIGHTWEIGHT,
+             "monitors found on heap frame that need to be fixed should only be those saved in the LockStack");
+        bool created;
+        table.put_if_absent(owner, true, &created);
+        if (created) {
+          monitor_count++;
+        }
       }
     }
   }
-  return false;
+  return monitor_count;
+}
+
+inline int ContinuationHelper::NativeFrame::monitors_to_fix(JavaThread* thread, const frame& f, ResourceHashtable<oopDesc*, bool> &table) {
+  assert(NativeFrame::is_instance(f), "");
+
+  Method* method = f.cb()->as_nmethod()->method();
+  if (!method->is_synchronized()) {
+    return 0;
+  }
+
+  oop synced_obj = f.get_native_receiver();
+  oop monitorenter_oop = thread->is_on_monitorenter() ? thread->current_pending_monitor()->object() : nullptr;
+
+  bool is_first_frame = f.sp() == thread->last_Java_sp();
+  if (!is_first_frame) {
+    assert(ObjectSynchronizer::current_thread_holds_lock(thread, Handle(thread, synced_obj)), "must be owner");
+    assert(monitorenter_oop == nullptr || monitorenter_oop != synced_obj, "owner already, should not be contended");
+
+    markWord mark = synced_obj->mark();
+    if (mark.has_monitor() && !mark.monitor()->is_owner_anonymous()) {
+      // Nothing to do
+      assert(mark.monitor()->is_owner(thread), "invariant");
+      return 0;
+    }
+    assert(!f.is_heap_frame(), "native frame on the heap???");
+    bool created;
+    table.put_if_absent(synced_obj, true, &created);
+    if (created) {
+      return 1;
+    }
+  } else {
+    assert(thread->is_on_monitorenter() && monitorenter_oop != nullptr && monitorenter_oop == synced_obj,
+           "should be freeze case due to preempt on monitorenter contention");
+    assert(!ObjectSynchronizer::current_thread_holds_lock(thread, Handle(thread, synced_obj)), "should not be owner");
+  }
+  return 0;
 }
 #endif
 
 inline bool ContinuationHelper::StubFrame::is_instance(const frame& f) {
   return !f.is_interpreted_frame() && is_stub(f.cb());
