Skip to content

Commit b149461

Browse files
committed
8316108: [Lilliput/JDK21] Cherry-pick: 8305898: Alternative self-forwarding mechanism
Reviewed-by: shade
1 parent 882ff14 commit b149461

File tree

8 files changed

+99
-16
lines changed

8 files changed

+99
-16
lines changed

src/hotspot/share/gc/g1/g1OopClosures.inline.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ void G1ParCopyClosure<barrier, should_mark>::do_oop_work(T* p) {
228228
oop forwardee;
229229
markWord m = obj->mark();
230230
if (m.is_marked()) {
231-
forwardee = cast_to_oop(m.decode_pointer());
231+
forwardee = obj->forwardee(m);
232232
} else {
233233
forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
234234
}

src/hotspot/share/gc/g1/g1ParScanThreadState.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ void G1ParScanThreadState::do_oop_evac(T* p) {
207207

208208
markWord m = obj->mark();
209209
if (m.is_marked()) {
210-
obj = cast_to_oop(m.decode_pointer());
210+
obj = obj->forwardee(m);
211211
} else {
212212
obj = do_copy_to_survivor_space(region_attr, obj, m);
213213
}
@@ -620,7 +620,7 @@ NOINLINE
620620
oop G1ParScanThreadState::handle_evacuation_failure_par(oop old, markWord m, size_t word_sz) {
621621
assert(_g1h->is_in_cset(old), "Object " PTR_FORMAT " should be in the CSet", p2i(old));
622622

623-
oop forward_ptr = old->forward_to_atomic(old, m, memory_order_relaxed);
623+
oop forward_ptr = old->forward_to_self_atomic(m, memory_order_relaxed);
624624
if (forward_ptr == nullptr) {
625625
// Forward-to-self succeeded. We are the "owner" of the object.
626626
HeapRegion* r = _g1h->heap_region_containing(old);

src/hotspot/share/gc/parallel/psPromotionManager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ oop PSPromotionManager::oop_promotion_failed(oop obj, markWord obj_mark) {
333333
// this started. If it is the same (i.e., no forwarding
334334
// pointer has been installed), then this thread owns
335335
// it.
336-
if (obj->forward_to_atomic(obj, obj_mark) == nullptr) {
336+
if (obj->forward_to_self_atomic(obj_mark) == nullptr) {
337337
// We won any races, we "own" this object.
338338
assert(obj == obj->forwardee(), "Sanity");
339339

src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ inline oop PSPromotionManager::copy_to_survivor_space(oop o) {
147147
// other thread.
148148
OrderAccess::acquire();
149149
// Return the already installed forwardee.
150-
return cast_to_oop(m.decode_pointer());
150+
return o->forwardee(m);
151151
}
152152
}
153153

src/hotspot/share/gc/serial/defNewGeneration.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -905,8 +905,7 @@ void DefNewGeneration::handle_promotion_failure(oop old) {
905905

906906
ContinuationGCSupport::transform_stack_chunk(old);
907907

908-
// forward to self
909-
old->forward_to(old);
908+
old->forward_to_self();
910909

911910
_promo_failure_scan_stack.push(old);
912911

src/hotspot/share/oops/markWord.hpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#ifndef SHARE_OOPS_MARKWORD_HPP
2626
#define SHARE_OOPS_MARKWORD_HPP
2727

28+
#include "gc/shared/gc_globals.hpp"
2829
#include "metaprogramming/primitiveConversions.hpp"
2930
#include "oops/oopsHierarchy.hpp"
3031
#include "runtime/globals.hpp"
@@ -43,6 +44,10 @@
4344
// --------
4445
// unused:25 hash:31 -->| unused_gap:1 age:4 unused_gap:1 lock:2 (normal object)
4546
//
47+
// 64 bits (alternative GC forwarding):
48+
// ------------------------------------
49+
// unused:25 hash:31 -->| unused_gap:1 age:4 self-fwd:1 lock:2 (normal object)
50+
//
4651
// - hash contains the identity hash value: largest value is
4752
// 31 bits, see os::random(). Also, 64-bit vm's require
4853
// a hash value no bigger than 32 bits because they will not
@@ -103,17 +108,20 @@ class markWord {
103108
// Constants
104109
static const int age_bits = 4;
105110
static const int lock_bits = 2;
106-
static const int first_unused_gap_bits = 1;
107-
static const int max_hash_bits = BitsPerWord - age_bits - lock_bits - first_unused_gap_bits;
111+
static const int self_forwarded_bits = 1;
112+
static const int max_hash_bits = BitsPerWord - age_bits - lock_bits - self_forwarded_bits;
108113
static const int hash_bits = max_hash_bits > 31 ? 31 : max_hash_bits;
109-
static const int second_unused_gap_bits = LP64_ONLY(1) NOT_LP64(0);
114+
static const int unused_gap_bits = LP64_ONLY(1) NOT_LP64(0);
110115

111116
static const int lock_shift = 0;
112-
static const int age_shift = lock_bits + first_unused_gap_bits;
113-
static const int hash_shift = age_shift + age_bits + second_unused_gap_bits;
117+
static const int self_forwarded_shift = lock_shift + lock_bits;
118+
static const int age_shift = self_forwarded_shift + self_forwarded_bits;
119+
static const int hash_shift = age_shift + age_bits + unused_gap_bits;
114120

115121
static const uintptr_t lock_mask = right_n_bits(lock_bits);
116122
static const uintptr_t lock_mask_in_place = lock_mask << lock_shift;
123+
static const uintptr_t self_forwarded_mask = right_n_bits(self_forwarded_bits);
124+
static const uintptr_t self_forwarded_mask_in_place = self_forwarded_mask << self_forwarded_shift;
117125
static const uintptr_t age_mask = right_n_bits(age_bits);
118126
static const uintptr_t age_mask_in_place = age_mask << age_shift;
119127
static const uintptr_t hash_mask = right_n_bits(hash_bits);
@@ -260,6 +268,19 @@ class markWord {
260268

261269
// Recover address of oop from encoded form used in mark
262270
inline void* decode_pointer() { return (void*)clear_lock_bits().value(); }
271+
272+
#ifdef _LP64
273+
inline bool self_forwarded() const {
274+
bool self_fwd = mask_bits(value(), self_forwarded_mask_in_place) != 0;
275+
assert(!self_fwd || UseAltGCForwarding, "Only set self-fwd bit when using alt GC forwarding");
276+
return self_fwd;
277+
}
278+
279+
inline markWord set_self_forwarded() const {
280+
assert(UseAltGCForwarding, "Only call this with alt GC forwarding");
281+
return markWord(value() | self_forwarded_mask_in_place | marked_value);
282+
}
283+
#endif
263284
};
264285

265286
// Support atomic operations.

src/hotspot/share/oops/oop.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,14 +259,17 @@ class oopDesc {
259259
inline bool is_forwarded() const;
260260

261261
inline void forward_to(oop p);
262+
inline void forward_to_self();
262263

263264
// Like "forward_to", but inserts the forwarding pointer atomically.
264265
// Exactly one thread succeeds in inserting the forwarding pointer, and
265266
// this call returns null for that thread; any other thread has the
266267
// value of the forwarding pointer returned and does not modify "this".
267268
inline oop forward_to_atomic(oop p, markWord compare, atomic_memory_order order = memory_order_conservative);
269+
inline oop forward_to_self_atomic(markWord compare, atomic_memory_order order = memory_order_conservative);
268270

269271
inline oop forwardee() const;
272+
inline oop forwardee(markWord header) const;
270273

271274
// Age of object during scavenge
272275
inline uint age() const;

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

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "oops/oopsHierarchy.hpp"
3939
#include "runtime/atomic.hpp"
4040
#include "runtime/globals.hpp"
41+
#include "runtime/safepoint.hpp"
4142
#include "utilities/align.hpp"
4243
#include "utilities/debug.hpp"
4344
#include "utilities/macros.hpp"
@@ -270,28 +271,87 @@ bool oopDesc::is_forwarded() const {
270271

271272
// Used by scavengers
272273
void oopDesc::forward_to(oop p) {
274+
assert(p != cast_to_oop(this) || !UseAltGCForwarding, "Must not be called with self-forwarding");
273275
markWord m = markWord::encode_pointer_as_mark(p);
274-
assert(m.decode_pointer() == p, "encoding must be reversible");
276+
assert(forwardee(m) == p, "encoding must be reversible");
275277
set_mark(m);
276278
}
277279

280+
void oopDesc::forward_to_self() {
281+
#ifdef _LP64
282+
if (UseAltGCForwarding) {
283+
markWord m = mark();
284+
// If mark is displaced, we need to preserve the real header during GC.
285+
// It will be restored to the displaced header after GC.
286+
assert(SafepointSynchronize::is_at_safepoint(), "we can only safely fetch the displaced header at safepoint");
287+
if (m.has_displaced_mark_helper()) {
288+
m = m.displaced_mark_helper();
289+
}
290+
m = m.set_self_forwarded();
291+
assert(forwardee(m) == cast_to_oop(this), "encoding must be reversible");
292+
set_mark(m);
293+
} else
294+
#endif
295+
{
296+
forward_to(oop(this));
297+
}
298+
}
299+
278300
oop oopDesc::forward_to_atomic(oop p, markWord compare, atomic_memory_order order) {
301+
assert(p != cast_to_oop(this) || !UseAltGCForwarding, "Must not be called with self-forwarding");
279302
markWord m = markWord::encode_pointer_as_mark(p);
280303
assert(m.decode_pointer() == p, "encoding must be reversible");
281304
markWord old_mark = cas_set_mark(m, compare, order);
282305
if (old_mark == compare) {
283306
return nullptr;
284307
} else {
285-
return cast_to_oop(old_mark.decode_pointer());
308+
return forwardee(old_mark);
309+
}
310+
}
311+
312+
oop oopDesc::forward_to_self_atomic(markWord compare, atomic_memory_order order) {
313+
#ifdef _LP64
314+
if (UseAltGCForwarding) {
315+
markWord m = compare;
316+
// If mark is displaced, we need to preserve the real header during GC.
317+
// It will be restored to the displaced header after GC.
318+
assert(SafepointSynchronize::is_at_safepoint(), "we can only safely fetch the displaced header at safepoint");
319+
if (m.has_displaced_mark_helper()) {
320+
m = m.displaced_mark_helper();
321+
}
322+
m = m.set_self_forwarded();
323+
assert(forwardee(m) == cast_to_oop(this), "encoding must be reversible");
324+
markWord old_mark = cas_set_mark(m, compare, order);
325+
if (old_mark == compare) {
326+
return nullptr;
327+
} else {
328+
assert(old_mark.is_marked(), "must be marked here");
329+
return forwardee(old_mark);
330+
}
331+
} else
332+
#endif
333+
{
334+
return forward_to_atomic(cast_to_oop(this), compare, order);
335+
}
336+
}
337+
338+
oop oopDesc::forwardee(markWord header) const {
339+
assert(header.is_marked(), "only decode when actually forwarded");
340+
#ifdef _LP64
341+
if (header.self_forwarded()) {
342+
return cast_to_oop(this);
343+
} else
344+
#endif
345+
{
346+
return cast_to_oop(header.decode_pointer());
286347
}
287348
}
288349

289350
// Note that the forwardee is not the same thing as the displaced_mark.
290351
// The forwardee is used when copying during scavenge and mark-sweep.
291352
// It does need to clear the low two locking- and GC-related bits.
292353
oop oopDesc::forwardee() const {
293-
assert(is_forwarded(), "only decode when actually forwarded");
294-
return cast_to_oop(mark().decode_pointer());
354+
return forwardee(mark());
295355
}
296356

297357
// The following method needs to be MT safe.

0 commit comments

Comments
 (0)