< prev index next > src/hotspot/share/oops/oop.inline.hpp
Print this page
markWord* oopDesc::mark_addr() const {
return (markWord*) &_mark;
}
void oopDesc::set_mark(markWord m) {
Atomic::store(&_mark, m);
}
void oopDesc::set_mark(HeapWord* mem, markWord m) {
! *(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);
}
void oopDesc::release_set_mark(markWord m) {
! Atomic::release_store(&_mark, m);
}
markWord oopDesc::cas_set_mark(markWord new_mark, markWord old_mark) {
return Atomic::cmpxchg(&_mark, old_mark, new_mark);
}
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) {
! 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) {
! 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) {
! 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);
}
return markWord::prototype();
}
}
void oopDesc::init_mark() {
! set_mark(prototype_mark());
}
Klass* oopDesc::klass() const {
switch (ObjLayout::klass_mode()) {
case ObjLayout::Compact:
return markWord::prototype();
}
}
void oopDesc::init_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:
bool oopDesc::is_a(Klass* k) const {
return klass()->is_subtype_of(k);
}
size_t oopDesc::size() {
! return size_given_klass(klass());
}
! size_t oopDesc::size_given_klass(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
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_mark_and_klass(mark(), 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
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);
}
} 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_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");
} else {
// Must be zero, so bite the bullet and take the virtual call.
! s = klass->oop_size(this);
}
}
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);
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, 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;
+ #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;
! 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, 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);
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);
}
void oopDesc::forward_to_self() {
set_mark(mark().set_self_forwarded());
}
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_full(m);
}
void oopDesc::forward_to_self() {
set_mark(mark().set_self_forwarded());
}
}
template <typename OopClosureType>
size_t oopDesc::oop_iterate_size(OopClosureType* cl) {
Klass* k = klass();
! size_t size = size_given_klass(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);
OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k, mr);
return size;
}
template <typename OopClosureType>
}
template <typename OopClosureType>
size_t oopDesc::oop_iterate_size(OopClosureType* cl) {
Klass* k = klass();
! 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_mark_and_klass(mark(), k);
OopIteratorClosureDispatch::oop_oop_iterate(cl, this, k, mr);
return size;
}
template <typename OopClosureType>
}
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();
} else {
! 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();
}
bool oopDesc::has_displaced_mark() const {
return mark().has_displaced_mark_helper();
}
}
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.
! 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 {
! 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 (UseCompactObjectHeaders || mrk.is_unlocked()) && mrk.has_no_hash();
}
bool oopDesc::has_displaced_mark() const {
return mark().has_displaced_mark_helper();
}
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 >