Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register reg_rax, Register t,

// Try to unlock. Transition lock bits 0b00 => 0b01
movptr(reg_rax, mark);
andptr(reg_rax, ~(int32_t)markWord::lock_mask);
andptr(reg_rax, ~(int32_t)markWord::lock_mask_in_place);
orptr(mark, markWord::unlocked_value);
lock(); cmpxchgptr(mark, Address(obj, oopDesc::mark_offset_in_bytes()));
jcc(Assembler::notEqual, push_and_slow_path);
Expand Down
107 changes: 67 additions & 40 deletions src/hotspot/share/oops/markWord.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,39 +30,52 @@
#include "oops/compressedKlass.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/globals.hpp"
#include "utilities/powerOfTwo.hpp"

// The markWord describes the header of an object.
//
// Bit-format of an object header (most significant first, big endian layout below):
//
// 32 bits:
// --------
// hash:25 ------------>| age:4 self-fwd:1 lock:2 (normal object)
// hash:25 age:4 self-fwd:1 lock:2
//
// 64 bits:
// --------
// unused:22 hash:31 -->| unused_gap:4 age:4 self-fwd:1 lock:2 (normal object)
// 64 bits (without compact headers):
// ----------------------------------
// unused:22 hash:31 valhalla:4 age:4 self-fwd:1 lock:2
//
// 64 bits (with compact headers):
// -------------------------------
// klass:22 hash:31 -->| unused_gap:4 age:4 self-fwd:1 lock:2 (normal object)
//
// - hash contains the identity hash value: largest value is
// 31 bits, see os::random(). Also, 64-bit vm's require
// a hash value no bigger than 32 bits because they will not
// properly generate a mask larger than that: see library_call.cpp
// klass:22 hash:31 valhalla:4 age:4 self-fwd:1 lock:2
//
// - the two lock bits are used to describe three states: locked/unlocked and monitor.
// - lock bits are used to describe lock states: locked/unlocked/monitor-locked
// and to indicate that an object has been GC marked / forwarded.
//
// [header | 00] locked locked regular object header (fast-locking in use)
// [header | 01] unlocked regular object header
// [ptr | 10] monitor inflated lock (header is swapped out, UseObjectMonitorTable == false)
// [header | 10] monitor inflated lock (UseObjectMonitorTable == true)
// [ptr | 11] marked used to mark an object
// [ptr | 10] monitor inflated lock (UseObjectMonitorTable == false, header is swapped out)
// [ptr | 11] marked used to mark an object (header is swapped out)
//
// - self-fwd - used by some GCs to indicate in-place forwarding.
//
// Note the position of 'self-fwd' is not by accident. When forwarding an
// object to a new heap position, HeapWord alignment guarantees the lower
// bits, including 'self-fwd' are 0. "is_self_forwarded()" will be correctly
// set to false. Otherwise encode_pointer_as_mark() may have 'self-fwd' set.
//
// - age - used by some GCs to track the age of objects.
//
// - valhalla - reserved for valhalla
//
// - hash - contains the identity hash value: largest value is 31 bits, see
// os::random(). Also, 64-bit VMs require a hash value no bigger than 32
// bits because they will not properly generate a mask larger than that:
// see library_call.cpp
//
// - klass - klass identifier used when UseCompactObjectHeaders == true

class BasicLock;
class ObjectMonitor;
class JavaThread;
class outputStream;

