Skip to content

Commit 5463d2d

Browse files
committed
Restore object barrier
1 parent bd5eb9c commit 5463d2d

File tree

2 files changed

+418
-0
lines changed

2 files changed

+418
-0
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
#include "precompiled.hpp"
2+
#include "mmtkObjectBarrier.hpp"
3+
#include "runtime/interfaceSupport.inline.hpp"
4+
5+
void MMTkObjectBarrierSetRuntime::record_modified_node_slow(void* obj) {
6+
::post_write_barrier_slow((MMTk_Mutator) &Thread::current()->third_party_heap_mutator, (void*) obj);
7+
}
8+
9+
void MMTkObjectBarrierSetRuntime::record_modified_node_full(void* obj) {
10+
::post_write_barrier((MMTk_Mutator) &Thread::current()->third_party_heap_mutator, (void*) obj);
11+
}
12+
13+
void MMTkObjectBarrierSetRuntime::record_modified_node(oop src) {
14+
#if MMTK_ENABLE_OBJECT_BARRIER_FASTPATH
15+
intptr_t addr = (intptr_t) (void*) src;
16+
uint8_t* meta_addr = (uint8_t*) (SIDE_METADATA_BASE_ADDRESS + (addr >> 6));
17+
intptr_t shift = (addr >> 3) & 0b111;
18+
uint8_t byte_val = *meta_addr;
19+
if (((byte_val >> shift) & 1) == 1) {
20+
record_modified_node_slow((void*) src);
21+
}
22+
#else
23+
record_modified_node_full((void*) src);
24+
#endif
25+
}
26+
27+
#define __ masm->
28+
29+
void MMTkObjectBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
30+
bool in_heap = (decorators & IN_HEAP) != 0;
31+
bool as_normal = (decorators & AS_NORMAL) != 0;
32+
assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
33+
34+
if (!in_heap || val == noreg) {
35+
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
36+
return;
37+
}
38+
39+
BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
40+
41+
record_modified_node(masm, dst.base(), tmp1, tmp2);
42+
}
43+
44+
void MMTkObjectBarrierSetAssembler::record_modified_node(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2) {
45+
#if MMTK_ENABLE_OBJECT_BARRIER_FASTPATH
46+
Label done;
47+
48+
Register tmp3 = rscratch1;
49+
Register tmp4 = rscratch2;
50+
assert_different_registers(obj, tmp2, tmp3);
51+
assert_different_registers(tmp4, rcx);
52+
53+
// tmp2 = load-byte (SIDE_METADATA_BASE_ADDRESS + (obj >> 6));
54+
__ movptr(tmp3, obj);
55+
__ shrptr(tmp3, 6);
56+
__ movptr(tmp2, SIDE_METADATA_BASE_ADDRESS);
57+
__ movb(tmp2, Address(tmp2, tmp3));
58+
// tmp3 = (obj >> 3) & 7
59+
__ movptr(tmp3, obj);
60+
__ shrptr(tmp3, 3);
61+
__ andptr(tmp3, 7);
62+
// tmp2 = tmp2 >> tmp3
63+
__ movptr(tmp4, rcx);
64+
__ movl(rcx, tmp3);
65+
__ shrptr(tmp2);
66+
__ movptr(rcx, tmp4);
67+
// if ((tmp2 & 1) == 1) goto slowpath;
68+
__ andptr(tmp2, 1);
69+
__ cmpptr(tmp2, 1);
70+
__ jcc(Assembler::notEqual, done);
71+
72+
assert_different_registers(c_rarg0, obj);
73+
__ movptr(c_rarg0, obj);
74+
__ call_VM_leaf_base(CAST_FROM_FN_PTR(address, MMTkObjectBarrierSetRuntime::record_modified_node_slow), 1);
75+
76+
__ bind(done);
77+
#else
78+
assert_different_registers(c_rarg0, obj);
79+
__ movptr(c_rarg0, obj);
80+
__ call_VM_leaf_base(CAST_FROM_FN_PTR(address, MMTkObjectBarrierSetRuntime::record_modified_node_full), 1);
81+
#endif
82+
}
83+
84+
#undef __
85+
86+
#ifdef ASSERT
87+
#define __ gen->lir(__FILE__, __LINE__)->
88+
#else
89+
#define __ gen->lir()->
90+
#endif
91+
92+
void MMTkObjectBarrierSetC1::record_modified_node(LIRAccess& access, LIR_Opr src, LIR_Opr slot, LIR_Opr new_val) {
93+
LIRGenerator* gen = access.gen();
94+
DecoratorSet decorators = access.decorators();
95+
if ((decorators & IN_HEAP) == 0) return;
96+
if (!src->is_register()) {
97+
LIR_Opr reg = gen->new_pointer_register();
98+
if (src->is_constant()) {
99+
__ move(src, reg);
100+
} else {
101+
__ leal(src, reg);
102+
}
103+
src = reg;
104+
}
105+
assert(src->is_register(), "must be a register at this point");
106+
if (!slot->is_register()) {
107+
LIR_Opr reg = gen->new_pointer_register();
108+
if (slot->is_constant()) {
109+
__ move(slot, reg);
110+
} else {
111+
__ leal(slot, reg);
112+
}
113+
slot = reg;
114+
}
115+
assert(slot->is_register(), "must be a register at this point");
116+
if (!new_val->is_register()) {
117+
LIR_Opr new_val_reg = gen->new_register(T_OBJECT);
118+
if (new_val->is_constant()) {
119+
__ move(new_val, new_val_reg);
120+
} else {
121+
__ leal(new_val, new_val_reg);
122+
}
123+
new_val = new_val_reg;
124+
}
125+
assert(new_val->is_register(), "must be a register at this point");
126+
CodeStub* slow = new MMTkObjectBarrierStub(src, slot, new_val);
127+
128+
#if MMTK_ENABLE_OBJECT_BARRIER_FASTPATH
129+
LIR_Opr addr = src;
130+
// uint8_t* meta_addr = (uint8_t*) (SIDE_METADATA_BASE_ADDRESS + (addr >> 6));
131+
LIR_Opr offset = gen->new_pointer_register();
132+
__ move(addr, offset);
133+
__ shift_right(offset, 6, offset);
134+
LIR_Opr base = gen->new_pointer_register();
135+
__ move(LIR_OprFact::longConst(SIDE_METADATA_BASE_ADDRESS), base);
136+
LIR_Address* meta_addr = new LIR_Address(base, offset, T_BYTE);
137+
// intptr_t shift = (addr >> 3) & 0b111;
138+
LIR_Opr shift_long = gen->new_pointer_register();
139+
__ move(addr, shift_long);
140+
__ shift_right(shift_long, 3, shift_long);
141+
__ logical_and(shift_long, LIR_OprFact::longConst(0b111), shift_long);
142+
LIR_Opr shift_int = gen->new_register(T_INT);
143+
__ convert(Bytecodes::_l2i, shift_long, shift_int);
144+
LIR_Opr shift = LIRGenerator::shiftCountOpr();
145+
__ move(shift_int, shift);
146+
// uint8_t byte_val = *meta_addr;
147+
LIR_Opr byte_val = gen->new_register(T_INT);
148+
__ move(meta_addr, byte_val);
149+
// if (((byte_val >> shift) & 1) == 1) slow;
150+
LIR_Opr result = byte_val;
151+
__ shift_right(result, shift, result, LIR_OprFact::illegalOpr);
152+
__ logical_and(result, LIR_OprFact::intConst(1), result);
153+
__ cmp(lir_cond_equal, result, LIR_OprFact::intConst(1));
154+
__ branch(lir_cond_equal, slow);
155+
#else
156+
__ jump(slow);
157+
#endif
158+
159+
__ branch_destination(slow->continuation());
160+
}
161+
162+
#undef __
163+
164+
#define __ ideal.
165+
166+
const TypeFunc* record_modified_node_entry_Type() {
167+
const Type **fields = TypeTuple::fields(1);
168+
fields[TypeFunc::Parms+0] = TypeOopPtr::BOTTOM; // oop src
169+
const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
170+
fields = TypeTuple::fields(0);
171+
const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
172+
return TypeFunc::make(domain, range);
173+
}
174+
175+
void MMTkObjectBarrierSetC2::record_modified_node(GraphKit* kit, Node* src, Node* val) const {
176+
if (val != NULL && val->is_Con()) {
177+
const Type* t = val->bottom_type();
178+
if (t == TypePtr::NULL_PTR) return;
179+
}
180+
181+
MMTkIdealKit ideal(kit, true);
182+
183+
#if MMTK_ENABLE_OBJECT_BARRIER_FASTPATH
184+
Node* no_base = __ top();
185+
float unlikely = PROB_UNLIKELY(0.999);
186+
187+
Node* zero = __ ConI(0);
188+
Node* addr = __ CastPX(__ ctrl(), src);
189+
Node* meta_addr = __ AddP(no_base, __ ConP(SIDE_METADATA_BASE_ADDRESS), __ URShiftX(addr, __ ConI(6)));
190+
Node* byte = __ load(__ ctrl(), meta_addr, TypeInt::INT, T_BYTE, Compile::AliasIdxRaw);
191+
Node* shift = __ URShiftX(addr, __ ConI(3));
192+
shift = __ AndI(__ ConvL2I(shift), __ ConI(7));
193+
Node* result = __ AndI(__ URShiftI(byte, shift), __ ConI(1));
194+
195+
__ if_then(result, BoolTest::ne, zero, unlikely); {
196+
const TypeFunc* tf = __ func_type(TypeOopPtr::BOTTOM);
197+
Node* x = __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, MMTkObjectBarrierSetRuntime::record_modified_node_slow), "record_modified_node", src);
198+
} __ end_if();
199+
#else
200+
const TypeFunc* tf = __ func_type(TypeOopPtr::BOTTOM);
201+
Node* x = __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, MMTkObjectBarrierSetRuntime::record_modified_node_full), "record_modified_node", src);
202+
#endif
203+
204+
kit->final_sync(ideal); // Final sync IdealKit and GraphKit.
205+
}
206+
207+
#undef __

0 commit comments

Comments
 (0)