< prev index next >

src/hotspot/share/oops/oop.inline.hpp

Print this page
@@ -58,23 +58,43 @@
  markWord* oopDesc::mark_addr() const {
    return (markWord*) &_mark;
  }
  
  void oopDesc::set_mark(markWord m) {
+   if (UseCompactObjectHeaders) {
+     Atomic::store(reinterpret_cast<uint32_t volatile*>(&_mark), m.value32());
+   } else {
+     Atomic::store(&_mark, m);
+   }
+ }
+ 
+ void oopDesc::set_mark_full(markWord m) {
    Atomic::store(&_mark, m);
  }
  
  void oopDesc::set_mark(HeapWord* mem, markWord m) {
-   *(markWord*)(((char*)mem) + mark_offset_in_bytes()) = m;
+   if (UseCompactObjectHeaders) {
+     *(uint32_t*)(((char*)mem) + mark_offset_in_bytes()) = m.value32();
+   } else {
+     *(markWord*)(((char*)mem) + mark_offset_in_bytes()) = m;
+   }
  }
  
  void oopDesc::release_set_mark(HeapWord* mem, markWord m) {
-   Atomic::release_store((markWord*)(((char*)mem) + mark_offset_in_bytes()), m);
+   if (UseCompactObjectHeaders) {
+     Atomic::release_store((uint32_t*)(((char*)mem) + mark_offset_in_bytes()), m.value32());
+   } else {
+     Atomic::release_store((markWord*)(((char*)mem) + mark_offset_in_bytes()), m);
+   }
  }
  
  void oopDesc::release_set_mark(markWord m) {
-   Atomic::release_store(&_mark, m);
+   if (UseCompactObjectHeaders) {
+     Atomic::release_store(reinterpret_cast<uint32_t volatile*>(&_mark), m.value32());
+   } else {
+     Atomic::release_store(&_mark, m);
+   }
  }
  
  markWord oopDesc::cas_set_mark(markWord new_mark, markWord old_mark) {
    return Atomic::cmpxchg(&_mark, old_mark, new_mark);
  }

