27 #include "gc/shared/c2/barrierSetC2.hpp" |
27 #include "gc/shared/c2/barrierSetC2.hpp" |
28 #include "memory/allocation.hpp" |
28 #include "memory/allocation.hpp" |
29 #include "opto/node.hpp" |
29 #include "opto/node.hpp" |
30 #include "utilities/growableArray.hpp" |
30 #include "utilities/growableArray.hpp" |
31 |
31 |
32 class ZCompareAndSwapPNode : public CompareAndSwapPNode { |
32 const uint8_t ZLoadBarrierStrong = 1; |
33 public: |
33 const uint8_t ZLoadBarrierWeak = 2; |
34 ZCompareAndSwapPNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : CompareAndSwapPNode(c, mem, adr, val, ex, mem_ord) { } |
34 const uint8_t ZLoadBarrierElided = 3; |
35 virtual int Opcode() const; |
|
36 }; |
|
37 |
35 |
38 class ZWeakCompareAndSwapPNode : public WeakCompareAndSwapPNode { |
36 class ZLoadBarrierStubC2 : public ResourceObj { |
39 public: |
37 private: |
40 ZWeakCompareAndSwapPNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, MemNode::MemOrd mem_ord) : WeakCompareAndSwapPNode(c, mem, adr, val, ex, mem_ord) { } |
38 const MachNode* _node; |
41 virtual int Opcode() const; |
39 const Address _ref_addr; |
42 }; |
40 const Register _ref; |
|
41 const Register _tmp; |
|
42 const bool _weak; |
|
43 Label _entry; |
|
44 Label _continuation; |
43 |
45 |
44 class ZCompareAndExchangePNode : public CompareAndExchangePNode { |
46 ZLoadBarrierStubC2(const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak); |
45 public: |
|
46 ZCompareAndExchangePNode(Node* c, Node *mem, Node *adr, Node *val, Node *ex, const TypePtr* at, const Type* t, MemNode::MemOrd mem_ord) : CompareAndExchangePNode(c, mem, adr, val, ex, at, t, mem_ord) { } |
|
47 virtual int Opcode() const; |
|
48 }; |
|
49 |
|
50 class ZGetAndSetPNode : public GetAndSetPNode { |
|
51 public: |
|
52 ZGetAndSetPNode(Node* c, Node *mem, Node *adr, Node *val, const TypePtr* at, const Type* t) : GetAndSetPNode(c, mem, adr, val, at, t) { } |
|
53 virtual int Opcode() const; |
|
54 }; |
|
55 |
|
56 class LoadBarrierNode : public MultiNode { |
|
57 private: |
|
58 bool _weak; // On strong or weak oop reference |
|
59 static bool is_dominator(PhaseIdealLoop* phase, bool linear_only, Node *d, Node *n); |
|
60 void push_dominated_barriers(PhaseIterGVN* igvn) const; |
|
61 |
47 |
62 public: |
48 public: |
63 enum { |
49 static ZLoadBarrierStubC2* create(const MachNode* node, Address ref_addr, Register ref, Register tmp, bool weak); |
64 Control, |
|
65 Memory, |
|
66 Oop, |
|
67 Address, |
|
68 Number_of_Outputs = Address, |
|
69 Similar, |
|
70 Number_of_Inputs |
|
71 }; |
|
72 |
50 |
73 LoadBarrierNode(Compile* C, |
51 Address ref_addr() const; |
74 Node* c, |
52 Register ref() const; |
75 Node* mem, |
53 Register tmp() const; |
76 Node* val, |
54 address slow_path() const; |
77 Node* adr, |
55 RegMask& live() const; |
78 bool weak); |
56 Label* entry(); |
79 |
57 Label* continuation(); |
80 virtual int Opcode() const; |
|
81 virtual uint size_of() const; |
|
82 virtual bool cmp(const Node& n) const; |
|
83 virtual const Type *bottom_type() const; |
|
84 virtual const TypePtr* adr_type() const; |
|
85 virtual const Type *Value(PhaseGVN *phase) const; |
|
86 virtual Node *Identity(PhaseGVN *phase); |
|
87 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
|
88 virtual uint match_edge(uint idx) const; |
|
89 |
|
90 LoadBarrierNode* has_dominating_barrier(PhaseIdealLoop* phase, |
|
91 bool linear_only, |
|
92 bool look_for_similar); |
|
93 |
|
94 void fix_similar_in_uses(PhaseIterGVN* igvn); |
|
95 |
|
96 bool has_true_uses() const; |
|
97 |
|
98 bool can_be_eliminated() const { |
|
99 return !in(Similar)->is_top(); |
|
100 } |
|
101 |
|
102 bool is_weak() const { |
|
103 return _weak; |
|
104 } |
|
105 }; |
|
106 |
|
107 class LoadBarrierSlowRegNode : public TypeNode { |
|
108 private: |
|
109 bool _is_weak; |
|
110 public: |
|
111 LoadBarrierSlowRegNode(Node *c, |
|
112 Node *adr, |
|
113 Node *src, |
|
114 const TypePtr* t, |
|
115 bool weak) : |
|
116 TypeNode(t, 3), _is_weak(weak) { |
|
117 init_req(1, adr); |
|
118 init_req(2, src); |
|
119 init_class_id(Class_LoadBarrierSlowReg); |
|
120 } |
|
121 |
|
122 virtual uint size_of() const { |
|
123 return sizeof(*this); |
|
124 } |
|
125 |
|
126 virtual const char * name() { |
|
127 return "LoadBarrierSlowRegNode"; |
|
128 } |
|
129 |
|
130 virtual Node *Ideal(PhaseGVN *phase, bool can_reshape) { |
|
131 return NULL; |
|
132 } |
|
133 |
|
134 virtual int Opcode() const; |
|
135 |
|
136 bool is_weak() { return _is_weak; } |
|
137 }; |
|
138 |
|
139 class ZBarrierSetC2State : public ResourceObj { |
|
140 private: |
|
141 // List of load barrier nodes which need to be expanded before matching |
|
142 GrowableArray<LoadBarrierNode*>* _load_barrier_nodes; |
|
143 |
|
144 public: |
|
145 ZBarrierSetC2State(Arena* comp_arena); |
|
146 int load_barrier_count() const; |
|
147 void add_load_barrier_node(LoadBarrierNode* n); |
|
148 void remove_load_barrier_node(LoadBarrierNode* n); |
|
149 LoadBarrierNode* load_barrier_node(int idx) const; |
|
150 }; |
58 }; |
151 |
59 |
152 class ZBarrierSetC2 : public BarrierSetC2 { |
60 class ZBarrierSetC2 : public BarrierSetC2 { |
153 private: |
61 private: |
154 ZBarrierSetC2State* state() const; |
62 void compute_liveness_at_stubs() const; |
155 void expand_loadbarrier_node(PhaseMacroExpand* phase, LoadBarrierNode* barrier) const; |
63 void analyze_dominating_barriers() const; |
156 |
|
157 #ifdef ASSERT |
|
158 void verify_gc_barriers(bool post_parse) const; |
|
159 #endif |
|
160 |
64 |
161 protected: |
65 protected: |
162 virtual Node* load_at_resolved(C2Access& access, const Type* val_type) const; |
66 virtual Node* load_at_resolved(C2Access& access, const Type* val_type) const; |
163 virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, |
67 virtual Node* atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, |
164 Node* expected_val, |
68 Node* expected_val, |
172 Node* new_val, |
76 Node* new_val, |
173 const Type* val_type) const; |
77 const Type* val_type) const; |
174 |
78 |
175 public: |
79 public: |
176 virtual void* create_barrier_state(Arena* comp_arena) const; |
80 virtual void* create_barrier_state(Arena* comp_arena) const; |
|
81 virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, |
|
82 BasicType type, |
|
83 bool is_clone, |
|
84 ArrayCopyPhase phase) const; |
177 |
85 |
178 virtual bool has_load_barriers() const { return true; } |
86 virtual void late_barrier_analysis() const; |
179 virtual bool is_gc_barrier_node(Node* node) const; |
87 virtual int estimate_stub_size() const; |
180 virtual Node* step_over_gc_barrier(Node* c) const; |
88 virtual void emit_stubs(CodeBuffer& cb) const; |
181 virtual Node* step_over_gc_barrier_ctrl(Node* c) const; |
|
182 |
|
183 virtual void register_potential_barrier_node(Node* node) const; |
|
184 virtual void unregister_potential_barrier_node(Node* node) const; |
|
185 virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const { } |
|
186 virtual void enqueue_useful_gc_barrier(PhaseIterGVN* igvn, Node* node) const; |
|
187 virtual void eliminate_useless_gc_barriers(Unique_Node_List &useful, Compile* C) const; |
|
188 |
|
189 virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const; |
|
190 |
|
191 virtual bool expand_barriers(Compile* C, PhaseIterGVN& igvn) const; |
|
192 virtual bool final_graph_reshaping(Compile* compile, Node* n, uint opcode) const; |
|
193 virtual bool matcher_find_shared_visit(Matcher* matcher, Matcher::MStack& mstack, Node* n, uint opcode, bool& mem_op, int& mem_addr_idx) const; |
|
194 virtual bool matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const; |
|
195 virtual bool needs_anti_dependence_check(const Node* node) const; |
|
196 |
|
197 #ifdef ASSERT |
|
198 virtual void verify_gc_barriers(Compile* compile, CompilePhase phase) const; |
|
199 #endif |
|
200 |
|
201 // Load barrier insertion and expansion external |
|
202 virtual void barrier_insertion_phase(Compile* C, PhaseIterGVN &igvn) const; |
|
203 virtual bool optimize_loops(PhaseIdealLoop* phase, LoopOptsMode mode, VectorSet& visited, Node_Stack& nstack, Node_List& worklist) const; |
|
204 virtual bool is_gc_specific_loop_opts_pass(LoopOptsMode mode) const { return (mode == LoopOptsZBarrierInsertion); } |
|
205 virtual bool strip_mined_loops_expanded(LoopOptsMode mode) const { return mode == LoopOptsZBarrierInsertion; } |
|
206 |
|
207 private: |
|
208 // Load barrier insertion and expansion internal |
|
209 void insert_barriers_on_unsafe(PhaseIdealLoop* phase) const; |
|
210 void clean_catch_blocks(PhaseIdealLoop* phase, bool verify = false) const; |
|
211 void insert_load_barriers(PhaseIdealLoop* phase) const; |
|
212 LoadNode* insert_one_loadbarrier(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl) const; |
|
213 void insert_one_loadbarrier_inner(PhaseIdealLoop* phase, LoadNode* load, Node* ctrl, VectorSet visited) const; |
|
214 }; |
89 }; |
215 |
90 |
216 #endif // SHARE_GC_Z_C2_ZBARRIERSETC2_HPP |
91 #endif // SHARE_GC_Z_C2_ZBARRIERSETC2_HPP |