Skip to content

Commit 28ae281

Browse files
William KemperkdnilsenY. Srinivas Ramakrishnabernd-awsTheRealMDoerr
committed
8337511: Implement JEP 404: Generational Shenandoah (Experimental)
Co-authored-by: Kelvin Nilsen <[email protected]> Co-authored-by: Y. Srinivas Ramakrishna <[email protected]> Co-authored-by: Bernd Mathiske <[email protected]> Co-authored-by: Martin Doerr <[email protected]> Co-authored-by: Fei Yang <[email protected]> Reviewed-by: rkennke, shade, phh
1 parent 029ace0 commit 28ae281

File tree

228 files changed

+21932
-1723
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

228 files changed

+21932
-1723
lines changed

src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
3+
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -86,6 +87,10 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LI
8687
LIR_Opr result = gen->new_register(T_INT);
8788

8889
__ append(new LIR_OpShenandoahCompareAndSwap(addr, cmp_value.result(), new_value.result(), t1, t2, result));
90+
91+
if (ShenandoahCardBarrier) {
92+
post_barrier(access, access.resolved_addr(), new_value.result());
93+
}
8994
return result;
9095
}
9196
}
@@ -113,6 +118,9 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRIt
113118
pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr,
114119
result /* pre_val */);
115120
}
121+
if (ShenandoahCardBarrier) {
122+
post_barrier(access, access.resolved_addr(), result);
123+
}
116124
}
117125

118126
return result;

src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2018, 2022, Red Hat, Inc. All rights reserved.
3+
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +32,7 @@
3132
#include "gc/shenandoah/shenandoahRuntime.hpp"
3233
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
3334
#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
35+
#include "gc/shenandoah/mode/shenandoahMode.hpp"
3436
#include "interpreter/interpreter.hpp"
3537
#include "interpreter/interp_masm.hpp"
3638
#include "runtime/javaThread.hpp"
@@ -77,6 +79,13 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec
7779
}
7880
}
7981

82+
void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
83+
Register start, Register count, Register tmp, RegSet saved_regs) {
84+
if (ShenandoahCardBarrier && is_oop) {
85+
gen_write_ref_array_post_barrier(masm, decorators, start, count, tmp, saved_regs);
86+
}
87+
}
88+
8089
void ShenandoahBarrierSetAssembler::shenandoah_write_barrier_pre(MacroAssembler* masm,
8190
Register obj,
8291
Register pre_val,
@@ -362,6 +371,26 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d
362371
}
363372
}
364373

374+
void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj) {
375+
assert(ShenandoahCardBarrier, "Should have been checked by caller");
376+
377+
__ lsr(obj, obj, CardTable::card_shift());
378+
379+
assert(CardTable::dirty_card_val() == 0, "must be");
380+
381+
__ load_byte_map_base(rscratch1);
382+
383+
if (UseCondCardMark) {
384+
Label L_already_dirty;
385+
__ ldrb(rscratch2, Address(obj, rscratch1));
386+
__ cbz(rscratch2, L_already_dirty);
387+
__ strb(zr, Address(obj, rscratch1));
388+
__ bind(L_already_dirty);
389+
} else {
390+
__ strb(zr, Address(obj, rscratch1));
391+
}
392+
}
393+
365394
void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
366395
Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
367396
bool on_oop = is_reference_type(type);
@@ -387,18 +416,13 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet
387416
val != noreg /* tosca_live */,
388417
false /* expand_call */);
389418

390-
if (val == noreg) {
391-
BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), noreg, noreg, noreg, noreg);
392-
} else {
393-
// Barrier needs uncompressed oop for region cross check.
394-
Register new_val = val;
395-
if (UseCompressedOops) {
396-
new_val = rscratch2;
397-
__ mov(new_val, val);
398-
}
399-
BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), val, noreg, noreg, noreg);
400-
}
419+
BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp3, 0), val, noreg, noreg, noreg);
401420

421+
bool in_heap = (decorators & IN_HEAP) != 0;
422+
bool needs_post_barrier = (val != noreg) && in_heap && ShenandoahCardBarrier;
423+
if (needs_post_barrier) {
424+
store_check(masm, tmp3);
425+
}
402426
}
403427

404428
void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env,
@@ -581,6 +605,35 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm,
581605
}
582606
}
583607

