|
44 | 44 | // |
45 | 45 | // 64 bits: |
46 | 46 | // -------- |
47 | | -// unused:22 hash:31 -->| unused_gap:4 age:4 self-fwd:1 lock:2 (normal object) |
| 47 | +// unused:22 hash:31 -->| valhalla:4 age:4 self-fwd:1 lock:2 (normal object) |
48 | 48 | // |
49 | 49 | // 64 bits (with compact headers): |
50 | 50 | // ------------------------------- |
51 | | -// klass:22 hash:31 -->| unused_gap:4 age:4 self-fwd:1 lock:2 (normal object) |
| 51 | +// klass:22 hash:31 -->| valhalla:4 age:4 self-fwd:1 lock:2 (normal object) |
52 | 52 | // |
53 | 53 | // - hash contains the identity hash value: largest value is |
54 | 54 | // 31 bits, see os::random(). Also, 64-bit vm's require |
|
72 | 72 | // used when inflating an existing stack-lock into an ObjectMonitor. |
73 | 73 | // See below for is_being_inflated() and INFLATING(). |
74 | 74 | // |
| 75 | +// VALHALLA EXTENSIONS: |
75 | 76 | // |
| 77 | +// N.B.: 32 bit mode is not supported, this section assumes 64 bit systems. |
76 | 78 | // |
77 | | -// Valhalla |
78 | | -// |
79 | | -// <CMH: merge this doc into the text above> |
80 | | -// |
81 | | -// Project Valhalla has mark word encoding requirements for the following oops: |
82 | | -// |
| 79 | +// Project Valhalla uses markWord bits to denote the following oops (listed least to most significant): |
83 | 80 | // * inline types: have alternative bytecode behavior, e.g. can not be locked |
84 | | -// - "larval state": mutable state, but only during object init, observable |
85 | | -// by only by a single thread (generally do not mutate markWord) |
86 | | -// |
87 | 81 | // * flat arrays: load/decode of klass layout helper is expensive for aaload |
88 | | -// |
89 | 82 | // * "null free" arrays: load/decode of klass layout helper again for aaload |
| 83 | +// * inline type: "larval state": mutable state, but only during object init, observable |
| 84 | +// by only by a single thread (generally do not mutate markWord) |
90 | 85 | // |
91 | | -// EnableValhalla |
92 | | -// |
93 | | -// Formerly known as "biased lock bit", "unused_gap" is free to use: using this |
94 | | -// bit to indicate inline type, combined with "unlocked" lock bits, means we |
95 | | -// will not interfere with lock encodings (displaced, inflating, and monitor), |
96 | | -// since inline types can't be locked. |
97 | | -// |
98 | | -// Further state encoding |
99 | | -// |
100 | | -// 32 bit plaforms currently have no further room for encoding. No room for |
101 | | -// "denormalized layout helper bits", these fast mark word tests can only be made on |
102 | | -// 64 bit platforms. 32-bit platforms need to load the klass->_layout_helper. This |
103 | | -// said, the larval state bit is still required for operation, stealing from the hash |
104 | | -// code is simplest mechanism. |
105 | | -// |
106 | | -// Valhalla specific encodings |
107 | | -// |
108 | | -// Revised Bit-format of an object header (most significant first, big endian layout below): |
109 | | -// |
110 | | -// 32 bits: |
111 | | -// -------- |
112 | | -// hash:24 ------------>| larval:1 age:4 inline_type:1 lock:2 |
113 | | -// |
114 | | -// 64 bits: |
115 | | -// -------- |
116 | | -// unused:1 | <-- hash:31 -->| unused:22 larval:1 age:4 flat_array:1 null_free_array:1 inline_type:1 lock:2 |
117 | | -// klass:22 hash:31 -->| larval:1 age:4 flat_array:1 null_free_array:1 inline_type:1 self-fwd:1 lock:2 (normal object) |
118 | | -// |
119 | | -// The "fast" static type bits (flat_array, null_free_array, and inline_type) |
120 | | -// are placed lowest next to lock bits to more easily decode forwarding pointers. |
121 | | -// G1 for example, implicitly clears age bits ("G1FullGCCompactionPoint::forward()") |
122 | | -// using "oopDesc->forwardee()", so it necessary for "markWord::decode_pointer()" |
123 | | -// to return a non-nullptr for this case, but not confuse the static type bits for |
124 | | -// a pointer. |
| 86 | +// Inline types cannot be locked, monitored or inflating. |
125 | 87 | // |
126 | 88 | // Note the position of 'self-fwd' is not by accident. When forwarding an |
127 | 89 | // object to a new heap position, HeapWord alignment guarantees the lower |
128 | 90 | // bits, including 'self-fwd' are 0. "is_self_forwarded()" will be correctly |
129 | 91 | // set to false. Otherwise encode_pointer_as_mark() may have 'self-fwd' set. |
130 | | -// |
131 | | -// |
132 | | -// Static types bits are recorded in the "klass->prototype_header()", displaced |
133 | | -// mark should simply use the prototype header as "slow path", rather chasing |
134 | | -// monitor or stack lock races. |
135 | | -// |
136 | | -// Lock patterns (note inline types can't be locked/monitor/inflating)... |
137 | | -// |
138 | | -// [ptr | 000] locked ptr points to real header on stack |
139 | | -// [header | ?01] unlocked regular object header |
140 | | -// [ptr | 010] monitor inflated lock (header is wapped out) |
141 | | -// [ptr | ?11] marked used to mark an object |
142 | | -// [0 ............ | 000] inflating inflation in progress |
143 | | -// |
144 | | -// |
145 | 92 |
|
146 | 93 | class BasicLock; |
147 | 94 | class ObjectMonitor; |
@@ -183,44 +130,43 @@ class markWord { |
183 | 130 | // Constants, in least significant bit order |
184 | 131 | static const int lock_bits = 2; |
185 | 132 | static const int self_fwd_bits = 1; |
| 133 | + // instance state |
| 134 | + static const int age_bits = 4; |
186 | 135 | // EnableValhalla: static prototype header bits (fast path instead of klass layout_helper) |
187 | 136 | static const int inline_type_bits = 1; |
188 | 137 | static const int null_free_array_bits = LP64_ONLY(1) NOT_LP64(0); |
189 | 138 | static const int flat_array_bits = LP64_ONLY(1) NOT_LP64(0); |
190 | | - // instance state |
191 | | - static const int age_bits = 4; |
192 | 139 | static const int larval_bits = 1; |
193 | 140 | static const int max_hash_bits = BitsPerWord - age_bits - lock_bits - inline_type_bits - larval_bits - flat_array_bits - null_free_array_bits - self_fwd_bits; |
194 | 141 | static const int hash_bits = max_hash_bits > 31 ? 31 : max_hash_bits; |
195 | 142 |
|
196 | 143 | static const int lock_shift = 0; |
197 | | - static const int self_fwd_shift = lock_bits ; |
198 | | - static const int inline_type_shift = self_fwd_shift + self_fwd_bits; |
| 144 | + static const int self_fwd_shift = lock_shift + lock_bits; |
| 145 | + static const int age_shift = self_fwd_shift + self_fwd_bits; |
| 146 | + static const int inline_type_shift = age_shift + age_bits; |
199 | 147 | static const int null_free_array_shift = inline_type_shift + inline_type_bits; |
200 | 148 | static const int flat_array_shift = null_free_array_shift + null_free_array_bits; |
201 | | - static const int age_shift = flat_array_shift + flat_array_bits; |
202 | | - static const int larval_shift = age_shift + age_bits; |
| 149 | + static const int larval_shift = flat_array_shift + flat_array_bits; |
203 | 150 | static const int hash_shift = larval_shift + larval_bits; |
204 | 151 |
|
205 | 152 | static const uintptr_t lock_mask = right_n_bits(lock_bits); |
206 | 153 | static const uintptr_t lock_mask_in_place = lock_mask << lock_shift; |
207 | 154 | static const uintptr_t self_fwd_mask = right_n_bits(self_fwd_bits); |
208 | 155 | static const uintptr_t self_fwd_mask_in_place = self_fwd_mask << self_fwd_shift; |
209 | | - static const uintptr_t inline_type_bit_in_place = 1 << inline_type_shift; |
210 | | - static const uintptr_t inline_type_mask = inline_type_bit_in_place + lock_mask; |
211 | | - static const uintptr_t inline_type_mask_in_place = inline_type_mask << lock_shift; |
| 156 | + static const uintptr_t inline_type_bit_in_place = right_n_bits(inline_type_bits) << inline_type_shift; |
| 157 | + static const uintptr_t inline_type_mask_in_place = inline_type_bit_in_place + lock_mask; |
212 | 158 | static const uintptr_t null_free_array_mask = right_n_bits(null_free_array_bits); |
213 | 159 | static const uintptr_t null_free_array_mask_in_place = (null_free_array_mask << null_free_array_shift) | lock_mask_in_place; |
214 | | - static const uintptr_t null_free_array_bit_in_place = (1 << null_free_array_shift); |
| 160 | + static const uintptr_t null_free_array_bit_in_place = (right_n_bits(null_free_array_bits) << null_free_array_shift); |
215 | 161 | static const uintptr_t flat_array_mask = right_n_bits(flat_array_bits); |
216 | 162 | static const uintptr_t flat_array_mask_in_place = (flat_array_mask << flat_array_shift) | null_free_array_mask_in_place | lock_mask_in_place; |
217 | | - static const uintptr_t flat_array_bit_in_place = (1 << flat_array_shift); |
| 163 | + static const uintptr_t flat_array_bit_in_place = right_n_bits(flat_array_bits) << flat_array_shift; |
218 | 164 | static const uintptr_t age_mask = right_n_bits(age_bits); |
219 | 165 | static const uintptr_t age_mask_in_place = age_mask << age_shift; |
220 | 166 |
|
221 | 167 | static const uintptr_t larval_mask = right_n_bits(larval_bits); |
222 | 168 | static const uintptr_t larval_mask_in_place = (larval_mask << larval_shift) | inline_type_mask_in_place; |
223 | | - static const uintptr_t larval_bit_in_place = (1 << larval_shift); |
| 169 | + static const uintptr_t larval_bit_in_place = right_n_bits(larval_bits) << larval_shift; |
224 | 170 |
|
225 | 171 | static const uintptr_t hash_mask = right_n_bits(hash_bits); |
226 | 172 | static const uintptr_t hash_mask_in_place = hash_mask << hash_shift; |
@@ -249,11 +195,6 @@ class markWord { |
249 | 195 | static const uintptr_t null_free_flat_array_pattern = flat_array_bit_in_place | null_free_array_pattern; |
250 | 196 | static const uintptr_t nullable_flat_array_pattern = flat_array_bit_in_place | unlocked_value; |
251 | 197 |
|
252 | | - // Has static klass prototype, used for decode/encode pointer |
253 | | - static const uintptr_t static_prototype_mask = LP64_ONLY(right_n_bits(inline_type_bits + flat_array_bits + null_free_array_bits)) NOT_LP64(right_n_bits(inline_type_bits)); |
254 | | - static const uintptr_t static_prototype_mask_in_place = static_prototype_mask << lock_bits; |
255 | | - static const uintptr_t static_prototype_value_max = (1 << age_shift) - 1; |
256 | | - |
257 | 198 | static const uintptr_t larval_pattern = larval_bit_in_place | inline_type_pattern; |
258 | 199 |
|
259 | 200 | static const uintptr_t no_hash = 0 ; // no hash value assigned |
@@ -445,10 +386,8 @@ class markWord { |
445 | 386 | // Prepare address of oop for placement into mark |
446 | 387 | inline static markWord encode_pointer_as_mark(void* p) { return from_pointer(p).set_marked(); } |
447 | 388 |
|
448 | | - // Recover address of oop from encoded form used in mark |
449 | 389 | inline void* decode_pointer() const { |
450 | | - return (EnableValhalla && _value < static_prototype_value_max) ? nullptr : |
451 | | - (void*) (clear_lock_bits().value()); |
| 390 | + return (void*) (clear_lock_bits().value()); |
452 | 391 | } |
453 | 392 |
|
454 | 393 | inline bool is_self_forwarded() const { |
|
0 commit comments