src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp
changeset 54423 6c0ab8bd8da5
parent 54327 a4d19817609c
child 54766 1321f8cf9de5
equal deleted inserted replaced
54422:f562f8318ebd 54423:6c0ab8bd8da5
    34 #include "opto/node.hpp"
    34 #include "opto/node.hpp"
    35 
    35 
    36 class PhaseGVN;
    36 class PhaseGVN;
    37 class MemoryGraphFixer;
    37 class MemoryGraphFixer;
    38 
    38 
    39 class ShenandoahBarrierNode : public TypeNode {
    39 class ShenandoahBarrierC2Support : public AllStatic {
    40 private:
    40 private:
    41   bool _allow_fromspace;
       
    42 
       
    43 #ifdef ASSERT
    41 #ifdef ASSERT
    44   enum verify_type {
    42   enum verify_type {
    45     ShenandoahLoad,
    43     ShenandoahLoad,
    46     ShenandoahStore,
    44     ShenandoahStore,
    47     ShenandoahValue,
    45     ShenandoahValue,
    48     ShenandoahOopStore,
    46     ShenandoahOopStore,
    49     ShenandoahNone,
    47     ShenandoahNone,
    50   };
    48   };
    51 
    49 
    52   static bool verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used);
    50   static bool verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used);
    53 #endif
       
    54 
       
    55 public:
       
    56   enum { Control,
       
    57          Memory,
       
    58          ValueIn
       
    59   };
       
    60 
       
    61   ShenandoahBarrierNode(Node* ctrl, Node* mem, Node* obj, bool allow_fromspace)
       
    62     : TypeNode(obj->bottom_type()->isa_oopptr() ? obj->bottom_type()->is_oopptr()->cast_to_nonconst() : obj->bottom_type(), 3),
       
    63       _allow_fromspace(allow_fromspace) {
       
    64 
       
    65     init_req(Control, ctrl);
       
    66     init_req(Memory, mem);
       
    67     init_req(ValueIn, obj);
       
    68 
       
    69     init_class_id(Class_ShenandoahBarrier);
       
    70   }
       
    71 
       
    72   static Node* skip_through_barrier(Node* n);
       
    73 
       
    74   static const TypeOopPtr* brooks_pointer_type(const Type* t) {
       
    75     return t->is_oopptr()->cast_to_nonconst()->add_offset(ShenandoahBrooksPointer::byte_offset())->is_oopptr();
       
    76   }
       
    77 
       
    78   virtual const TypePtr* adr_type() const {
       
    79     if (bottom_type() == Type::TOP) {
       
    80       return NULL;
       
    81     }
       
    82     //const TypePtr* adr_type = in(MemNode::Address)->bottom_type()->is_ptr();
       
    83     const TypePtr* adr_type = brooks_pointer_type(bottom_type());
       
    84     assert(adr_type->offset() == ShenandoahBrooksPointer::byte_offset(), "sane offset");
       
    85     assert(Compile::current()->alias_type(adr_type)->is_rewritable(), "brooks ptr must be rewritable");
       
    86     return adr_type;
       
    87   }
       
    88 
       
    89   virtual uint  ideal_reg() const { return Op_RegP; }
       
    90   virtual uint match_edge(uint idx) const {
       
    91     return idx >= ValueIn;
       
    92   }
       
    93 
       
    94   Node* Identity_impl(PhaseGVN* phase);
       
    95 
       
    96   virtual const Type* Value(PhaseGVN* phase) const;
       
    97   virtual bool depends_only_on_test() const {
       
    98     return true;
       
    99   };
       
   100 
       
   101   static bool needs_barrier(PhaseGVN* phase, ShenandoahBarrierNode* orig, Node* n, Node* rb_mem, bool allow_fromspace);
       
   102 
       
   103 #ifdef ASSERT
       
   104   static void report_verify_failure(const char* msg, Node* n1 = NULL, Node* n2 = NULL);
    51   static void report_verify_failure(const char* msg, Node* n1 = NULL, Node* n2 = NULL);
   105   static void verify(RootNode* root);
       
   106   static void verify_raw_mem(RootNode* root);
    52   static void verify_raw_mem(RootNode* root);
   107 #endif
    53 #endif
   108 #ifndef PRODUCT
       
   109   virtual void dump_spec(outputStream *st) const;
       
   110 #endif
       
   111 
       
   112   // protected:
       
   113   static Node* dom_mem(Node* mem, Node*& mem_ctrl, Node* n, Node* rep_ctrl, int alias, PhaseIdealLoop* phase);
       
   114   static Node* dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase);
    54   static Node* dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase);
   115   static bool is_dominator(Node *d_c, Node *n_c, Node* d, Node* n, PhaseIdealLoop* phase);
       
   116   static bool is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase);
       
   117   static Node* no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase);
    55   static Node* no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase);
   118   static bool build_loop_late_post(PhaseIdealLoop* phase, Node* n);
       
   119   bool sink_node(PhaseIdealLoop* phase, Node* ctrl, Node* n_ctrl);
       
   120 
       
   121 protected:
       
   122   uint hash() const;
       
   123   bool cmp(const Node& n) const;
       
   124   uint size_of() const;
       
   125 
       
   126 private:
       
   127   static bool needs_barrier_impl(PhaseGVN* phase, ShenandoahBarrierNode* orig, Node* n, Node* rb_mem, bool allow_fromspace, Unique_Node_List &visited);
       
   128 
       
   129   static bool dominates_memory(PhaseGVN* phase, Node* b1, Node* b2, bool linear);
       
   130   static bool dominates_memory_impl(PhaseGVN* phase, Node* b1, Node* b2, Node* current, bool linear);
       
   131 };
       
   132 
       
   133 class ShenandoahReadBarrierNode : public ShenandoahBarrierNode {
       
   134 public:
       
   135   ShenandoahReadBarrierNode(Node* ctrl, Node* mem, Node* obj)
       
   136     : ShenandoahBarrierNode(ctrl, mem, obj, true) {
       
   137     assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier ||
       
   138                                ShenandoahWriteBarrier || ShenandoahAcmpBarrier),
       
   139            "should be enabled");
       
   140   }
       
   141   ShenandoahReadBarrierNode(Node* ctrl, Node* mem, Node* obj, bool allow_fromspace)
       
   142     : ShenandoahBarrierNode(ctrl, mem, obj, allow_fromspace) {
       
   143     assert(UseShenandoahGC && (ShenandoahReadBarrier || ShenandoahStoreValReadBarrier ||
       
   144                                ShenandoahWriteBarrier || ShenandoahAcmpBarrier),
       
   145            "should be enabled");
       
   146   }
       
   147 
       
   148   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
       
   149   virtual Node* Identity(PhaseGVN* phase);
       
   150   virtual int Opcode() const;
       
   151 
       
   152   bool is_independent(Node* mem);
       
   153 
       
   154   void try_move(PhaseIdealLoop* phase);
       
   155 
       
   156 private:
       
   157   static bool is_independent(const Type* in_type, const Type* this_type);
       
   158   static bool dominates_memory_rb(PhaseGVN* phase, Node* b1, Node* b2, bool linear);
       
   159   static bool dominates_memory_rb_impl(PhaseGVN* phase, Node* b1, Node* b2, Node* current, bool linear);
       
   160 };
       
   161 
       
   162 class ShenandoahWriteBarrierNode : public ShenandoahBarrierNode {
       
   163 public:
       
   164   ShenandoahWriteBarrierNode(Compile* C, Node* ctrl, Node* mem, Node* obj);
       
   165 
       
   166   virtual int Opcode() const;
       
   167   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
       
   168   virtual Node* Identity(PhaseGVN* phase);
       
   169   virtual bool depends_only_on_test() const { return false; }
       
   170 
       
   171   static bool expand(Compile* C, PhaseIterGVN& igvn);
       
   172   static bool is_gc_state_load(Node *n);
       
   173   static bool is_heap_state_test(Node* iff, int mask);
    56   static bool is_heap_state_test(Node* iff, int mask);
   174   static bool is_heap_stable_test(Node* iff);
       
   175   static bool try_common_gc_state_load(Node *n, PhaseIdealLoop *phase);
    57   static bool try_common_gc_state_load(Node *n, PhaseIdealLoop *phase);
   176   static bool has_safepoint_between(Node* start, Node* stop, PhaseIdealLoop *phase);
    58   static bool has_safepoint_between(Node* start, Node* stop, PhaseIdealLoop *phase);
   177 
       
   178   static LoopNode* try_move_before_pre_loop(Node* c, Node* val_ctrl, PhaseIdealLoop* phase);
       
   179   static Node* move_above_predicates(LoopNode* cl, Node* val_ctrl, PhaseIdealLoop* phase);
       
   180 #ifdef ASSERT
       
   181   static bool memory_dominates_all_paths(Node* mem, Node* rep_ctrl, int alias, PhaseIdealLoop* phase);
       
   182   static void memory_dominates_all_paths_helper(Node* c, Node* rep_ctrl, Unique_Node_List& controls, PhaseIdealLoop* phase);
       
   183 #endif
       
   184   void try_move_before_loop(GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, PhaseIdealLoop* phase, bool include_lsm, Unique_Node_List& uses);
       
   185   void try_move_before_loop_helper(LoopNode* cl, Node* val_ctrl, GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, PhaseIdealLoop* phase, bool include_lsm, Unique_Node_List& uses);
       
   186   static void pin_and_expand(PhaseIdealLoop* phase);
       
   187   CallStaticJavaNode* pin_and_expand_null_check(PhaseIterGVN& igvn);
       
   188   void pin_and_expand_move_barrier(PhaseIdealLoop* phase, GrowableArray<MemoryGraphFixer*>& memory_graph_fixers, Unique_Node_List& uses);
       
   189   void pin_and_expand_helper(PhaseIdealLoop* phase);
       
   190   static Node* find_bottom_mem(Node* ctrl, PhaseIdealLoop* phase);
    59   static Node* find_bottom_mem(Node* ctrl, PhaseIdealLoop* phase);
   191   static void follow_barrier_uses(Node* n, Node* ctrl, Unique_Node_List& uses, PhaseIdealLoop* phase);
    60   static void follow_barrier_uses(Node* n, Node* ctrl, Unique_Node_List& uses, PhaseIdealLoop* phase);
   192   static void test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase);
    61   static void test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase);
   193 
       
   194   static void test_heap_stable(Node*& ctrl, Node* raw_mem, Node*& heap_stable_ctrl,
    62   static void test_heap_stable(Node*& ctrl, Node* raw_mem, Node*& heap_stable_ctrl,
   195                                PhaseIdealLoop* phase);
    63                                PhaseIdealLoop* phase);
   196   static void call_wb_stub(Node*& ctrl, Node*& val, Node*& result_mem,
    64   static void call_lrb_stub(Node*& ctrl, Node*& val, Node*& result_mem, Node* raw_mem, PhaseIdealLoop* phase);
   197                            Node* raw_mem, Node* wb_mem, int alias,
       
   198                            PhaseIdealLoop* phase);
       
   199   static Node* clone_null_check(Node*& c, Node* val, Node* unc_ctrl, PhaseIdealLoop* phase);
    65   static Node* clone_null_check(Node*& c, Node* val, Node* unc_ctrl, PhaseIdealLoop* phase);
   200   static void fix_null_check(Node* unc, Node* unc_ctrl, Node* new_unc_ctrl, Unique_Node_List& uses,
    66   static void fix_null_check(Node* unc, Node* unc_ctrl, Node* new_unc_ctrl, Unique_Node_List& uses,
   201                              PhaseIdealLoop* phase);
    67                              PhaseIdealLoop* phase);
   202   static void in_cset_fast_test(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase);
    68   static void in_cset_fast_test(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase);
   203   static void move_heap_stable_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase);
    69   static void move_heap_stable_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase);
   204 
       
   205   static void optimize_after_expansion(VectorSet &visited, Node_Stack &nstack, Node_List &old_new, PhaseIdealLoop* phase);
       
   206   static void merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase);
    70   static void merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase);
   207   static bool identical_backtoback_ifs(Node *n, PhaseIdealLoop* phase);
    71   static bool identical_backtoback_ifs(Node *n, PhaseIdealLoop* phase);
   208   static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase);
    72   static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase);
   209 
       
   210   static void optimize_before_expansion(PhaseIdealLoop* phase, GrowableArray<MemoryGraphFixer*> memory_graph_fixers, bool include_lsm);
       
   211   Node* would_subsume(ShenandoahBarrierNode* other, PhaseIdealLoop* phase);
       
   212   static IfNode* find_unswitching_candidate(const IdealLoopTree *loop, PhaseIdealLoop* phase);
    73   static IfNode* find_unswitching_candidate(const IdealLoopTree *loop, PhaseIdealLoop* phase);
   213 
    74 
   214   Node* try_split_thru_phi(PhaseIdealLoop* phase);
    75 public:
   215 };
    76   static bool is_dominator(Node* d_c, Node* n_c, Node* d, Node* n, PhaseIdealLoop* phase);
   216 
    77   static bool is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase);
   217 class ShenandoahWBMemProjNode : public Node {
    78 
   218 public:
    79   static bool is_gc_state_load(Node* n);
   219   enum { Control,
    80   static bool is_heap_stable_test(Node* iff);
   220          WriteBarrier };
    81 
   221 
    82   static bool expand(Compile* C, PhaseIterGVN& igvn);
   222   ShenandoahWBMemProjNode(Node *src) : Node(NULL, src) {
    83   static void pin_and_expand(PhaseIdealLoop* phase);
   223     assert(UseShenandoahGC && ShenandoahWriteBarrier, "should be enabled");
    84   static void optimize_after_expansion(VectorSet& visited, Node_Stack& nstack, Node_List& old_new, PhaseIdealLoop* phase);
   224     assert(src->Opcode() == Op_ShenandoahWriteBarrier || src->is_Mach(), "epxect wb");
    85 
   225   }
    86 #ifdef ASSERT
   226   virtual Node* Identity(PhaseGVN* phase);
    87   static void verify(RootNode* root);
   227 
       
   228   virtual int Opcode() const;
       
   229   virtual bool      is_CFG() const  { return false; }
       
   230   virtual const Type *bottom_type() const {return Type::MEMORY;}
       
   231   virtual const TypePtr *adr_type() const {
       
   232     Node* wb = in(WriteBarrier);
       
   233     if (wb == NULL || wb->is_top())  return NULL; // node is dead
       
   234     assert(wb->Opcode() == Op_ShenandoahWriteBarrier || (wb->is_Mach() && wb->as_Mach()->ideal_Opcode() == Op_ShenandoahWriteBarrier) || wb->is_Phi(), "expect wb");
       
   235     return ShenandoahBarrierNode::brooks_pointer_type(wb->bottom_type());
       
   236   }
       
   237 
       
   238   virtual uint ideal_reg() const { return 0;} // memory projections don't have a register
       
   239   virtual const Type *Value(PhaseGVN* phase ) const {
       
   240     return bottom_type();
       
   241   }
       
   242 #ifndef PRODUCT
       
   243   virtual void dump_spec(outputStream *st) const {};
       
   244 #endif
    88 #endif
   245 };
    89 };
   246 
    90 
   247 class ShenandoahEnqueueBarrierNode : public Node {
    91 class ShenandoahEnqueueBarrierNode : public Node {
   248 public:
    92 public:
   249   ShenandoahEnqueueBarrierNode(Node* val) : Node(NULL, val) {
    93   ShenandoahEnqueueBarrierNode(Node* val);
   250   }
       
   251 
    94 
   252   const Type *bottom_type() const;
    95   const Type *bottom_type() const;
   253   const Type* Value(PhaseGVN* phase) const;
    96   const Type* Value(PhaseGVN* phase) const;
   254   Node* Identity(PhaseGVN* phase);
    97   Node* Identity(PhaseGVN* phase);
   255 
    98 
   287   }
   130   }
   288 
   131 
   289   Node* find_mem(Node* ctrl, Node* n) const;
   132   Node* find_mem(Node* ctrl, Node* n) const;
   290   void fix_mem(Node* ctrl, Node* region, Node* mem, Node* mem_for_ctrl, Node* mem_phi, Unique_Node_List& uses);
   133   void fix_mem(Node* ctrl, Node* region, Node* mem, Node* mem_for_ctrl, Node* mem_phi, Unique_Node_List& uses);
   291   int alias() const { return _alias; }
   134   int alias() const { return _alias; }
   292   void remove(Node* n);
       
   293 };
   135 };
   294 
   136 
   295 class ShenandoahCompareAndSwapPNode : public CompareAndSwapPNode {
   137 class ShenandoahCompareAndSwapPNode : public CompareAndSwapPNode {
   296 public:
   138 public:
   297   ShenandoahCompareAndSwapPNode(Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord)
   139   ShenandoahCompareAndSwapPNode(Node *c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord)
   380   }
   222   }
   381 
   223 
   382   virtual int Opcode() const;
   224   virtual int Opcode() const;
   383 };
   225 };
   384 
   226 
       
   227 class ShenandoahLoadReferenceBarrierNode : public Node {
       
   228 public:
       
   229   enum {
       
   230     Control,
       
   231     ValueIn
       
   232   };
       
   233 
       
   234   enum Strength {
       
   235     NONE, WEAK, STRONG, NA
       
   236   };
       
   237 
       
   238   ShenandoahLoadReferenceBarrierNode(Node* ctrl, Node* val);
       
   239 
       
   240   virtual int Opcode() const;
       
   241   virtual const Type* bottom_type() const;
       
   242   virtual const Type* Value(PhaseGVN* phase) const;
       
   243   virtual const class TypePtr *adr_type() const { return TypeOopPtr::BOTTOM; }
       
   244   virtual uint match_edge(uint idx) const {
       
   245     return idx >= ValueIn;
       
   246   }
       
   247   virtual uint ideal_reg() const { return Op_RegP; }
       
   248 
       
   249   virtual Node* Identity(PhaseGVN* phase);
       
   250 
       
   251   uint size_of() const {
       
   252     return sizeof(*this);
       
   253   }
       
   254 
       
   255   Strength get_barrier_strength();
       
   256   CallStaticJavaNode* pin_and_expand_null_check(PhaseIterGVN& igvn);
       
   257 
       
   258 private:
       
   259   bool needs_barrier(PhaseGVN* phase, Node* n);
       
   260   bool needs_barrier_impl(PhaseGVN* phase, Node* n, Unique_Node_List &visited);
       
   261 };
       
   262 
       
   263 
   385 #endif // SHARE_GC_SHENANDOAH_C2_SHENANDOAHSUPPORT_HPP
   264 #endif // SHARE_GC_SHENANDOAH_C2_SHENANDOAHSUPPORT_HPP