8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "c1/c1_IR.hpp"
26 #include "gc/shared/satbMarkQueue.hpp"
27 #include "gc/shenandoah/brooksPointer.hpp"
28 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
29 #include "gc/shenandoah/shenandoahHeap.hpp"
30 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
31 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
32 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
33
34 #ifdef ASSERT
35 #define __ gen->lir(__FILE__, __LINE__)->
36 #else
37 #define __ gen->lir()->
38 #endif
39
40 void ShenandoahPreBarrierStub::emit_code(LIR_Assembler* ce) {
41 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
42 bs->gen_pre_barrier_stub(ce, this);
43 }
44
45 void ShenandoahWriteBarrierStub::emit_code(LIR_Assembler* ce) {
46 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
47 bs->gen_write_barrier_stub(ce, this);
48 }
49
50 void ShenandoahBarrierSetC1::pre_barrier(LIRGenerator* gen, CodeEmitInfo* info, DecoratorSet decorators, LIR_Opr addr_opr, LIR_Opr pre_val) {
51
52 // First we test whether marking is in progress.
53 BasicType flag_type;
54 bool patch = (decorators & C1_NEEDS_PATCHING) != 0;
55 bool do_load = pre_val == LIR_OprFact::illegalOpr;
56 if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
57 flag_type = T_INT;
58 } else {
59 guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
60 "Assumption");
61 // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,
62 // need to use unsigned instructions to use the large offset to load the satb_mark_queue.
63 flag_type = T_BOOLEAN;
64 }
65 LIR_Opr thrd = gen->getThreadPointer();
66 LIR_Address* mark_active_flag_addr =
67 new LIR_Address(thrd,
68 in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset()),
69 flag_type);
70 // Read the marking-in-progress flag.
71 LIR_Opr flag_val = gen->new_register(T_INT);
72 __ load(mark_active_flag_addr, flag_val);
73 __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
74
75 LIR_PatchCode pre_val_patch_code = lir_patch_none;
76
77 CodeStub* slow;
78
79 if (do_load) {
80 assert(pre_val == LIR_OprFact::illegalOpr, "sanity");
81 assert(addr_opr != LIR_OprFact::illegalOpr, "sanity");
82
83 if (patch)
84 pre_val_patch_code = lir_patch_normal;
85
86 pre_val = gen->new_register(T_OBJECT);
87
88 if (!addr_opr->is_address()) {
89 assert(addr_opr->is_register(), "must be");
90 addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));
91 }
92 slow = new ShenandoahPreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info ? new CodeEmitInfo(info) : NULL);
93 } else {
94 assert(addr_opr == LIR_OprFact::illegalOpr, "sanity");
95 assert(pre_val->is_register(), "must be");
96 assert(pre_val->type() == T_OBJECT, "must be an object");
97
98 slow = new ShenandoahPreBarrierStub(pre_val);
99 }
100
101 __ branch(lir_cond_notEqual, T_INT, slow);
102 __ branch_destination(slow->continuation());
103 }
104
105 LIR_Opr ShenandoahBarrierSetC1::read_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
106 if (UseShenandoahGC && ShenandoahReadBarrier) {
107 return read_barrier_impl(gen, obj, info, need_null_check);
108 } else {
109 return obj;
110 }
111 }
112
113 LIR_Opr ShenandoahBarrierSetC1::read_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
114 assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier), "Should be enabled");
115 LabelObj* done = new LabelObj();
116 LIR_Opr result = gen->new_register(T_OBJECT);
117 __ move(obj, result);
118 if (need_null_check) {
119 __ cmp(lir_cond_equal, result, LIR_OprFact::oopConst(NULL));
120 __ branch(lir_cond_equal, T_LONG, done->label());
121 }
122 LIR_Address* brooks_ptr_address = gen->generate_address(result, BrooksPointer::byte_offset(), T_ADDRESS);
123 __ load(brooks_ptr_address, result, info ? new CodeEmitInfo(info) : NULL, lir_patch_none);
124
125 __ branch_destination(done->label());
126 return result;
127 }
128
129 LIR_Opr ShenandoahBarrierSetC1::write_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
130 if (UseShenandoahGC && ShenandoahWriteBarrier) {
131 return write_barrier_impl(gen, obj, info, need_null_check);
132 } else {
133 return obj;
134 }
135 }
136
137 LIR_Opr ShenandoahBarrierSetC1::write_barrier_impl(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, bool need_null_check) {
138 assert(UseShenandoahGC && (ShenandoahWriteBarrier || ShenandoahStoreValEnqueueBarrier), "Should be enabled");
139
140 obj = ensure_in_register(gen, obj);
141 assert(obj->is_register(), "must be a register at this point");
142 LIR_Opr result = gen->new_register(T_OBJECT);
143 __ move(obj, result);
144
145 LIR_Opr thrd = gen->getThreadPointer();
146 LIR_Address* active_flag_addr =
147 new LIR_Address(thrd,
148 in_bytes(ShenandoahThreadLocalData::gc_state_offset()),
149 T_BYTE);
150 // Read and check the gc-state-flag.
151 LIR_Opr flag_val = gen->new_register(T_INT);
152 __ load(active_flag_addr, flag_val);
153 LIR_Opr mask = LIR_OprFact::intConst(ShenandoahHeap::HAS_FORWARDED |
154 ShenandoahHeap::EVACUATION |
155 ShenandoahHeap::TRAVERSAL);
156 LIR_Opr mask_reg = gen->new_register(T_INT);
157 __ move(mask, mask_reg);
158
159 if (TwoOperandLIRForm) {
160 __ logical_and(flag_val, mask_reg, flag_val);
161 } else {
162 LIR_Opr masked_flag = gen->new_register(T_INT);
163 __ logical_and(flag_val, mask_reg, masked_flag);
164 flag_val = masked_flag;
165 }
166 __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
167
168 CodeStub* slow = new ShenandoahWriteBarrierStub(obj, result, info ? new CodeEmitInfo(info) : NULL, need_null_check);
169 __ branch(lir_cond_notEqual, T_INT, slow);
170 __ branch_destination(slow->continuation());
171
172 return result;
173 }
174
175 LIR_Opr ShenandoahBarrierSetC1::ensure_in_register(LIRGenerator* gen, LIR_Opr obj) {
176 if (!obj->is_register()) {
177 LIR_Opr obj_reg = gen->new_register(T_OBJECT);
178 if (obj->is_constant()) {
179 __ move(obj, obj_reg);
180 } else {
181 __ leal(obj, obj_reg);
182 }
183 obj = obj_reg;
184 }
185 return obj;
186 }
187
188 LIR_Opr ShenandoahBarrierSetC1::storeval_barrier(LIRGenerator* gen, LIR_Opr obj, CodeEmitInfo* info, DecoratorSet decorators) {
189 bool need_null_check = (decorators & IS_NOT_NULL) == 0;
190 if (ShenandoahStoreValEnqueueBarrier) {
191 obj = write_barrier_impl(gen, obj, info, need_null_check);
192 pre_barrier(gen, info, decorators, LIR_OprFact::illegalOpr, obj);
193 }
194 if (ShenandoahStoreValReadBarrier) {
195 obj = read_barrier_impl(gen, obj, info, true /*need_null_check*/);
196 }
197 return obj;
198 }
199
200 void ShenandoahBarrierSetC1::store_at(LIRAccess& access, LIR_Opr value) {
201 access.set_base(write_barrier(access.gen(), access.base().item().result(), access.access_emit_info(), access.needs_null_check()));
202 LIR_Opr resolved = resolve_address(access, false);
203 access.set_resolved_addr(resolved);
204 if (access.is_oop()) {
205 if (ShenandoahSATBBarrier) {
206 pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), access.resolved_addr(), LIR_OprFact::illegalOpr /* pre_val */);
207 }
208 value = storeval_barrier(access.gen(), value, access.access_emit_info(), access.decorators());
209 }
210 BarrierSetC1::store_at_resolved(access, value);
211 }
212
213 void ShenandoahBarrierSetC1::load_at(LIRAccess& access, LIR_Opr result) {
214 LIRItem& base_item = access.base().item();
215 access.set_base(read_barrier(access.gen(), access.base().item().result(), access.access_emit_info(), access.needs_null_check()));
216 LIR_Opr resolved = resolve_address(access, false);
217 access.set_resolved_addr(resolved);
218 BarrierSetC1::load_at_resolved(access, result);
219 access.set_base(base_item);
266 }
267 return BarrierSetC1::atomic_xchg_at_resolved(access, value);
268 }
269
270 LIR_Opr ShenandoahBarrierSetC1::atomic_add_at(LIRAccess& access, LIRItem& value) {
271 access.load_address();
272 access.set_base(write_barrier(access.gen(), access.base().item().result(), access.access_emit_info(), access.needs_null_check()));
273 LIR_Opr resolved = resolve_address(access, true);
274 access.set_resolved_addr(resolved);
275 return BarrierSetC1::atomic_add_at_resolved(access, value);
276 }
277
278 LIR_Opr ShenandoahBarrierSetC1::resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj) {
279 bool is_write = decorators & ACCESS_WRITE;
280 if (is_write) {
281 return write_barrier(gen, obj, NULL, (decorators & IS_NOT_NULL) == 0);
282 } else {
283 return read_barrier(gen, obj, NULL, (decorators & IS_NOT_NULL) == 0);
284 }
285 }
286
287 class C1ShenandoahPreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
288 virtual OopMapSet* generate_code(StubAssembler* sasm) {
289 ShenandoahBarrierSetAssembler* bs = (ShenandoahBarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
290 bs->generate_c1_pre_barrier_runtime_stub(sasm);
291 return NULL;
292 }
293 };
294
295 void ShenandoahBarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) {
296 C1ShenandoahPreBarrierCodeGenClosure pre_code_gen_cl;
297 _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1,
298 "shenandoah_pre_barrier_slow",
299 false, &pre_code_gen_cl);
300 }
301
|
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "c1/c1_IR.hpp"
26 #include "gc/shared/satbMarkQueue.hpp"
27 #include "gc/shenandoah/brooksPointer.hpp"
28 #include "gc/shenandoah/shenandoahBaseBarrierSetAssembler.hpp"
29 #include "gc/shenandoah/shenandoahHeap.hpp"
30 #include "gc/shenandoah/shenandoahHeapRegion.hpp"
31 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
32 #include "gc/shenandoah/c1/shenandoahBarrierSetC1.hpp"
33
34 #ifdef ASSERT
35 #define __ gen->lir(__FILE__, __LINE__)->
36 #else
37 #define __ gen->lir()->
38 #endif
39
40 void ShenandoahBarrierSetC1::store_at(LIRAccess& access, LIR_Opr value) {
41 access.set_base(write_barrier(access.gen(), access.base().item().result(), access.access_emit_info(), access.needs_null_check()));
42 LIR_Opr resolved = resolve_address(access, false);
43 access.set_resolved_addr(resolved);
44 if (access.is_oop()) {
45 if (ShenandoahSATBBarrier) {
46 pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), access.resolved_addr(), LIR_OprFact::illegalOpr /* pre_val */);
47 }
48 value = storeval_barrier(access.gen(), value, access.access_emit_info(), access.decorators());
49 }
50 BarrierSetC1::store_at_resolved(access, value);
51 }
52
53 void ShenandoahBarrierSetC1::load_at(LIRAccess& access, LIR_Opr result) {
54 LIRItem& base_item = access.base().item();
55 access.set_base(read_barrier(access.gen(), access.base().item().result(), access.access_emit_info(), access.needs_null_check()));
56 LIR_Opr resolved = resolve_address(access, false);
57 access.set_resolved_addr(resolved);
58 BarrierSetC1::load_at_resolved(access, result);
59 access.set_base(base_item);
106 }
107 return BarrierSetC1::atomic_xchg_at_resolved(access, value);
108 }
109
110 LIR_Opr ShenandoahBarrierSetC1::atomic_add_at(LIRAccess& access, LIRItem& value) {
111 access.load_address();
112 access.set_base(write_barrier(access.gen(), access.base().item().result(), access.access_emit_info(), access.needs_null_check()));
113 LIR_Opr resolved = resolve_address(access, true);
114 access.set_resolved_addr(resolved);
115 return BarrierSetC1::atomic_add_at_resolved(access, value);
116 }
117
118 LIR_Opr ShenandoahBarrierSetC1::resolve(LIRGenerator* gen, DecoratorSet decorators, LIR_Opr obj) {
119 bool is_write = decorators & ACCESS_WRITE;
120 if (is_write) {
121 return write_barrier(gen, obj, NULL, (decorators & IS_NOT_NULL) == 0);
122 } else {
123 return read_barrier(gen, obj, NULL, (decorators & IS_NOT_NULL) == 0);
124 }
125 }
|