28 #include "gc/g1/g1BarrierSetRuntime.hpp" |
28 #include "gc/g1/g1BarrierSetRuntime.hpp" |
29 #include "gc/g1/g1CardTable.hpp" |
29 #include "gc/g1/g1CardTable.hpp" |
30 #include "gc/g1/g1ThreadLocalData.hpp" |
30 #include "gc/g1/g1ThreadLocalData.hpp" |
31 #include "gc/g1/heapRegion.hpp" |
31 #include "gc/g1/heapRegion.hpp" |
32 #include "opto/arraycopynode.hpp" |
32 #include "opto/arraycopynode.hpp" |
|
33 #include "opto/compile.hpp" |
33 #include "opto/graphKit.hpp" |
34 #include "opto/graphKit.hpp" |
34 #include "opto/idealKit.hpp" |
35 #include "opto/idealKit.hpp" |
35 #include "opto/macro.hpp" |
36 #include "opto/macro.hpp" |
|
37 #include "opto/rootnode.hpp" |
36 #include "opto/type.hpp" |
38 #include "opto/type.hpp" |
37 #include "utilities/macros.hpp" |
39 #include "utilities/macros.hpp" |
38 |
40 |
39 const TypeFunc *G1BarrierSetC2::write_ref_field_pre_entry_Type() { |
41 const TypeFunc *G1BarrierSetC2::write_ref_field_pre_entry_Type() { |
40 const Type **fields = TypeTuple::fields(2); |
42 const Type **fields = TypeTuple::fields(2); |
771 } |
773 } |
772 } |
774 } |
773 } |
775 } |
774 return c; |
776 return c; |
775 } |
777 } |
|
778 |
|
779 #ifdef ASSERT |
|
780 void G1BarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase phase) const { |
|
781 // Verify G1 pre-barriers |
|
782 const int marking_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()); |
|
783 |
|
784 ResourceArea *area = Thread::current()->resource_area(); |
|
785 Unique_Node_List visited(area); |
|
786 Node_List worklist(area); |
|
787 // We're going to walk control flow backwards starting from the Root |
|
788 worklist.push(compile->root()); |
|
789 while (worklist.size() > 0) { |
|
790 Node* x = worklist.pop(); |
|
791 if (x == NULL || x == compile->top()) continue; |
|
792 if (visited.member(x)) { |
|
793 continue; |
|
794 } else { |
|
795 visited.push(x); |
|
796 } |
|
797 |
|
798 if (x->is_Region()) { |
|
799 for (uint i = 1; i < x->req(); i++) { |
|
800 worklist.push(x->in(i)); |
|
801 } |
|
802 } else { |
|
803 worklist.push(x->in(0)); |
|
804 // We are looking for the pattern: |
|
805 // /->ThreadLocal |
|
806 // If->Bool->CmpI->LoadB->AddP->ConL(marking_offset) |
|
807 // \->ConI(0) |
|
808 // We want to verify that the If and the LoadB have the same control |
|
809 // See GraphKit::g1_write_barrier_pre() |
|
810 if (x->is_If()) { |
|
811 IfNode *iff = x->as_If(); |
|
812 if (iff->in(1)->is_Bool() && iff->in(1)->in(1)->is_Cmp()) { |
|
813 CmpNode *cmp = iff->in(1)->in(1)->as_Cmp(); |
|
814 if (cmp->Opcode() == Op_CmpI && cmp->in(2)->is_Con() && cmp->in(2)->bottom_type()->is_int()->get_con() == 0 |
|
815 && cmp->in(1)->is_Load()) { |
|
816 LoadNode* load = cmp->in(1)->as_Load(); |
|
817 if (load->Opcode() == Op_LoadB && load->in(2)->is_AddP() && load->in(2)->in(2)->Opcode() == Op_ThreadLocal |
|
818 && load->in(2)->in(3)->is_Con() |
|
819 && load->in(2)->in(3)->bottom_type()->is_intptr_t()->get_con() == marking_offset) { |
|
820 |
|
821 Node* if_ctrl = iff->in(0); |
|
822 Node* load_ctrl = load->in(0); |
|
823 |
|
824 if (if_ctrl != load_ctrl) { |
|
825 // Skip possible CProj->NeverBranch in infinite loops |
|
826 if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj) |
|
827 && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) { |
|
828 if_ctrl = if_ctrl->in(0)->in(0); |
|
829 } |
|
830 } |
|
831 assert(load_ctrl != NULL && if_ctrl == load_ctrl, "controls must match"); |
|
832 } |
|
833 } |
|
834 } |
|
835 } |
|
836 } |
|
837 } |
|
838 } |
|
839 #endif |