757
758 bool ShenandoahBarrierSetC2::optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const {
759 if (mode == LoopOptsShenandoahExpand) {
760 assert(UseShenandoahGC, "only for shenandoah");
761 ShenandoahBarrierC2Support::pin_and_expand(phase);
762 return true;
763 } else if (mode == LoopOptsShenandoahPostExpand) {
764 assert(UseShenandoahGC, "only for shenandoah");
765 visited.clear();
766 ShenandoahBarrierC2Support::optimize_after_expansion(visited, nstack, worklist, phase);
767 return true;
768 }
769 return false;
770 }
771
772 bool ShenandoahBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
773 bool is_oop = is_reference_type(type);
774 if (!is_oop) {
775 return false;
776 }
777 if (tightly_coupled_alloc) {
778 if (phase == Optimization) {
779 return false;
780 }
781 return !is_clone;
782 }
783 if (phase == Optimization) {
784 return !ShenandoahStoreValEnqueueBarrier;
785 }
786 return true;
787 }
788
789 bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
790 const TypeOopPtr* src_type = gvn.type(src)->is_oopptr();
791 if (src_type->isa_instptr() != NULL) {
792 ciInstanceKlass* ik = src_type->klass()->as_instance_klass();
793 if ((src_type->klass_is_exact() || (!ik->is_interface() && !ik->has_subklass())) && !ik->has_injected_fields()) {
794 if (ik->has_object_fields()) {
795 return true;
796 } else {
797 if (!src_type->klass_is_exact()) {
824 Node* src = phase->basic_plus_adr(src_base, src_offset);
825 Node* dest = phase->basic_plus_adr(dest_base, dest_offset);
826
827 if (ShenandoahCloneBarrier && clone_needs_barrier(src, phase->igvn())) {
828 // Check if heap is has forwarded objects. If it does, we need to call into the special
829 // routine that would fix up source references before we can continue.
830
831 enum { _heap_stable = 1, _heap_unstable, PATH_LIMIT };
832 Node* region = new RegionNode(PATH_LIMIT);
833 Node* mem_phi = new PhiNode(region, Type::MEMORY, TypeRawPtr::BOTTOM);
834
835 Node* thread = phase->transform_later(new ThreadLocalNode());
836 Node* offset = phase->igvn().MakeConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
837 Node* gc_state_addr = phase->transform_later(new AddPNode(phase->C->top(), thread, offset));
838
839 uint gc_state_idx = Compile::AliasIdxRaw;
840 const TypePtr* gc_state_adr_type = NULL; // debug-mode-only argument
841 debug_only(gc_state_adr_type = phase->C->get_adr_type(gc_state_idx));
842
843 Node* gc_state = phase->transform_later(new LoadBNode(ctrl, mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered));
844 Node* stable_and = phase->transform_later(new AndINode(gc_state, phase->igvn().intcon(ShenandoahHeap::HAS_FORWARDED)));
845 Node* stable_cmp = phase->transform_later(new CmpINode(stable_and, phase->igvn().zerocon(T_INT)));
846 Node* stable_test = phase->transform_later(new BoolNode(stable_cmp, BoolTest::ne));
847
848 IfNode* stable_iff = phase->transform_later(new IfNode(ctrl, stable_test, PROB_UNLIKELY(0.999), COUNT_UNKNOWN))->as_If();
849 Node* stable_ctrl = phase->transform_later(new IfFalseNode(stable_iff));
850 Node* unstable_ctrl = phase->transform_later(new IfTrueNode(stable_iff));
851
852 // Heap is stable, no need to do anything additional
853 region->init_req(_heap_stable, stable_ctrl);
854 mem_phi->init_req(_heap_stable, mem);
855
856 // Heap is unstable, call into clone barrier stub
857 Node* call = phase->make_leaf_call(unstable_ctrl, mem,
858 ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type(),
859 CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier),
860 "shenandoah_clone",
861 TypeRawPtr::BOTTOM,
862 src_base);
863 call = phase->transform_later(call);
864
|
757
758 bool ShenandoahBarrierSetC2::optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const {
759 if (mode == LoopOptsShenandoahExpand) {
760 assert(UseShenandoahGC, "only for shenandoah");
761 ShenandoahBarrierC2Support::pin_and_expand(phase);
762 return true;
763 } else if (mode == LoopOptsShenandoahPostExpand) {
764 assert(UseShenandoahGC, "only for shenandoah");
765 visited.clear();
766 ShenandoahBarrierC2Support::optimize_after_expansion(visited, nstack, worklist, phase);
767 return true;
768 }
769 return false;
770 }
771
772 bool ShenandoahBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
773 bool is_oop = is_reference_type(type);
774 if (!is_oop) {
775 return false;
776 }
777 if (ShenandoahSATBBarrier && tightly_coupled_alloc) {
778 if (phase == Optimization) {
779 return false;
780 }
781 return !is_clone;
782 }
783 if (phase == Optimization) {
784 return !ShenandoahStoreValEnqueueBarrier;
785 }
786 return true;
787 }
788
789 bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
790 const TypeOopPtr* src_type = gvn.type(src)->is_oopptr();
791 if (src_type->isa_instptr() != NULL) {
792 ciInstanceKlass* ik = src_type->klass()->as_instance_klass();
793 if ((src_type->klass_is_exact() || (!ik->is_interface() && !ik->has_subklass())) && !ik->has_injected_fields()) {
794 if (ik->has_object_fields()) {
795 return true;
796 } else {
797 if (!src_type->klass_is_exact()) {
824 Node* src = phase->basic_plus_adr(src_base, src_offset);
825 Node* dest = phase->basic_plus_adr(dest_base, dest_offset);
826
827 if (ShenandoahCloneBarrier && clone_needs_barrier(src, phase->igvn())) {
828 // Check if heap is has forwarded objects. If it does, we need to call into the special
829 // routine that would fix up source references before we can continue.
830
831 enum { _heap_stable = 1, _heap_unstable, PATH_LIMIT };
832 Node* region = new RegionNode(PATH_LIMIT);
833 Node* mem_phi = new PhiNode(region, Type::MEMORY, TypeRawPtr::BOTTOM);
834
835 Node* thread = phase->transform_later(new ThreadLocalNode());
836 Node* offset = phase->igvn().MakeConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
837 Node* gc_state_addr = phase->transform_later(new AddPNode(phase->C->top(), thread, offset));
838
839 uint gc_state_idx = Compile::AliasIdxRaw;
840 const TypePtr* gc_state_adr_type = NULL; // debug-mode-only argument
841 debug_only(gc_state_adr_type = phase->C->get_adr_type(gc_state_idx));
842
843 Node* gc_state = phase->transform_later(new LoadBNode(ctrl, mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered));
844 int flags = ShenandoahHeap::HAS_FORWARDED;
845 if (ShenandoahStoreValEnqueueBarrier) {
846 flags |= ShenandoahHeap::MARKING;
847 }
848 Node* stable_and = phase->transform_later(new AndINode(gc_state, phase->igvn().intcon(flags)));
849 Node* stable_cmp = phase->transform_later(new CmpINode(stable_and, phase->igvn().zerocon(T_INT)));
850 Node* stable_test = phase->transform_later(new BoolNode(stable_cmp, BoolTest::ne));
851
852 IfNode* stable_iff = phase->transform_later(new IfNode(ctrl, stable_test, PROB_UNLIKELY(0.999), COUNT_UNKNOWN))->as_If();
853 Node* stable_ctrl = phase->transform_later(new IfFalseNode(stable_iff));
854 Node* unstable_ctrl = phase->transform_later(new IfTrueNode(stable_iff));
855
856 // Heap is stable, no need to do anything additional
857 region->init_req(_heap_stable, stable_ctrl);
858 mem_phi->init_req(_heap_stable, mem);
859
860 // Heap is unstable, call into clone barrier stub
861 Node* call = phase->make_leaf_call(unstable_ctrl, mem,
862 ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type(),
863 CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier),
864 "shenandoah_clone",
865 TypeRawPtr::BOTTOM,
866 src_base);
867 call = phase->transform_later(call);
868
|