532 } |
533 } |
533 return BarrierSetC2::store_at_resolved(access, val); |
534 return BarrierSetC2::store_at_resolved(access, val); |
534 } |
535 } |
535 |
536 |
536 Node* ShenandoahBarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) const { |
537 Node* ShenandoahBarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) const { |
|
538 // 1: non-reference load, no additional barrier is needed |
|
539 if (!access.is_oop()) { |
|
540 return BarrierSetC2::load_at_resolved(access, val_type);; |
|
541 } |
|
542 |
|
543 Node* load = BarrierSetC2::load_at_resolved(access, val_type); |
537 DecoratorSet decorators = access.decorators(); |
544 DecoratorSet decorators = access.decorators(); |
538 |
|
539 Node* adr = access.addr().node(); |
|
540 Node* obj = access.base(); |
|
541 |
|
542 bool mismatched = (decorators & C2_MISMATCHED) != 0; |
|
543 bool unknown = (decorators & ON_UNKNOWN_OOP_REF) != 0; |
|
544 bool on_heap = (decorators & IN_HEAP) != 0; |
|
545 bool on_weak_ref = (decorators & (ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF)) != 0; |
|
546 bool is_unordered = (decorators & MO_UNORDERED) != 0; |
|
547 bool need_cpu_mem_bar = !is_unordered || mismatched || !on_heap; |
|
548 bool is_traversal_mode = ShenandoahHeap::heap()->is_traversal_mode(); |
|
549 bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0 || is_traversal_mode; |
|
550 bool in_native = (decorators & IN_NATIVE) != 0; |
545 bool in_native = (decorators & IN_NATIVE) != 0; |
551 |
546 |
552 Node* top = Compile::current()->top(); |
547 // 2: apply LRB if ShenandoahLoadRefBarrier is set |
553 |
548 if (ShenandoahLoadRefBarrier) { |
554 Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : top; |
549 // Native barrier is for concurrent root processing |
555 Node* load = BarrierSetC2::load_at_resolved(access, val_type); |
550 bool use_native_barrier = in_native && ShenandoahConcurrentRoots::can_do_concurrent_roots(); |
556 |
551 load = new ShenandoahLoadReferenceBarrierNode(NULL, load, use_native_barrier); |
557 if (access.is_oop()) { |
552 if (access.is_parse_access()) { |
558 if (ShenandoahLoadRefBarrier) { |
553 load = static_cast<C2ParseAccess &>(access).kit()->gvn().transform(load); |
559 load = new ShenandoahLoadReferenceBarrierNode(NULL, load, in_native && !is_traversal_mode); |
554 } else { |
560 if (access.is_parse_access()) { |
555 load = static_cast<C2OptAccess &>(access).gvn().transform(load); |
561 load = static_cast<C2ParseAccess &>(access).kit()->gvn().transform(load); |
556 } |
562 } else { |
557 } |
563 load = static_cast<C2OptAccess &>(access).gvn().transform(load); |
558 |
564 } |
559 // 3: apply keep-alive barrier if ShenandoahKeepAliveBarrier is set |
565 } |
560 if (ShenandoahKeepAliveBarrier) { |
566 } |
561 Node* top = Compile::current()->top(); |
567 |
562 Node* adr = access.addr().node(); |
568 // If we are reading the value of the referent field of a Reference |
563 Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : top; |
569 // object (either by using Unsafe directly or through reflection) |
564 Node* obj = access.base(); |
570 // then, if SATB is enabled, we need to record the referent in an |
565 |
571 // SATB log buffer using the pre-barrier mechanism. |
566 bool unknown = (decorators & ON_UNKNOWN_OOP_REF) != 0; |
572 // Also we need to add memory barrier to prevent commoning reads |
567 bool on_weak_ref = (decorators & (ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF)) != 0; |
573 // from this field across safepoint since GC can change its value. |
568 bool is_traversal_mode = ShenandoahHeap::heap()->is_traversal_mode(); |
574 bool need_read_barrier = ShenandoahKeepAliveBarrier && |
569 bool keep_alive = (decorators & AS_NO_KEEPALIVE) == 0 || is_traversal_mode; |
575 (on_weak_ref || (unknown && offset != top && obj != top)); |
570 |
576 |
571 // If we are reading the value of the referent field of a Reference |
577 if (!access.is_oop() || !need_read_barrier) { |
572 // object (either by using Unsafe directly or through reflection) |
578 return load; |
573 // then, if SATB is enabled, we need to record the referent in an |
579 } |
574 // SATB log buffer using the pre-barrier mechanism. |
580 |
575 // Also we need to add memory barrier to prevent commoning reads |
581 assert(access.is_parse_access(), "entry not supported at optimization time"); |
576 // from this field across safepoint since GC can change its value. |
582 C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access); |
577 if (!on_weak_ref || (unknown && (offset == top || obj == top)) || !keep_alive) { |
583 GraphKit* kit = parse_access.kit(); |
578 return load; |
584 |
579 } |
585 if (on_weak_ref && keep_alive) { |
580 |
586 // Use the pre-barrier to record the value in the referent field |
581 assert(access.is_parse_access(), "entry not supported at optimization time"); |
587 satb_write_barrier_pre(kit, false /* do_load */, |
582 C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access); |
588 NULL /* obj */, NULL /* adr */, max_juint /* alias_idx */, NULL /* val */, NULL /* val_type */, |
583 GraphKit* kit = parse_access.kit(); |
589 load /* pre_val */, T_OBJECT); |
584 bool mismatched = (decorators & C2_MISMATCHED) != 0; |
590 // Add memory barrier to prevent commoning reads from this field |
585 bool is_unordered = (decorators & MO_UNORDERED) != 0; |
591 // across safepoint since GC can change its value. |
586 bool need_cpu_mem_bar = !is_unordered || mismatched || in_native; |
592 kit->insert_mem_bar(Op_MemBarCPUOrder); |
587 |
593 } else if (unknown) { |
588 if (on_weak_ref) { |
594 // We do not require a mem bar inside pre_barrier if need_mem_bar |
589 // Use the pre-barrier to record the value in the referent field |
595 // is set: the barriers would be emitted by us. |
590 satb_write_barrier_pre(kit, false /* do_load */, |
596 insert_pre_barrier(kit, obj, offset, load, !need_cpu_mem_bar); |
591 NULL /* obj */, NULL /* adr */, max_juint /* alias_idx */, NULL /* val */, NULL /* val_type */, |
|
592 load /* pre_val */, T_OBJECT); |
|
593 // Add memory barrier to prevent commoning reads from this field |
|
594 // across safepoint since GC can change its value. |
|
595 kit->insert_mem_bar(Op_MemBarCPUOrder); |
|
596 } else if (unknown) { |
|
597 // We do not require a mem bar inside pre_barrier if need_mem_bar |
|
598 // is set: the barriers would be emitted by us. |
|
599 insert_pre_barrier(kit, obj, offset, load, !need_cpu_mem_bar); |
|
600 } |
597 } |
601 } |
598 |
602 |
599 return load; |
603 return load; |
600 } |
604 } |
601 |
605 |