class markWord {
Expand Down Expand Up @@ -97,33 +110,42 @@ class markWord {
// Conversion
uintptr_t value() const { return _value; }

// Constants
static const int age_bits = 4;
// Constants, in least significant bit order

// Number of bits
static const int lock_bits = 2;
static const int self_fwd_bits = 1;
static const int max_hash_bits = BitsPerWord - age_bits - lock_bits - self_fwd_bits;
static const int age_bits = 4;
static const int valhalla_reserved_bits = LP64_ONLY(4) NOT_LP64(0);
static const int max_hash_bits = BitsPerWord - age_bits - lock_bits - self_fwd_bits - valhalla_reserved_bits;
static const int hash_bits = max_hash_bits > 31 ? 31 : max_hash_bits;
static const int unused_gap_bits = LP64_ONLY(4) NOT_LP64(0); // Reserved for Valhalla.

// Shifts
static const int lock_shift = 0;
static const int self_fwd_shift = lock_shift + lock_bits;
static const int age_shift = self_fwd_shift + self_fwd_bits;
static const int hash_shift = age_shift + age_bits + unused_gap_bits;
static const int valhalla_reserved_shift = age_shift + age_bits;
static const int hash_shift = valhalla_reserved_shift + valhalla_reserved_bits;

// Masks (in-place)
static const uintptr_t lock_mask_in_place = right_n_bits(lock_bits) << lock_shift;
static const uintptr_t self_fwd_bit_in_place = right_n_bits(self_fwd_bits) << self_fwd_shift;
static const uintptr_t age_mask_in_place = right_n_bits(age_bits) << age_shift;
static const uintptr_t hash_mask_in_place = right_n_bits(hash_bits) << hash_shift;

// Verify that _bit_in_place refers to constants with only one bit.
static_assert(is_power_of_2(self_fwd_bit_in_place));

static const uintptr_t lock_mask = right_n_bits(lock_bits);
static const uintptr_t lock_mask_in_place = lock_mask << lock_shift;
static const uintptr_t self_fwd_mask = right_n_bits(self_fwd_bits);
static const uintptr_t self_fwd_mask_in_place = self_fwd_mask << self_fwd_shift;
static const uintptr_t age_mask = right_n_bits(age_bits);
static const uintptr_t age_mask_in_place = age_mask << age_shift;
static const uintptr_t hash_mask = right_n_bits(hash_bits);
static const uintptr_t hash_mask_in_place = hash_mask << hash_shift;
// Masks (unshifted)
static const uintptr_t lock_mask = lock_mask_in_place >> lock_shift;
static const uintptr_t age_mask = age_mask_in_place >> age_shift;
static const uintptr_t hash_mask = hash_mask_in_place >> hash_shift;

#ifdef _LP64
// Used only with compact headers:
// We store the (narrow) Klass* in the bits 43 to 64.

// These are for bit-precise extraction of the narrow Klass* from the 64-bit Markword
// These are for bit-precise extraction of the narrow Klass* from the 64-bit markWord
static constexpr int klass_offset_in_bytes = 4;
static constexpr int klass_shift = hash_shift + hash_bits;
static constexpr int klass_shift_at_offset = klass_shift - klass_offset_in_bytes * BitsPerByte;
Expand All @@ -132,7 +154,6 @@ class markWord {
static constexpr uintptr_t klass_mask_in_place = klass_mask << klass_shift;
#endif


static const uintptr_t locked_value = 0;
static const uintptr_t unlocked_value = 1;
static const uintptr_t monitor_value = 2;
Expand All @@ -157,17 +178,19 @@ class markWord {
bool is_marked() const {
return (mask_bits(value(), lock_mask_in_place) == marked_value);
}
bool is_forwarded() const {
// Returns true for normal forwarded (0b011) and self-forwarded (0b1xx).
return mask_bits(value(), lock_mask_in_place | self_fwd_mask_in_place) >= static_cast<intptr_t>(marked_value);
}

bool is_neutral() const { // Not locked, or marked - a "clean" neutral state
return (mask_bits(value(), lock_mask_in_place) == unlocked_value);
}

bool is_forwarded() const {
// Returns true for normal forwarded (0b011) and self-forwarded (0b1xx).
return mask_bits(value(), lock_mask_in_place | self_fwd_bit_in_place) >= static_cast<intptr_t>(marked_value);
}

// Should this header be preserved during GC?
bool must_be_preserved() const {
return (!is_unlocked() || !has_no_hash());
return !is_unlocked() || !has_no_hash();
}

// WARNING: The following routines are used EXCLUSIVELY by
Expand Down Expand Up @@ -204,10 +227,14 @@ class markWord {
return markWord(tmp | monitor_value);
}

bool has_displaced_mark_helper() const {
bool has_monitor_pointer() const {
intptr_t lockbits = value() & lock_mask_in_place;
return !UseObjectMonitorTable && lockbits == monitor_value;
}

bool has_displaced_mark_helper() const {
return has_monitor_pointer();
}
markWord displaced_mark_helper() const;
void set_displaced_mark_helper(markWord m) const;

Expand Down Expand Up @@ -248,7 +275,7 @@ class markWord {

// Prototype mark for initialization
static markWord prototype() {
return markWord( no_hash_in_place | no_lock_in_place );
return markWord(unlocked_value);
}

// Debugging
Expand All @@ -261,15 +288,15 @@ class markWord {
inline void* decode_pointer() const { return (void*)clear_lock_bits().value(); }

inline bool is_self_forwarded() const {
return mask_bits(value(), self_fwd_mask_in_place) != 0;
return mask_bits(value(), self_fwd_bit_in_place) != 0;
}

inline markWord set_self_forwarded() const {
return markWord(value() | self_fwd_mask_in_place);
return markWord(value() | self_fwd_bit_in_place);
}

inline markWord unset_self_forwarded() const {
return markWord(value() & ~self_fwd_mask_in_place);
return markWord(value() & ~self_fwd_bit_in_place);
}

inline oop forwardee() const {
Expand Down