20 * questions. |
20 * questions. |
21 * |
21 * |
22 */ |
22 */ |
23 |
23 |
24 #include "precompiled.hpp" |
24 #include "precompiled.hpp" |
|
25 #include "gc/shenandoah/shenandoahBarrierSet.hpp" |
25 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" |
26 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" |
26 #include "gc/shenandoah/shenandoahConcurrentRoots.hpp" |
|
27 #include "gc/shenandoah/shenandoahForwarding.hpp" |
27 #include "gc/shenandoah/shenandoahForwarding.hpp" |
28 #include "gc/shenandoah/shenandoahHeap.inline.hpp" |
28 #include "gc/shenandoah/shenandoahHeap.inline.hpp" |
29 #include "gc/shenandoah/shenandoahHeapRegion.hpp" |
29 #include "gc/shenandoah/shenandoahHeapRegion.hpp" |
30 #include "gc/shenandoah/shenandoahHeuristics.hpp" |
30 #include "gc/shenandoah/shenandoahHeuristics.hpp" |
31 #include "gc/shenandoah/shenandoahRuntime.hpp" |
31 #include "gc/shenandoah/shenandoahRuntime.hpp" |
465 if (!is_reference_type(type)) { |
465 if (!is_reference_type(type)) { |
466 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
466 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
467 return; |
467 return; |
468 } |
468 } |
469 |
469 |
470 // 2: load a reference from src location and apply LRB if ShenandoahLoadRefBarrier is set |
470 assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Not expected"); |
471 if (ShenandoahLoadRefBarrier) { |
471 |
|
472 // 2: load a reference from src location and apply LRB if needed |
|
473 if (ShenandoahBarrierSet::need_load_reference_barrier(decorators, type)) { |
472 Register result_dst = dst; |
474 Register result_dst = dst; |
473 bool use_tmp1_for_dst = false; |
475 bool use_tmp1_for_dst = false; |
474 |
476 |
475 // Preserve src location for LRB |
477 // Preserve src location for LRB |
476 if (dst == src.base() || dst == src.index()) { |
478 if (dst == src.base() || dst == src.index()) { |
485 assert_different_registers(dst, src.base(), src.index()); |
487 assert_different_registers(dst, src.base(), src.index()); |
486 } |
488 } |
487 |
489 |
488 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
490 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
489 |
491 |
490 // Native barrier is for concurrent root processing |
492 if (ShenandoahBarrierSet::use_load_reference_barrier_native(decorators, type)) { |
491 bool in_native = (decorators & IN_NATIVE) != 0; |
|
492 if (in_native && ShenandoahConcurrentRoots::can_do_concurrent_roots()) { |
|
493 load_reference_barrier_native(masm, dst, src); |
493 load_reference_barrier_native(masm, dst, src); |
494 } else { |
494 } else { |
495 load_reference_barrier(masm, dst, src); |
495 load_reference_barrier(masm, dst, src); |
496 } |
496 } |
497 |
497 |
507 } |
507 } |
508 } else { |
508 } else { |
509 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
509 BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); |
510 } |
510 } |
511 |
511 |
512 // 3: apply keep-alive barrier if ShenandoahKeepAliveBarrier is set |
512 // 3: apply keep-alive barrier if needed |
513 if (ShenandoahKeepAliveBarrier) { |
513 if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) { |
514 bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; |
514 const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); |
515 bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; |
515 assert_different_registers(dst, tmp1, tmp_thread); |
516 bool on_reference = on_weak || on_phantom; |
516 NOT_LP64(__ get_thread(thread)); |
517 bool is_traversal_mode = ShenandoahHeap::heap()->is_traversal_mode(); |
517 // Generate the SATB pre-barrier code to log the value of |
518 bool keep_alive = ((decorators & AS_NO_KEEPALIVE) == 0) || is_traversal_mode; |
518 // the referent field in an SATB buffer. |
519 |
519 shenandoah_write_barrier_pre(masm /* masm */, |
520 if (on_reference && keep_alive) { |
520 noreg /* obj */, |
521 const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread); |
521 dst /* pre_val */, |
522 assert_different_registers(dst, tmp1, tmp_thread); |
522 thread /* thread */, |
523 NOT_LP64(__ get_thread(thread)); |
523 tmp1 /* tmp */, |
524 // Generate the SATB pre-barrier code to log the value of |
524 true /* tosca_live */, |
525 // the referent field in an SATB buffer. |
525 true /* expand_call */); |
526 shenandoah_write_barrier_pre(masm /* masm */, |
|
527 noreg /* obj */, |
|
528 dst /* pre_val */, |
|
529 thread /* thread */, |
|
530 tmp1 /* tmp */, |
|
531 true /* tosca_live */, |
|
532 true /* expand_call */); |
|
533 } |
|
534 } |
526 } |
535 } |
527 } |
536 |
528 |
537 void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
529 void ShenandoahBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, |
538 Address dst, Register val, Register tmp1, Register tmp2) { |
530 Address dst, Register val, Register tmp1, Register tmp2) { |