608+
void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
609+
Register start, Register count, Register scratch, RegSet saved_regs) {
610+
assert(ShenandoahCardBarrier, "Should have been checked by caller");
611+
612+
Label L_loop, L_done;
613+
const Register end = count;
614+
615+
// Zero count? Nothing to do.
616+
__ cbz(count, L_done);
617+
618+
// end = start + count << LogBytesPerHeapOop
619+
// last element address to make inclusive
620+
__ lea(end, Address(start, count, Address::lsl(LogBytesPerHeapOop)));
621+
__ sub(end, end, BytesPerHeapOop);
622+
__ lsr(start, start, CardTable::card_shift());
623+
__ lsr(end, end, CardTable::card_shift());
624+
625+
// number of bytes to copy
626+
__ sub(count, end, start);
627+
628+
__ load_byte_map_base(scratch);
629+
__ add(start, start, scratch);
630+
__ bind(L_loop);
631+
__ strb(zr, Address(start, count));
632+
__ subs(count, count, 1);
633+
__ br(Assembler::GE, L_loop);
634+
__ bind(L_done);
635+
}
636+
584637
#undef __
585638

586639
#ifdef COMPILER1

src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
3+
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -55,10 +56,16 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
5556
bool tosca_live,
5657
bool expand_call);
5758

59+
void store_check(MacroAssembler* masm, Register obj);
60+
5861
void resolve_forward_pointer(MacroAssembler* masm, Register dst, Register tmp = noreg);
5962
void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp = noreg);
6063
void load_reference_barrier(MacroAssembler* masm, Register dst, Address load_addr, DecoratorSet decorators);
6164

65+
void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
66+
Register start, Register count,
67+
Register scratch, RegSet saved_regs);
68+
6269
public:
6370
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; }
6471

@@ -71,6 +78,8 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
7178

7279
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
7380
Register src, Register dst, Register count, RegSet saved_regs);
81+
virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
82+
Register start, Register count, Register tmp, RegSet saved_regs);
7483
virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
7584
Register dst, Address src, Register tmp1, Register tmp2);
7685
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,

src/hotspot/cpu/ppc/gc/shenandoah/c1/shenandoahBarrierSetC1_ppc.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess &access, LI
102102

103103
__ append(new LIR_OpShenandoahCompareAndSwap(addr, cmp_value.result(), new_value.result(), t1, t2, result));
104104

105+
if (ShenandoahCardBarrier) {
106+
post_barrier(access, access.resolved_addr(), new_value.result());
107+
}
108+
105109
return result;
106110
}
107111
}
@@ -132,6 +136,10 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess &access, LIRIt
132136
if (ShenandoahSATBBarrier) {
133137
pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr, result);
134138
}
139+
140+
if (ShenandoahCardBarrier) {
141+
post_barrier(access, access.resolved_addr(), result);
142+
}
135143
}
136144

137145
return result;

src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "gc/shenandoah/shenandoahRuntime.hpp"
3737
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
3838
#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
39+
#include "gc/shenandoah/mode/shenandoahMode.hpp"
3940
#include "interpreter/interpreter.hpp"
4041
#include "macroAssembler_ppc.hpp"
4142
#include "runtime/javaThread.hpp"
@@ -76,8 +77,6 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm,
7677
void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, DecoratorSet decorators, BasicType type,
7778
Register src, Register dst, Register count,
7879
Register preserve1, Register preserve2) {
79-
__ block_comment("arraycopy_prologue (shenandoahgc) {");
80-
8180
Register R11_tmp = R11_scratch1;
8281

8382
assert_different_registers(src, dst, count, R11_tmp, noreg);
@@ -100,6 +99,7 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, Dec
10099
return;
101100
}
102101

102+
__ block_comment("arraycopy_prologue (shenandoahgc) {");
103103
Label skip_prologue;
104104

105105
// Fast path: Array is of length zero.
@@ -173,6 +173,16 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, Dec
173173
__ block_comment("} arraycopy_prologue (shenandoahgc)");
174174
}
175175

176+
void ShenandoahBarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
177+
Register dst, Register count,
178+
Register preserve) {
179+
if (ShenandoahCardBarrier && is_reference_type(type)) {
180+
__ block_comment("arraycopy_epilogue (shenandoahgc) {");
181+
gen_write_ref_array_post_barrier(masm, decorators, dst, count, preserve);
182+
__ block_comment("} arraycopy_epilogue (shenandoahgc)");
183+
}
184+
}
185+
176186
// The to-be-enqueued value can either be determined
177187
// - dynamically by passing the reference's address information (load mode) or
178188
// - statically by passing a register the value is stored in (preloaded mode)
@@ -576,6 +586,25 @@ void ShenandoahBarrierSetAssembler::load_at(
576586
}
577587
}
578588