@@ -90,11 +110,17 @@
      return markWord::prototype();
    }
  }
  
  void oopDesc::init_mark() {
-   set_mark(prototype_mark());
+   if (UseCompactObjectHeaders) {
+     markWord m = prototype_mark().copy_hashctrl_from(mark());
+     assert(m.is_neutral(), "must be neutral");
+     set_mark(m);
+   } else {
+     set_mark(prototype_mark());
+   }
  }
  
  Klass* oopDesc::klass() const {
    switch (ObjLayout::klass_mode()) {
      case ObjLayout::Compact:

@@ -170,15 +196,53 @@
  
  bool oopDesc::is_a(Klass* k) const {
    return klass()->is_subtype_of(k);
  }
  
+ size_t oopDesc::size_given_mark_and_klass(markWord mrk, const Klass* kls) {
+   size_t sz = base_size_given_klass(mrk, kls);
+   if (UseCompactObjectHeaders) {
+     assert(!mrk.has_displaced_mark_helper(), "must not be displaced");
+     if (mrk.is_expanded() && kls->expand_for_hash(cast_to_oop(this))) {
+       sz = align_object_size(sz + 1);
+     }
+   }
+   return sz;
+ }
+ 
+ size_t oopDesc::copy_size(size_t size, markWord mark) const {
+   if (UseCompactObjectHeaders) {
+     assert(!mark.has_displaced_mark_helper(), "must not be displaced");
+     Klass* klass = mark.klass();
+     if (mark.is_hashed_not_expanded() && klass->expand_for_hash(cast_to_oop(this))) {
+       size = align_object_size(size + 1);
+     }
+   }
+   assert(is_object_aligned(size), "Oop size is not properly aligned: " SIZE_FORMAT, size);
+   return size;
+ }
+ 
+ size_t oopDesc::copy_size_cds(size_t size, markWord mark) const {
+   if (UseCompactObjectHeaders) {
+     assert(!mark.has_displaced_mark_helper(), "must not be displaced");
+     Klass* klass = mark.klass();
+     if (mark.is_hashed_not_expanded() && klass->expand_for_hash(cast_to_oop(this))) {
+       size = align_object_size(size + 1);
+     }
+     if (mark.is_not_hashed_expanded() && klass->expand_for_hash(cast_to_oop(this))) {
+       size = align_object_size(size - ObjectAlignmentInBytes / HeapWordSize);
+     }
+   }
+   assert(is_object_aligned(size), "Oop size is not properly aligned: " SIZE_FORMAT, size);
+   return size;
+ }
+ 
  size_t oopDesc::size()  {
-   return size_given_klass(klass());
+   return size_given_mark_and_klass(mark(), klass());
  }
  
- size_t oopDesc::size_given_klass(Klass* klass)  {
+ size_t oopDesc::base_size_given_klass(markWord mrk, const Klass* klass)  {
    int lh = klass->layout_helper();
    size_t s;
  
    // lh is now a value computed at class initialization that may hint
    // at the size.  For instances, this is positive and equal to the

@@ -193,32 +257,43 @@
  
    if (lh > Klass::_lh_neutral_value) {
      if (!Klass::layout_helper_needs_slow_path(lh)) {
        s = lh >> LogHeapWordSize;  // deliver size scaled by wordSize
      } else {
-       s = klass->oop_size(this);
+       s = klass->oop_size(this, mrk);
      }
    } else if (lh <= Klass::_lh_neutral_value) {
      // The most common case is instances; fall through if so.
      if (lh < Klass::_lh_neutral_value) {
        // Second most common case is arrays.  We have to fetch the
        // length of the array, shift (multiply) it appropriately,
        // up to wordSize, add the header, and align to object size.
        size_t size_in_bytes;
-       size_t array_length = (size_t) ((arrayOop)this)->length();
+       size_t array_length;
+ #ifdef _LP64
+       if (UseCompactObjectHeaders) {
+         array_length = (size_t) mrk.array_length();
+       } else
+ #endif
+         array_length = (size_t)((arrayOop)this)->length();
+ 
        size_in_bytes = array_length << Klass::layout_helper_log2_element_size(lh);
        size_in_bytes += Klass::layout_helper_header_size(lh);
  
        // This code could be simplified, but by keeping array_header_in_bytes
        // in units of bytes and doing it this way we can round up just once,
        // skipping the intermediate round to HeapWordSize.
        s = align_up(size_in_bytes, MinObjAlignmentInBytes) / HeapWordSize;
- 
-       assert(s == klass->oop_size(this), "wrong array object size");
+       if (s != klass->oop_size(this, mrk)) {
+         tty->print_cr("length: " SIZE_FORMAT, array_length);
+         tty->print_cr("log element size: %d", Klass::layout_helper_log2_element_size(lh));
+         tty->print_cr("is_objArray: %s", BOOL_TO_STR(klass->is_objArray_klass()));
+       }
+       assert(s == klass->oop_size(this, mrk), "wrong array object size, s: " SIZE_FORMAT ", oop_size: " SIZE_FORMAT, s, klass->oop_size(this, mrk));
      } else {
        // Must be zero, so bite the bullet and take the virtual call.
-       s = klass->oop_size(this);
+       s = klass->oop_size(this, mrk);
      }
    }
  
    assert(s > 0, "Oop size must be greater than zero, not " SIZE_FORMAT, s);
    assert(is_object_aligned(s), "Oop size is not properly aligned: " SIZE_FORMAT, s);

@@ -298,11 +373,11 @@
  void oopDesc::forward_to(oop p) {
    assert(cast_from_oop<oopDesc*>(p) != this,
           "must not be used for self-forwarding, use forward_to_self() instead");
    markWord m = markWord::encode_pointer_as_mark(p);
    assert(m.decode_pointer() == p, "encoding must be reversible");
-   set_mark(m);
+   set_mark_full(m);
  }
  
  void oopDesc::forward_to_self() {
    set_mark(mark().set_self_forwarded());
  }

@@ -383,19 +458,19 @@
  }
  
  template <typename OopClosureType>
  size_t oopDesc::oop_iterate_size(OopClosureType* cl) {
    Klass* k = klass();
-   size_t size = size_given_klass(k);
+   size_t size = size_given_mark_and_klass(mark(), k);
    OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k);
    return size;
  }
  
  template <typename OopClosureType>
  size_t oopDesc::oop_iterate_size(OopClosureType* cl, MemRegion mr) {
    Klass* k = klass();
-   size_t size = size_given_klass(k);
+   size_t size = size_given_mark_and_klass(mark(), k);
    OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k, mr);
    return size;
  }
  
  template <typename OopClosureType>

@@ -415,26 +490,35 @@
  }
  
  intptr_t oopDesc::identity_hash() {
    // Fast case; if the object is unlocked and the hash value is set, no locking is needed
    // Note: The mark must be read into local variable to avoid concurrent updates.
-   markWord mrk = mark();
-   if (mrk.is_unlocked() && !mrk.has_no_hash()) {
-     return mrk.hash();
-   } else if (mrk.is_marked()) {
-     return mrk.hash();
+   if (UseCompactObjectHeaders) {
+     markWord mrk = mark();
+     if (mrk.is_hashed_expanded()) {
+       Klass* klass = mrk.klass();
+       return int_field(klass->hash_offset_in_bytes(cast_to_oop(this)));
+     }
+     // Fall-through to slow-case.
    } else {
-     return slow_identity_hash();
+     markWord mrk = mark();
+     if (mrk.is_unlocked() && !mrk.has_no_hash()) {
+       return mrk.hash();
+     } else if (mrk.is_marked()) {
+       return mrk.hash();
+     }
+     // Fall-through to slow-case.
    }
+   return slow_identity_hash();
  }
  
  // This checks fast simple case of whether the oop has_no_hash,
  // to optimize JVMTI table lookup.
  bool oopDesc::fast_no_hash_check() {
    markWord mrk = mark_acquire();
    assert(!mrk.is_marked(), "should never be marked");
-   return mrk.is_unlocked() && mrk.has_no_hash();
+   return (UseCompactObjectHeaders || mrk.is_unlocked()) && mrk.has_no_hash();
  }
  
  bool oopDesc::has_displaced_mark() const {
    return mark().has_displaced_mark_helper();
  }

@@ -453,6 +537,19 @@
  
  bool oopDesc::mark_must_be_preserved(markWord m) const {
    return m.must_be_preserved(this);
  }
  
+ inline void oopDesc::initialize_hash_if_necessary(oop obj) {
+   if (!UseCompactObjectHeaders) {
+     return;
+   }
+   markWord m = mark();
+   assert(!m.has_displaced_mark_helper(), "must not be displaced header");
+   assert(!m.is_forwarded(), "must not be forwarded header");
+   if (m.is_hashed_not_expanded()) {
+     initialize_hash_if_necessary(obj, m.klass(), m);
+   }
+ }
+ 
+ 
  #endif // SHARE_OOPS_OOP_INLINE_HPP
< prev index next >