< prev index next >

src/hotspot/share/runtime/continuationHelper.inline.hpp

Print this page
*** 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 ***
  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());
  }
  
  inline Method* ContinuationHelper::Frame::frame_method(const frame& f) {
    return f.is_interpreted_frame() ? f.interpreter_frame_method() : f.cb()->as_nmethod()->method();
  }
--- 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_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 ***
    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;
    }
  
!   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)) {
  
!       oop obj = current->obj();
!       if (obj != nullptr) {
!         return true;
        }
    }
!   return false;
  }
  #endif
  
  inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f) { // inclusive; this will be copied with the frame
    return f.unextended_sp();
--- 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 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;
    }
  
!   int monitor_count = 0;
!   oop monitorenter_oop = thread->is_on_monitorenter() ? thread->current_pending_monitor()->object() : nullptr;
  
!   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 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 ***
  
  inline bool ContinuationHelper::CompiledFrame::is_instance(const frame& f) {
    return f.is_compiled_frame();
  }
  
  #ifdef ASSERT
  template<typename RegisterMapT>
! bool ContinuationHelper::CompiledFrame::is_owning_locks(JavaThread* thread, RegisterMapT* map, const frame& f) {
    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
  
    if (!nm->has_monitors()) {
!     return false;
    }
  
!   frame::update_map_with_saved_link(map, Frame::callee_link_address(f)); // the monitor object could be stored in the link register
!   ResourceMark rm;
    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
        }
        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;
        }
      }
    }
!   return false;
  }
  #endif
  
  inline bool ContinuationHelper::StubFrame::is_instance(const frame& f) {
    return !f.is_interpreted_frame() && is_stub(f.cb());
--- 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>
! 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_nmethod() || !nm->as_nmethod()->is_native_method(), ""); // See compiledVFrame::compiledVFrame(...) in vframe_hp.cpp
  
    if (!nm->has_monitors()) {
!     // No monitors in this frame
+     return 0;
    }
  
!   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 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 && 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 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());
< prev index next >