diff a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp
--- a/src/hotspot/share/runtime/objectMonitor.hpp
+++ b/src/hotspot/share/runtime/objectMonitor.hpp
@@ -147,14 +147,16 @@
   //   we achieve this by using the lowest two bits.
   // - ANONYMOUS_OWNER should be a small value, it is used in generated code
   //   and small values encode much better.
   // - We test for anonymous owner by testing for the lowest bit, therefore
   //   DEFLATER_MARKER must *not* have that bit set.
-  #define DEFLATER_MARKER reinterpret_cast<void*>(2)
+  static const uintptr_t DEFLATER_MARKER_VALUE = 2;
+  #define DEFLATER_MARKER reinterpret_cast<void*>(DEFLATER_MARKER_VALUE)
 public:
   // NOTE: Typed as uintptr_t so that we can pick it up in SA, via vmStructs.
   static const uintptr_t ANONYMOUS_OWNER = 1;
+  static const uintptr_t ANONYMOUS_OWNER_OR_DEFLATER_MARKER = ANONYMOUS_OWNER | DEFLATER_MARKER_VALUE;
 
 private:
   static void* anon_owner_ptr() { return reinterpret_cast<void*>(ANONYMOUS_OWNER); }
 
   void* volatile _owner;            // pointer to owning thread OR BasicLock
@@ -211,10 +213,11 @@
   static PerfCounter * _sync_Deflations;
   static PerfLongVariable * _sync_MonExtant;
 
   static int Knob_SpinLimit;
 
+  static ByteSize header_offset()      { return byte_offset_of(ObjectMonitor, _header); }
   static ByteSize owner_offset()       { return byte_offset_of(ObjectMonitor, _owner); }
   static ByteSize recursions_offset()  { return byte_offset_of(ObjectMonitor, _recursions); }
   static ByteSize cxq_offset()         { return byte_offset_of(ObjectMonitor, _cxq); }
   static ByteSize succ_offset()        { return byte_offset_of(ObjectMonitor, _succ); }
   static ByteSize EntryList_offset()   { return byte_offset_of(ObjectMonitor, _EntryList); }
@@ -228,17 +231,25 @@
   // offset or we can adjust the offset that is added to the ObjectMonitor
   // reference. The latter avoids an AGI (Address Generation Interlock)
   // stall so the helper macro adjusts the offset value that is returned
   // to the ObjectMonitor reference manipulation code:
   //
+  // Lightweight locking fetches ObjectMonitor references from a cache
+  // instead of the markWord and doesn't work with tagged values.
+  //
   #define OM_OFFSET_NO_MONITOR_VALUE_TAG(f) \
-    ((in_bytes(ObjectMonitor::f ## _offset())) - checked_cast<int>(markWord::monitor_value))
+    ((in_bytes(ObjectMonitor::f ## _offset())) - (LockingMode == LM_LIGHTWEIGHT ? 0 : checked_cast<int>(markWord::monitor_value)))
 
   markWord           header() const;
+  uintptr_t          header_value() const;
   volatile markWord* header_addr();
   void               set_header(markWord hdr);
 
+  // TODO[OMWorld]: Cleanup these names, the storage `_header` usage depends on the locking mode.
+  intptr_t           hash_lightweight_locking() const;
+  void               set_hash_lightweight_locking(intptr_t hash);
+
   bool is_busy() const {
     // TODO-FIXME: assert _owner == null implies _recursions = 0
     intptr_t ret_code = intptr_t(_waiters) | intptr_t(_cxq) | intptr_t(_EntryList);
     int cnts = contentions(); // read once
     if (cnts > 0) {
@@ -247,10 +258,18 @@
     if (!owner_is_DEFLATER_MARKER()) {
       ret_code |= intptr_t(owner_raw());
     }
     return ret_code != 0;
   }
+  bool is_contended() const {
+    intptr_t ret_code = intptr_t(_waiters) | intptr_t(_cxq) | intptr_t(_EntryList);
+    int cnts = contentions();
+    if (cnts > 0) {
+      ret_code |= intptr_t(cnts);
+    }
+    return ret_code != 0;
+  }
   const char* is_busy_to_string(stringStream* ss);
 
   bool is_entered(JavaThread* current) const;
 
   // Returns true if this OM has an owner, false otherwise.
@@ -304,10 +323,13 @@
   ObjectMonitor(oop object);
   ~ObjectMonitor();
 
   oop       object() const;
   oop       object_peek() const;
+  bool      object_is_cleared() const;
+  bool      object_is_dead() const;
+  bool      object_refers_to(oop obj) const;
 
   // Returns true if the specified thread owns the ObjectMonitor. Otherwise
   // returns false and throws IllegalMonitorStateException (IMSE).
   bool      check_owner(TRAPS);
 
@@ -327,10 +349,11 @@
    public:
     ClearSuccOnSuspend(ObjectMonitor* om) : _om(om)  {}
     void operator()(JavaThread* current);
   };
  public:
+  bool      try_enter(JavaThread* current);
   bool      enter_for(JavaThread* locking_thread);
   bool      enter(JavaThread* current);
   void      exit(JavaThread* current, bool not_suspended = true);
   void      wait(jlong millis, bool interruptible, TRAPS);
   void      notify(TRAPS);
@@ -356,10 +379,23 @@
   int       TryLock(JavaThread* current);
   int       TrySpin(JavaThread* current);
   void      ExitEpilog(JavaThread* current, ObjectWaiter* Wakee);
 
   // Deflation support
-  bool      deflate_monitor();
+  bool      deflate_monitor(Thread* current);
+public:
+  bool      deflate_anon_monitor(JavaThread* current);
+private:
   void      install_displaced_markword_in_object(const oop obj);
 };
 
+// RAII object to ensure that ObjectMonitor::is_being_async_deflated() is
+// stable within the context of this mark.
+class ObjectMonitorContentionMark {
+  ObjectMonitor* _monitor;
+
+public:
+  ObjectMonitorContentionMark(ObjectMonitor* monitor);
+  ~ObjectMonitorContentionMark();
+};
+
 #endif // SHARE_RUNTIME_OBJECTMONITOR_HPP
