diff a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp
--- a/src/hotspot/share/oops/oop.hpp
+++ b/src/hotspot/share/oops/oop.hpp
@@ -73,10 +73,11 @@
   inline markWord  mark_acquire()  const;
   inline markWord* mark_addr() const;
 
   inline void set_mark(markWord m);
   static inline void set_mark(HeapWord* mem, markWord m);
+  inline void set_mark_full(markWord m);
   static inline void release_set_mark(HeapWord* mem, markWord m);
 
   inline void release_set_mark(markWord m);
   inline markWord cas_set_mark(markWord new_mark, markWord old_mark);
   inline markWord cas_set_mark(markWord new_mark, markWord old_mark, atomic_memory_order order);
@@ -114,13 +115,36 @@
   inline bool is_a(Klass* k) const;
 
   // Returns the actual oop size of the object in machine words
   inline size_t size();
 
+  // Returns the size that a copy of this object requires, in machine words.
+  // It can be 1 word larger than its current size to accomodate
+  // an additional 4-byte-field for the identity hash-code.
+  //
+  // size: the current size of this object, we're passing this here for performance
+  //       reasons, because all callers compute this anyway, and we want to avoid
+  //       recomputing it.
+  // mark: the mark-word of this object. Some callers (e.g. G1ParScanThreadState::do_copy_to_survivor_space())
+  //       need to use a known markWord because of racing GC threads that can change
+  //       the markWord at any time.
+  inline size_t copy_size(size_t size, markWord mark) const;
+  // Special version to deal with scratch classes in CDS. There we allocate
+  // temporary scratch classes (which are skeleton versions of InstanceMirrorKlass,
+  // which represent java.lang.Class objects in the CDS archive). At that point, we
+  // don't know whether or not the final archived version will be hashed or expanded,
+  // and therefore we allocate them in the special state not-hashed-but-expanded.
+  // When creating the final copy of those objects, we either populate the hidden hash
+  // field and make the object 'expanded', or we turn it back to 'not-hashed'
+  // and reduce the object's size. We do this by providing a separate method for CDS
+  // so that we don't affect GC performance.
+  inline size_t copy_size_cds(size_t size, markWord mark) const;
+
   // Sometimes (for complicated concurrency-related reasons), it is useful
   // to be able to figure out the size of an object knowing its klass.
-  inline size_t size_given_klass(Klass* klass);
+  inline size_t base_size_given_klass(markWord m, const Klass* klass);
+  inline size_t size_given_mark_and_klass(markWord mrk, const Klass* kls);
 
   // type test operations (inlined in oop.inline.hpp)
   inline bool is_instance()    const;
   inline bool is_instanceRef() const;
   inline bool is_stackChunk()  const;
@@ -284,10 +308,11 @@
 
   inline oop forwardee() const;
   inline oop forwardee(markWord header) const;
 
   inline void unset_self_forwarded();
+  inline void reset_forwarded();
 
   // Age of object during scavenge
   inline uint age() const;
   inline void incr_age();
 
@@ -314,10 +339,16 @@
   // identity hash; returns the identity hash key (computes it if necessary)
   inline intptr_t identity_hash();
   intptr_t slow_identity_hash();
   inline bool fast_no_hash_check();
 
+  // Initialize identity hash code in hash word of object copy from original object.
+  // Returns true if the object has been expanded, false otherwise.
+  inline void initialize_hash_if_necessary(oop obj);
+  // For CDS only.
+  void initialize_hash_if_necessary(oop obj, Klass* k, markWord m);
+
   // marks are forwarded to stack when object is locked
   inline bool     has_displaced_mark() const;
   inline markWord displaced_mark() const;
   inline void     set_displaced_mark(markWord m);
 
@@ -330,24 +361,20 @@
   }
 
   // for code generation
   static int mark_offset_in_bytes()      { return (int)offset_of(oopDesc, _mark); }
   static int klass_offset_in_bytes()     {
-#ifdef _LP64
-    if (UseCompactObjectHeaders) {
-      // NOTE: The only places where this is used with compact headers are the C2
-      // compiler and JVMCI.
-      return mark_offset_in_bytes() + markWord::klass_offset_in_bytes;
-    } else
-#endif
-    {
-      return (int)offset_of(oopDesc, _metadata._klass);
-    }
+    assert(!UseCompactObjectHeaders, "don't use this with compact headers");
+    return (int)offset_of(oopDesc, _metadata._klass);
   }
   static int klass_gap_offset_in_bytes() {
     assert(has_klass_gap(), "only applicable to compressed klass pointers");
-    return klass_offset_in_bytes() + sizeof(narrowKlass);
+    if (UseCompactObjectHeaders) {
+      return base_offset_in_bytes();
+    } else {
+      return klass_offset_in_bytes() + sizeof(narrowKlass);
+    }
   }
 
   static int base_offset_in_bytes() {
     return ObjLayout::oop_base_offset_in_bytes();
   }
