22 */ |
22 */ |
23 |
23 |
24 #include "precompiled.hpp" |
24 #include "precompiled.hpp" |
25 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" |
25 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" |
26 #include "gc/shenandoah/shenandoahForwarding.hpp" |
26 #include "gc/shenandoah/shenandoahForwarding.hpp" |
27 #include "gc/shenandoah/shenandoahHeap.hpp" |
27 #include "gc/shenandoah/shenandoahHeap.inline.hpp" |
28 #include "gc/shenandoah/shenandoahHeapRegion.hpp" |
28 #include "gc/shenandoah/shenandoahHeapRegion.hpp" |
29 #include "gc/shenandoah/shenandoahHeuristics.hpp" |
29 #include "gc/shenandoah/shenandoahHeuristics.hpp" |
30 #include "gc/shenandoah/shenandoahRuntime.hpp" |
30 #include "gc/shenandoah/shenandoahRuntime.hpp" |
31 #include "gc/shenandoah/shenandoahThreadLocalData.hpp" |
31 #include "gc/shenandoah/shenandoahThreadLocalData.hpp" |
32 #include "interpreter/interpreter.hpp" |
32 #include "interpreter/interpreter.hpp" |
280 |
280 |
281 __ bind(done); |
281 __ bind(done); |
282 __ leave(); |
282 __ leave(); |
283 } |
283 } |
284 |
284 |
|
285 void ShenandoahBarrierSetAssembler::load_reference_barrier_native(MacroAssembler* masm, Register dst, Register tmp) { |
|
286 if (!ShenandoahLoadRefBarrier) { |
|
287 return; |
|
288 } |
|
289 |
|
290 assert(dst != rscratch2, "need rscratch2"); |
|
291 |
|
292 Label is_null; |
|
293 Label done; |
|
294 |
|
295 __ cbz(dst, is_null); |
|
296 |
|
297 __ enter(); |
|
298 |
|
299 Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); |
|
300 __ ldrb(rscratch2, gc_state); |
|
301 |
|
302 // Check for heap in evacuation phase |
|
303 __ tbz(rscratch2, ShenandoahHeap::EVACUATION_BITPOS, done); |
|
304 |
|
305 __ mov(rscratch2, dst); |
|
306 __ push_call_clobbered_registers(); |
|
307 __ mov(lr, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_native)); |
|
308 __ mov(r0, rscratch2); |
|
309 __ blrt(lr, 1, 0, MacroAssembler::ret_type_integral); |
|
310 __ mov(rscratch2, r0); |
|
311 __ pop_call_clobbered_registers(); |
|
312 __ mov(dst, rscratch2); |
|
313 |
|
314 __ bind(done); |
|
315 __ leave(); |
|
316 __ bind(is_null); |
|
317 } |
|
318 |
285 void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) { |
319 void ShenandoahBarrierSetAssembler::storeval_barrier(MacroAssembler* masm, Register dst, Register tmp) { |
286 if (ShenandoahStoreValEnqueueBarrier) { |
320 if (ShenandoahStoreValEnqueueBarrier) { |
287 // Save possibly live regs. |
321 // Save possibly live regs. |
288 RegSet live_regs = RegSet::range(r0, r4) - dst; |
322 RegSet live_regs = RegSet::range(r0, r4) - dst; |
289 __ push(live_regs, sp); |
323 __ push(live_regs, sp); |
307 } |
341 } |
308 |
342 |
309 void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
343 void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
310 Register dst, Address src, Register tmp1, Register tmp_thread) { |
344 Register dst, Address src, Register tmp1, Register tmp_thread) { |
311 bool on_oop = type == T_OBJECT || type == T_ARRAY; |
345 bool on_oop = type == T_OBJECT || type == T_ARRAY; |
|
346 bool not_in_heap = (decorators & IN_NATIVE) != 0; |
312 bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; |
347 bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; |
313 bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; |
348 bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; |
314 bool on_reference = on_weak || on_phantom; |
349 bool on_reference = on_weak || on_phantom; |
|
350 bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0; |
315 |
351 |
316 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
352 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
317 if (on_oop) { |
353 if (on_oop) { |
318 load_reference_barrier(masm, dst, tmp1); |
354 if (not_in_heap) { |
319 |
355 if (ShenandoahHeap::heap()->is_traversal_mode()) { |
320 if (ShenandoahKeepAliveBarrier && on_reference) { |
356 load_reference_barrier(masm, dst, tmp1); |
|
357 keep_alive = true; |
|
358 } else { |
|
359 load_reference_barrier_native(masm, dst, tmp1); |
|
360 } |
|
361 } else { |
|
362 load_reference_barrier(masm, dst, tmp1); |
|
363 } |
|
364 if (ShenandoahKeepAliveBarrier && on_reference && keep_alive) { |
321 __ enter(); |
365 __ enter(); |
322 satb_write_barrier_pre(masm /* masm */, |
366 satb_write_barrier_pre(masm /* masm */, |
323 noreg /* obj */, |
367 noreg /* obj */, |
324 dst /* pre_val */, |
368 dst /* pre_val */, |
325 rthread /* thread */, |
369 rthread /* thread */, |