589+
void ShenandoahBarrierSetAssembler::store_check(MacroAssembler* masm, Register base, RegisterOrConstant ind_or_offs, Register tmp) {
590+
assert(ShenandoahCardBarrier, "Should have been checked by caller");
591+
592+
ShenandoahBarrierSet* ctbs = ShenandoahBarrierSet::barrier_set();
593+
CardTable* ct = ctbs->card_table();
594+
assert_different_registers(base, tmp, R0);
595+
596+
if (ind_or_offs.is_constant()) {
597+
__ add_const_optimized(base, base, ind_or_offs.as_constant(), tmp);
598+
} else {
599+
__ add(base, ind_or_offs.as_register(), base);
600+
}
601+
602+
__ load_const_optimized(tmp, (address)ct->byte_map_base(), R0);
603+
__ srdi(base, base, CardTable::card_shift());
604+
__ li(R0, CardTable::dirty_card_val());
605+
__ stbx(R0, tmp, base);
606+
}
607+
579608
// base: Base register of the reference's address.
580609
// ind_or_offs: Index or offset of the reference's address.
581610
// val: To-be-stored value/reference's new value.
@@ -594,6 +623,11 @@ void ShenandoahBarrierSetAssembler::store_at(MacroAssembler *masm, DecoratorSet
594623
val,
595624
tmp1, tmp2, tmp3,
596625
preservation_level);
626+
627+
// No need for post barrier if storing NULL
628+
if (ShenandoahCardBarrier && is_reference_type(type) && val != noreg) {
629+
store_check(masm, base, ind_or_offs, tmp1);
630+
}
597631
}
598632

599633
void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler *masm,
@@ -743,6 +777,40 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler *masm, Register b
743777
__ block_comment("} cmpxchg_oop (shenandoahgc)");
744778
}
745779

780+
void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
781+
Register addr, Register count, Register preserve) {
782+
assert(ShenandoahCardBarrier, "Should have been checked by caller");
783+
784+
ShenandoahBarrierSet* bs = ShenandoahBarrierSet::barrier_set();
785+
CardTable* ct = bs->card_table();
786+
assert_different_registers(addr, count, R0);
787+
788+
Label L_skip_loop, L_store_loop;
789+
790+
__ sldi_(count, count, LogBytesPerHeapOop);
791+
792+
// Zero length? Skip.
793+
__ beq(CCR0, L_skip_loop);
794+
795+
__ addi(count, count, -BytesPerHeapOop);
796+
__ add(count, addr, count);
797+
// Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
798+
__ srdi(addr, addr, CardTable::card_shift());
799+
__ srdi(count, count, CardTable::card_shift());
800+
__ subf(count, addr, count);
801+
__ add_const_optimized(addr, addr, (address)ct->byte_map_base(), R0);
802+
__ addi(count, count, 1);
803+
__ li(R0, 0);
804+
__ mtctr(count);
805+
806+
// Byte store loop
807+
__ bind(L_store_loop);
808+
__ stb(R0, 0, addr);
809+
__ addi(addr, addr, 1);
810+
__ bdnz(L_store_loop);
811+
__ bind(L_skip_loop);
812+
}
813+
746814
#undef __
747815

748816
#ifdef COMPILER1

src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
5151
Register tmp1, Register tmp2,
5252
MacroAssembler::PreservationLevel preservation_level);
5353

54+
void store_check(MacroAssembler* masm,
55+
Register base, RegisterOrConstant ind_or_offs,
56+
Register tmp);
57+
5458
void load_reference_barrier_impl(MacroAssembler* masm, DecoratorSet decorators,
5559
Register base, RegisterOrConstant ind_or_offs,
5660
Register dst,
@@ -60,6 +64,10 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
6064
/* ==== Helper methods for barrier implementations ==== */
6165
void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp);
6266

67+
void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
68+
Register addr, Register count,
69+
Register preserve);
70+
6371
public:
6472
virtual NMethodPatchingType nmethod_patching_type() { return NMethodPatchingType::conc_data_patch; }
6573

@@ -95,7 +103,11 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler {
95103

96104
/* ==== Access api ==== */
97105
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
98-
Register src, Register dst, Register count, Register preserve1, Register preserve2);
106+
Register src, Register dst, Register count,
107+
Register preserve1, Register preserve2);
108+
virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
109+
Register dst, Register count,
110+
Register preserve);
99111

100112
virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
101113
Register base, RegisterOrConstant ind_or_offs, Register val,

src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,14 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LI
7878
LIR_Opr result = gen->new_register(T_INT);
7979

8080
__ append(new LIR_OpShenandoahCompareAndSwap(addr, cmp_value.result(), new_value.result(), tmp1, tmp2, result));
81+
82+
if (ShenandoahCardBarrier) {
83+
post_barrier(access, access.resolved_addr(), new_value.result());
84+
}
8185
return result;
8286
}
8387
}
88+
8489
return BarrierSetC1::atomic_cmpxchg_at_resolved(access, cmp_value, new_value);
8590
}
8691

@@ -105,6 +110,9 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRIt
105110
pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), LIR_OprFact::illegalOpr,
106111
result /* pre_val */);
107112
}
113+
if (ShenandoahCardBarrier) {
114+
post_barrier(access, access.resolved_addr(), result);
115+
}
108116
}
109117

110118
return result;

0 commit comments

Comments
 (0)