File: | jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp |
Warning: | line 349, column 11 Value stored to 'mark_inputs' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | * Copyright (c) 2015, 2021, Red Hat, Inc. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #include "precompiled.hpp" |
26 | |
27 | #include "classfile/javaClasses.hpp" |
28 | #include "gc/shenandoah/c2/shenandoahSupport.hpp" |
29 | #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" |
30 | #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" |
31 | #include "gc/shenandoah/shenandoahForwarding.hpp" |
32 | #include "gc/shenandoah/shenandoahHeap.hpp" |
33 | #include "gc/shenandoah/shenandoahHeapRegion.hpp" |
34 | #include "gc/shenandoah/shenandoahRuntime.hpp" |
35 | #include "gc/shenandoah/shenandoahThreadLocalData.hpp" |
36 | #include "opto/arraycopynode.hpp" |
37 | #include "opto/block.hpp" |
38 | #include "opto/callnode.hpp" |
39 | #include "opto/castnode.hpp" |
40 | #include "opto/movenode.hpp" |
41 | #include "opto/phaseX.hpp" |
42 | #include "opto/rootnode.hpp" |
43 | #include "opto/runtime.hpp" |
44 | #include "opto/subnode.hpp" |
45 | |
46 | bool ShenandoahBarrierC2Support::expand(Compile* C, PhaseIterGVN& igvn) { |
47 | ShenandoahBarrierSetC2State* state = ShenandoahBarrierSetC2::bsc2()->state(); |
48 | if ((state->iu_barriers_count() + |
49 | state->load_reference_barriers_count()) > 0) { |
50 | assert(C->post_loop_opts_phase(), "no loop opts allowed")do { if (!(C->post_loop_opts_phase())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 50, "assert(" "C->post_loop_opts_phase()" ") failed", "no loop opts allowed" ); ::breakpoint(); } } while (0); |
51 | C->reset_post_loop_opts_phase(); // ... but we know what we are doing |
52 | bool attempt_more_loopopts = ShenandoahLoopOptsAfterExpansion; |
53 | C->clear_major_progress(); |
54 | PhaseIdealLoop::optimize(igvn, LoopOptsShenandoahExpand); |
55 | if (C->failing()) return false; |
56 | PhaseIdealLoop::verify(igvn); |
57 | if (attempt_more_loopopts) { |
58 | C->set_major_progress(); |
59 | if (!C->optimize_loops(igvn, LoopOptsShenandoahPostExpand)) { |
60 | return false; |
61 | } |
62 | C->clear_major_progress(); |
63 | |
64 | C->process_for_post_loop_opts_igvn(igvn); |
65 | } |
66 | C->set_post_loop_opts_phase(); // now for real! |
67 | } |
68 | return true; |
69 | } |
70 | |
71 | bool ShenandoahBarrierC2Support::is_gc_state_test(Node* iff, int mask) { |
72 | if (!UseShenandoahGC) { |
73 | return false; |
74 | } |
75 | assert(iff->is_If(), "bad input")do { if (!(iff->is_If())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 75, "assert(" "iff->is_If()" ") failed", "bad input"); :: breakpoint(); } } while (0); |
76 | if (iff->Opcode() != Op_If) { |
77 | return false; |
78 | } |
79 | Node* bol = iff->in(1); |
80 | if (!bol->is_Bool() || bol->as_Bool()->_test._test != BoolTest::ne) { |
81 | return false; |
82 | } |
83 | Node* cmp = bol->in(1); |
84 | if (cmp->Opcode() != Op_CmpI) { |
85 | return false; |
86 | } |
87 | Node* in1 = cmp->in(1); |
88 | Node* in2 = cmp->in(2); |
89 | if (in2->find_int_con(-1) != 0) { |
90 | return false; |
91 | } |
92 | if (in1->Opcode() != Op_AndI) { |
93 | return false; |
94 | } |
95 | in2 = in1->in(2); |
96 | if (in2->find_int_con(-1) != mask) { |
97 | return false; |
98 | } |
99 | in1 = in1->in(1); |
100 | |
101 | return is_gc_state_load(in1); |
102 | } |
103 | |
104 | bool ShenandoahBarrierC2Support::is_heap_stable_test(Node* iff) { |
105 | return is_gc_state_test(iff, ShenandoahHeap::HAS_FORWARDED); |
106 | } |
107 | |
108 | bool ShenandoahBarrierC2Support::is_gc_state_load(Node *n) { |
109 | if (!UseShenandoahGC) { |
110 | return false; |
111 | } |
112 | if (n->Opcode() != Op_LoadB && n->Opcode() != Op_LoadUB) { |
113 | return false; |
114 | } |
115 | Node* addp = n->in(MemNode::Address); |
116 | if (!addp->is_AddP()) { |
117 | return false; |
118 | } |
119 | Node* base = addp->in(AddPNode::Address); |
120 | Node* off = addp->in(AddPNode::Offset); |
121 | if (base->Opcode() != Op_ThreadLocal) { |
122 | return false; |
123 | } |
124 | if (off->find_intptr_t_confind_long_con(-1) != in_bytes(ShenandoahThreadLocalData::gc_state_offset())) { |
125 | return false; |
126 | } |
127 | return true; |
128 | } |
129 | |
130 | bool ShenandoahBarrierC2Support::has_safepoint_between(Node* start, Node* stop, PhaseIdealLoop *phase) { |
131 | assert(phase->is_dominator(stop, start), "bad inputs")do { if (!(phase->is_dominator(stop, start))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 131, "assert(" "phase->is_dominator(stop, start)" ") failed" , "bad inputs"); ::breakpoint(); } } while (0); |
132 | ResourceMark rm; |
133 | Unique_Node_List wq; |
134 | wq.push(start); |
135 | for (uint next = 0; next < wq.size(); next++) { |
136 | Node *m = wq.at(next); |
137 | if (m == stop) { |
138 | continue; |
139 | } |
140 | if (m->is_SafePoint() && !m->is_CallLeaf()) { |
141 | return true; |
142 | } |
143 | if (m->is_Region()) { |
144 | for (uint i = 1; i < m->req(); i++) { |
145 | wq.push(m->in(i)); |
146 | } |
147 | } else { |
148 | wq.push(m->in(0)); |
149 | } |
150 | } |
151 | return false; |
152 | } |
153 | |
154 | #ifdef ASSERT1 |
155 | bool ShenandoahBarrierC2Support::verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used) { |
156 | assert(phis.size() == 0, "")do { if (!(phis.size() == 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 156, "assert(" "phis.size() == 0" ") failed", ""); ::breakpoint (); } } while (0); |
157 | |
158 | while (true) { |
159 | if (in->bottom_type() == TypePtr::NULL_PTR) { |
160 | if (trace) {tty->print_cr("NULL");} |
161 | } else if (!in->bottom_type()->make_ptr()->make_oopptr()) { |
162 | if (trace) {tty->print_cr("Non oop");} |
163 | } else { |
164 | if (in->is_ConstraintCast()) { |
165 | in = in->in(1); |
166 | continue; |
167 | } else if (in->is_AddP()) { |
168 | assert(!in->in(AddPNode::Address)->is_top(), "no raw memory access")do { if (!(!in->in(AddPNode::Address)->is_top())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 168, "assert(" "!in->in(AddPNode::Address)->is_top()" ") failed", "no raw memory access"); ::breakpoint(); } } while (0); |
169 | in = in->in(AddPNode::Address); |
170 | continue; |
171 | } else if (in->is_Con()) { |
172 | if (trace) { |
173 | tty->print("Found constant"); |
174 | in->dump(); |
175 | } |
176 | } else if (in->Opcode() == Op_Parm) { |
177 | if (trace) { |
178 | tty->print("Found argument"); |
179 | } |
180 | } else if (in->Opcode() == Op_CreateEx) { |
181 | if (trace) { |
182 | tty->print("Found create-exception"); |
183 | } |
184 | } else if (in->Opcode() == Op_LoadP && in->adr_type() == TypeRawPtr::BOTTOM) { |
185 | if (trace) { |
186 | tty->print("Found raw LoadP (OSR argument?)"); |
187 | } |
188 | } else if (in->Opcode() == Op_ShenandoahLoadReferenceBarrier) { |
189 | if (t == ShenandoahOopStore) { |
190 | uint i = 0; |
191 | for (; i < phis.size(); i++) { |
192 | Node* n = phis.node_at(i); |
193 | if (n->Opcode() == Op_ShenandoahIUBarrier) { |
194 | break; |
195 | } |
196 | } |
197 | if (i == phis.size()) { |
198 | return false; |
199 | } |
200 | } |
201 | barriers_used.push(in); |
202 | if (trace) {tty->print("Found barrier"); in->dump();} |
203 | } else if (in->Opcode() == Op_ShenandoahIUBarrier) { |
204 | if (t != ShenandoahOopStore) { |
205 | in = in->in(1); |
206 | continue; |
207 | } |
208 | if (trace) {tty->print("Found enqueue barrier"); in->dump();} |
209 | phis.push(in, in->req()); |
210 | in = in->in(1); |
211 | continue; |
212 | } else if (in->is_Proj() && in->in(0)->is_Allocate()) { |
213 | if (trace) { |
214 | tty->print("Found alloc"); |
215 | in->in(0)->dump(); |
216 | } |
217 | } else if (in->is_Proj() && (in->in(0)->Opcode() == Op_CallStaticJava || in->in(0)->Opcode() == Op_CallDynamicJava)) { |
218 | if (trace) { |
219 | tty->print("Found Java call"); |
220 | } |
221 | } else if (in->is_Phi()) { |
222 | if (!visited.test_set(in->_idx)) { |
223 | if (trace) {tty->print("Pushed phi:"); in->dump();} |
224 | phis.push(in, 2); |
225 | in = in->in(1); |
226 | continue; |
227 | } |
228 | if (trace) {tty->print("Already seen phi:"); in->dump();} |
229 | } else if (in->Opcode() == Op_CMoveP || in->Opcode() == Op_CMoveN) { |
230 | if (!visited.test_set(in->_idx)) { |
231 | if (trace) {tty->print("Pushed cmovep:"); in->dump();} |
232 | phis.push(in, CMoveNode::IfTrue); |
233 | in = in->in(CMoveNode::IfFalse); |
234 | continue; |
235 | } |
236 | if (trace) {tty->print("Already seen cmovep:"); in->dump();} |
237 | } else if (in->Opcode() == Op_EncodeP || in->Opcode() == Op_DecodeN) { |
238 | in = in->in(1); |
239 | continue; |
240 | } else { |
241 | return false; |
242 | } |
243 | } |
244 | bool cont = false; |
245 | while (phis.is_nonempty()) { |
246 | uint idx = phis.index(); |
247 | Node* phi = phis.node(); |
248 | if (idx >= phi->req()) { |
249 | if (trace) {tty->print("Popped phi:"); phi->dump();} |
250 | phis.pop(); |
251 | continue; |
252 | } |
253 | if (trace) {tty->print("Next entry(%d) for phi:", idx); phi->dump();} |
254 | in = phi->in(idx); |
255 | phis.set_index(idx+1); |
256 | cont = true; |
257 | break; |
258 | } |
259 | if (!cont) { |
260 | break; |
261 | } |
262 | } |
263 | return true; |
264 | } |
265 | |
266 | void ShenandoahBarrierC2Support::report_verify_failure(const char* msg, Node* n1, Node* n2) { |
267 | if (n1 != NULL__null) { |
268 | n1->dump(+10); |
269 | } |
270 | if (n2 != NULL__null) { |
271 | n2->dump(+10); |
272 | } |
273 | fatal("%s", msg)do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 273, "%s", msg); ::breakpoint(); } while (0); |
274 | } |
275 | |
276 | void ShenandoahBarrierC2Support::verify(RootNode* root) { |
277 | ResourceMark rm; |
278 | Unique_Node_List wq; |
279 | GrowableArray<Node*> barriers; |
280 | Unique_Node_List barriers_used; |
281 | Node_Stack phis(0); |
282 | VectorSet visited; |
283 | const bool trace = false; |
284 | const bool verify_no_useless_barrier = false; |
285 | |
286 | wq.push(root); |
287 | for (uint next = 0; next < wq.size(); next++) { |
288 | Node *n = wq.at(next); |
289 | if (n->is_Load()) { |
290 | const bool trace = false; |
291 | if (trace) {tty->print("Verifying"); n->dump();} |
292 | if (n->Opcode() == Op_LoadRange || n->Opcode() == Op_LoadKlass || n->Opcode() == Op_LoadNKlass) { |
293 | if (trace) {tty->print_cr("Load range/klass");} |
294 | } else { |
295 | const TypePtr* adr_type = n->as_Load()->adr_type(); |
296 | |
297 | if (adr_type->isa_oopptr() && adr_type->is_oopptr()->offset() == oopDesc::mark_offset_in_bytes()) { |
298 | if (trace) {tty->print_cr("Mark load");} |
299 | } else if (adr_type->isa_instptr() && |
300 | adr_type->is_instptr()->klass()->is_subtype_of(Compile::current()->env()->Reference_klass()) && |
301 | adr_type->is_instptr()->offset() == java_lang_ref_Reference::referent_offset()) { |
302 | if (trace) {tty->print_cr("Reference.get()");} |
303 | } else if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) { |
304 | report_verify_failure("Shenandoah verification: Load should have barriers", n); |
305 | } |
306 | } |
307 | } else if (n->is_Store()) { |
308 | const bool trace = false; |
309 | |
310 | if (trace) {tty->print("Verifying"); n->dump();} |
311 | if (n->in(MemNode::ValueIn)->bottom_type()->make_oopptr()) { |
312 | Node* adr = n->in(MemNode::Address); |
313 | bool verify = true; |
314 | |
315 | if (adr->is_AddP() && adr->in(AddPNode::Base)->is_top()) { |
316 | adr = adr->in(AddPNode::Address); |
317 | if (adr->is_AddP()) { |
318 | assert(adr->in(AddPNode::Base)->is_top(), "")do { if (!(adr->in(AddPNode::Base)->is_top())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 318, "assert(" "adr->in(AddPNode::Base)->is_top()" ") failed" , ""); ::breakpoint(); } } while (0); |
319 | adr = adr->in(AddPNode::Address); |
320 | if (adr->Opcode() == Op_LoadP && |
321 | adr->in(MemNode::Address)->in(AddPNode::Base)->is_top() && |
322 | adr->in(MemNode::Address)->in(AddPNode::Address)->Opcode() == Op_ThreadLocal && |
323 | adr->in(MemNode::Address)->in(AddPNode::Offset)->find_intptr_t_confind_long_con(-1) == in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())) { |
324 | if (trace) {tty->print_cr("SATB prebarrier");} |
325 | verify = false; |
326 | } |
327 | } |
328 | } |
329 | |
330 | if (verify && !verify_helper(n->in(MemNode::ValueIn), phis, visited, ShenandoahIUBarrier ? ShenandoahOopStore : ShenandoahValue, trace, barriers_used)) { |
331 | report_verify_failure("Shenandoah verification: Store should have barriers", n); |
332 | } |
333 | } |
334 | if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahStore, trace, barriers_used)) { |
335 | report_verify_failure("Shenandoah verification: Store (address) should have barriers", n); |
336 | } |
337 | } else if (n->Opcode() == Op_CmpP) { |
338 | const bool trace = false; |
339 | |
340 | Node* in1 = n->in(1); |
341 | Node* in2 = n->in(2); |
342 | if (in1->bottom_type()->isa_oopptr()) { |
343 | if (trace) {tty->print("Verifying"); n->dump();} |
344 | |
345 | bool mark_inputs = false; |
346 | if (in1->bottom_type() == TypePtr::NULL_PTR || in2->bottom_type() == TypePtr::NULL_PTR || |
347 | (in1->is_Con() || in2->is_Con())) { |
348 | if (trace) {tty->print_cr("Comparison against a constant");} |
349 | mark_inputs = true; |
Value stored to 'mark_inputs' is never read | |
350 | } else if ((in1->is_CheckCastPP() && in1->in(1)->is_Proj() && in1->in(1)->in(0)->is_Allocate()) || |
351 | (in2->is_CheckCastPP() && in2->in(1)->is_Proj() && in2->in(1)->in(0)->is_Allocate())) { |
352 | if (trace) {tty->print_cr("Comparison with newly alloc'ed object");} |
353 | mark_inputs = true; |
354 | } else { |
355 | assert(in2->bottom_type()->isa_oopptr(), "")do { if (!(in2->bottom_type()->isa_oopptr())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 355, "assert(" "in2->bottom_type()->isa_oopptr()" ") failed" , ""); ::breakpoint(); } } while (0); |
356 | |
357 | if (!verify_helper(in1, phis, visited, ShenandoahStore, trace, barriers_used) || |
358 | !verify_helper(in2, phis, visited, ShenandoahStore, trace, barriers_used)) { |
359 | report_verify_failure("Shenandoah verification: Cmp should have barriers", n); |
360 | } |
361 | } |
362 | if (verify_no_useless_barrier && |
363 | mark_inputs && |
364 | (!verify_helper(in1, phis, visited, ShenandoahValue, trace, barriers_used) || |
365 | !verify_helper(in2, phis, visited, ShenandoahValue, trace, barriers_used))) { |
366 | phis.clear(); |
367 | visited.reset(); |
368 | } |
369 | } |
370 | } else if (n->is_LoadStore()) { |
371 | if (n->in(MemNode::ValueIn)->bottom_type()->make_ptr() && |
372 | !verify_helper(n->in(MemNode::ValueIn), phis, visited, ShenandoahIUBarrier ? ShenandoahOopStore : ShenandoahValue, trace, barriers_used)) { |
373 | report_verify_failure("Shenandoah verification: LoadStore (value) should have barriers", n); |
374 | } |
375 | |
376 | if (n->in(MemNode::Address)->bottom_type()->make_oopptr() && !verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahStore, trace, barriers_used)) { |
377 | report_verify_failure("Shenandoah verification: LoadStore (address) should have barriers", n); |
378 | } |
379 | } else if (n->Opcode() == Op_CallLeafNoFP || n->Opcode() == Op_CallLeaf) { |
380 | CallNode* call = n->as_Call(); |
381 | |
382 | static struct { |
383 | const char* name; |
384 | struct { |
385 | int pos; |
386 | verify_type t; |
387 | } args[6]; |
388 | } calls[] = { |
389 | "aescrypt_encryptBlock", |
390 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad }, |
391 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
392 | "aescrypt_decryptBlock", |
393 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad }, |
394 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
395 | "multiplyToLen", |
396 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+2, ShenandoahLoad }, { TypeFunc::Parms+4, ShenandoahStore }, |
397 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
398 | "squareToLen", |
399 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+2, ShenandoahLoad }, { -1, ShenandoahNone}, |
400 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
401 | "montgomery_multiply", |
402 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahLoad }, { TypeFunc::Parms+2, ShenandoahLoad }, |
403 | { TypeFunc::Parms+6, ShenandoahStore }, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
404 | "montgomery_square", |
405 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahLoad }, { TypeFunc::Parms+5, ShenandoahStore }, |
406 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
407 | "mulAdd", |
408 | { { TypeFunc::Parms, ShenandoahStore }, { TypeFunc::Parms+1, ShenandoahLoad }, { -1, ShenandoahNone}, |
409 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
410 | "vectorizedMismatch", |
411 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahLoad }, { -1, ShenandoahNone}, |
412 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
413 | "updateBytesCRC32", |
414 | { { TypeFunc::Parms+1, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone}, |
415 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
416 | "updateBytesAdler32", |
417 | { { TypeFunc::Parms+1, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone}, |
418 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
419 | "updateBytesCRC32C", |
420 | { { TypeFunc::Parms+1, ShenandoahLoad }, { TypeFunc::Parms+3, ShenandoahLoad}, { -1, ShenandoahNone}, |
421 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
422 | "counterMode_AESCrypt", |
423 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad }, |
424 | { TypeFunc::Parms+3, ShenandoahStore }, { TypeFunc::Parms+5, ShenandoahStore }, { TypeFunc::Parms+6, ShenandoahStore } }, |
425 | "cipherBlockChaining_encryptAESCrypt", |
426 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad }, |
427 | { TypeFunc::Parms+3, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
428 | "cipherBlockChaining_decryptAESCrypt", |
429 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad }, |
430 | { TypeFunc::Parms+3, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
431 | "shenandoah_clone_barrier", |
432 | { { TypeFunc::Parms, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone}, |
433 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
434 | "ghash_processBlocks", |
435 | { { TypeFunc::Parms, ShenandoahStore }, { TypeFunc::Parms+1, ShenandoahLoad }, { TypeFunc::Parms+2, ShenandoahLoad }, |
436 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
437 | "sha1_implCompress", |
438 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone }, |
439 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
440 | "sha256_implCompress", |
441 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone }, |
442 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
443 | "sha512_implCompress", |
444 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone }, |
445 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
446 | "sha1_implCompressMB", |
447 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone }, |
448 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
449 | "sha256_implCompressMB", |
450 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone }, |
451 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
452 | "sha512_implCompressMB", |
453 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone }, |
454 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
455 | "encodeBlock", |
456 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+3, ShenandoahStore }, { -1, ShenandoahNone }, |
457 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
458 | "decodeBlock", |
459 | { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+3, ShenandoahStore }, { -1, ShenandoahNone }, |
460 | { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, |
461 | }; |
462 | |
463 | if (call->is_call_to_arraycopystub()) { |
464 | Node* dest = NULL__null; |
465 | const TypeTuple* args = n->as_Call()->_tf->domain(); |
466 | for (uint i = TypeFunc::Parms, j = 0; i < args->cnt(); i++) { |
467 | if (args->field_at(i)->isa_ptr()) { |
468 | j++; |
469 | if (j == 2) { |
470 | dest = n->in(i); |
471 | break; |
472 | } |
473 | } |
474 | } |
475 | if (!verify_helper(n->in(TypeFunc::Parms), phis, visited, ShenandoahLoad, trace, barriers_used) || |
476 | !verify_helper(dest, phis, visited, ShenandoahStore, trace, barriers_used)) { |
477 | report_verify_failure("Shenandoah verification: ArrayCopy should have barriers", n); |
478 | } |
479 | } else if (strlen(call->_name) > 5 && |
480 | !strcmp(call->_name + strlen(call->_name) - 5, "_fill")) { |
481 | if (!verify_helper(n->in(TypeFunc::Parms), phis, visited, ShenandoahStore, trace, barriers_used)) { |
482 | report_verify_failure("Shenandoah verification: _fill should have barriers", n); |
483 | } |
484 | } else if (!strcmp(call->_name, "shenandoah_wb_pre")) { |
485 | // skip |
486 | } else { |
487 | const int calls_len = sizeof(calls) / sizeof(calls[0]); |
488 | int i = 0; |
489 | for (; i < calls_len; i++) { |
490 | if (!strcmp(calls[i].name, call->_name)) { |
491 | break; |
492 | } |
493 | } |
494 | if (i != calls_len) { |
495 | const uint args_len = sizeof(calls[0].args) / sizeof(calls[0].args[0]); |
496 | for (uint j = 0; j < args_len; j++) { |
497 | int pos = calls[i].args[j].pos; |
498 | if (pos == -1) { |
499 | break; |
500 | } |
501 | if (!verify_helper(call->in(pos), phis, visited, calls[i].args[j].t, trace, barriers_used)) { |
502 | report_verify_failure("Shenandoah verification: intrinsic calls should have barriers", n); |
503 | } |
504 | } |
505 | for (uint j = TypeFunc::Parms; j < call->req(); j++) { |
506 | if (call->in(j)->bottom_type()->make_ptr() && |
507 | call->in(j)->bottom_type()->make_ptr()->isa_oopptr()) { |
508 | uint k = 0; |
509 | for (; k < args_len && calls[i].args[k].pos != (int)j; k++); |
510 | if (k == args_len) { |
511 | fatal("arg %d for call %s not covered", j, call->_name)do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 511, "arg %d for call %s not covered", j, call->_name); :: breakpoint(); } while (0); |
512 | } |
513 | } |
514 | } |
515 | } else { |
516 | for (uint j = TypeFunc::Parms; j < call->req(); j++) { |
517 | if (call->in(j)->bottom_type()->make_ptr() && |
518 | call->in(j)->bottom_type()->make_ptr()->isa_oopptr()) { |
519 | fatal("%s not covered", call->_name)do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 519, "%s not covered", call->_name); ::breakpoint(); } while (0); |
520 | } |
521 | } |
522 | } |
523 | } |
524 | } else if (n->Opcode() == Op_ShenandoahIUBarrier || n->Opcode() == Op_ShenandoahLoadReferenceBarrier) { |
525 | // skip |
526 | } else if (n->is_AddP() |
527 | || n->is_Phi() |
528 | || n->is_ConstraintCast() |
529 | || n->Opcode() == Op_Return |
530 | || n->Opcode() == Op_CMoveP |
531 | || n->Opcode() == Op_CMoveN |
532 | || n->Opcode() == Op_Rethrow |
533 | || n->is_MemBar() |
534 | || n->Opcode() == Op_Conv2B |
535 | || n->Opcode() == Op_SafePoint |
536 | || n->is_CallJava() |
537 | || n->Opcode() == Op_Unlock |
538 | || n->Opcode() == Op_EncodeP |
539 | || n->Opcode() == Op_DecodeN) { |
540 | // nothing to do |
541 | } else { |
542 | static struct { |
543 | int opcode; |
544 | struct { |
545 | int pos; |
546 | verify_type t; |
547 | } inputs[2]; |
548 | } others[] = { |
549 | Op_FastLock, |
550 | { { 1, ShenandoahLoad }, { -1, ShenandoahNone} }, |
551 | Op_Lock, |
552 | { { TypeFunc::Parms, ShenandoahLoad }, { -1, ShenandoahNone} }, |
553 | Op_ArrayCopy, |
554 | { { ArrayCopyNode::Src, ShenandoahLoad }, { ArrayCopyNode::Dest, ShenandoahStore } }, |
555 | Op_StrCompressedCopy, |
556 | { { 2, ShenandoahLoad }, { 3, ShenandoahStore } }, |
557 | Op_StrInflatedCopy, |
558 | { { 2, ShenandoahLoad }, { 3, ShenandoahStore } }, |
559 | Op_AryEq, |
560 | { { 2, ShenandoahLoad }, { 3, ShenandoahLoad } }, |
561 | Op_StrIndexOf, |
562 | { { 2, ShenandoahLoad }, { 4, ShenandoahLoad } }, |
563 | Op_StrComp, |
564 | { { 2, ShenandoahLoad }, { 4, ShenandoahLoad } }, |
565 | Op_StrEquals, |
566 | { { 2, ShenandoahLoad }, { 3, ShenandoahLoad } }, |
567 | Op_EncodeISOArray, |
568 | { { 2, ShenandoahLoad }, { 3, ShenandoahStore } }, |
569 | Op_HasNegatives, |
570 | { { 2, ShenandoahLoad }, { -1, ShenandoahNone} }, |
571 | Op_CastP2X, |
572 | { { 1, ShenandoahLoad }, { -1, ShenandoahNone} }, |
573 | Op_StrIndexOfChar, |
574 | { { 2, ShenandoahLoad }, { -1, ShenandoahNone } }, |
575 | }; |
576 | |
577 | const int others_len = sizeof(others) / sizeof(others[0]); |
578 | int i = 0; |
579 | for (; i < others_len; i++) { |
580 | if (others[i].opcode == n->Opcode()) { |
581 | break; |
582 | } |
583 | } |
584 | uint stop = n->is_Call() ? n->as_Call()->tf()->domain()->cnt() : n->req(); |
585 | if (i != others_len) { |
586 | const uint inputs_len = sizeof(others[0].inputs) / sizeof(others[0].inputs[0]); |
587 | for (uint j = 0; j < inputs_len; j++) { |
588 | int pos = others[i].inputs[j].pos; |
589 | if (pos == -1) { |
590 | break; |
591 | } |
592 | if (!verify_helper(n->in(pos), phis, visited, others[i].inputs[j].t, trace, barriers_used)) { |
593 | report_verify_failure("Shenandoah verification: intrinsic calls should have barriers", n); |
594 | } |
595 | } |
596 | for (uint j = 1; j < stop; j++) { |
597 | if (n->in(j) != NULL__null && n->in(j)->bottom_type()->make_ptr() && |
598 | n->in(j)->bottom_type()->make_ptr()->make_oopptr()) { |
599 | uint k = 0; |
600 | for (; k < inputs_len && others[i].inputs[k].pos != (int)j; k++); |
601 | if (k == inputs_len) { |
602 | fatal("arg %d for node %s not covered", j, n->Name())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 602, "arg %d for node %s not covered", j, n->Name()); :: breakpoint(); } while (0); |
603 | } |
604 | } |
605 | } |
606 | } else { |
607 | for (uint j = 1; j < stop; j++) { |
608 | if (n->in(j) != NULL__null && n->in(j)->bottom_type()->make_ptr() && |
609 | n->in(j)->bottom_type()->make_ptr()->make_oopptr()) { |
610 | fatal("%s not covered", n->Name())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 610, "%s not covered", n->Name()); ::breakpoint(); } while (0); |
611 | } |
612 | } |
613 | } |
614 | } |
615 | |
616 | if (n->is_SafePoint()) { |
617 | SafePointNode* sfpt = n->as_SafePoint(); |
618 | if (verify_no_useless_barrier && sfpt->jvms() != NULL__null) { |
619 | for (uint i = sfpt->jvms()->scloff(); i < sfpt->jvms()->endoff(); i++) { |
620 | if (!verify_helper(sfpt->in(i), phis, visited, ShenandoahLoad, trace, barriers_used)) { |
621 | phis.clear(); |
622 | visited.reset(); |
623 | } |
624 | } |
625 | } |
626 | } |
627 | } |
628 | |
629 | if (verify_no_useless_barrier) { |
630 | for (int i = 0; i < barriers.length(); i++) { |
631 | Node* n = barriers.at(i); |
632 | if (!barriers_used.member(n)) { |
633 | tty->print("XXX useless barrier"); n->dump(-2); |
634 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 634); ::breakpoint(); } while (0); |
635 | } |
636 | } |
637 | } |
638 | } |
639 | #endif |
640 | |
641 | bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase) { |
642 | // That both nodes have the same control is not sufficient to prove |
643 | // domination, verify that there's no path from d to n |
644 | ResourceMark rm; |
645 | Unique_Node_List wq; |
646 | wq.push(d); |
647 | for (uint next = 0; next < wq.size(); next++) { |
648 | Node *m = wq.at(next); |
649 | if (m == n) { |
650 | return false; |
651 | } |
652 | if (m->is_Phi() && m->in(0)->is_Loop()) { |
653 | assert(phase->ctrl_or_self(m->in(LoopNode::EntryControl)) != c, "following loop entry should lead to new control")do { if (!(phase->ctrl_or_self(m->in(LoopNode::EntryControl )) != c)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 653, "assert(" "phase->ctrl_or_self(m->in(LoopNode::EntryControl)) != c" ") failed", "following loop entry should lead to new control" ); ::breakpoint(); } } while (0); |
654 | } else { |
655 | if (m->is_Store() || m->is_LoadStore()) { |
656 | // Take anti-dependencies into account |
657 | Node* mem = m->in(MemNode::Memory); |
658 | for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { |
659 | Node* u = mem->fast_out(i); |
660 | if (u->is_Load() && phase->C->can_alias(m->adr_type(), phase->C->get_alias_index(u->adr_type())) && |
661 | phase->ctrl_or_self(u) == c) { |
662 | wq.push(u); |
663 | } |
664 | } |
665 | } |
666 | for (uint i = 0; i < m->req(); i++) { |
667 | if (m->in(i) != NULL__null && phase->ctrl_or_self(m->in(i)) == c) { |
668 | wq.push(m->in(i)); |
669 | } |
670 | } |
671 | } |
672 | } |
673 | return true; |
674 | } |
675 | |
676 | bool ShenandoahBarrierC2Support::is_dominator(Node* d_c, Node* n_c, Node* d, Node* n, PhaseIdealLoop* phase) { |
677 | if (d_c != n_c) { |
678 | return phase->is_dominator(d_c, n_c); |
679 | } |
680 | return is_dominator_same_ctrl(d_c, d, n, phase); |
681 | } |
682 | |
683 | Node* next_mem(Node* mem, int alias) { |
684 | Node* res = NULL__null; |
685 | if (mem->is_Proj()) { |
686 | res = mem->in(0); |
687 | } else if (mem->is_SafePoint() || mem->is_MemBar()) { |
688 | res = mem->in(TypeFunc::Memory); |
689 | } else if (mem->is_Phi()) { |
690 | res = mem->in(1); |
691 | } else if (mem->is_MergeMem()) { |
692 | res = mem->as_MergeMem()->memory_at(alias); |
693 | } else if (mem->is_Store() || mem->is_LoadStore() || mem->is_ClearArray()) { |
694 | assert(alias == Compile::AliasIdxRaw, "following raw memory can't lead to a barrier")do { if (!(alias == Compile::AliasIdxRaw)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 694, "assert(" "alias == Compile::AliasIdxRaw" ") failed", "following raw memory can't lead to a barrier" ); ::breakpoint(); } } while (0); |
695 | res = mem->in(MemNode::Memory); |
696 | } else { |
697 | #ifdef ASSERT1 |
698 | mem->dump(); |
699 | #endif |
700 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 700); ::breakpoint(); } while (0); |
701 | } |
702 | return res; |
703 | } |
704 | |
705 | Node* ShenandoahBarrierC2Support::no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase) { |
706 | Node* iffproj = NULL__null; |
707 | while (c != dom) { |
708 | Node* next = phase->idom(c); |
709 | assert(next->unique_ctrl_out() == c || c->is_Proj() || c->is_Region(), "multiple control flow out but no proj or region?")do { if (!(next->unique_ctrl_out() == c || c->is_Proj() || c->is_Region())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 709, "assert(" "next->unique_ctrl_out() == c || c->is_Proj() || c->is_Region()" ") failed", "multiple control flow out but no proj or region?" ); ::breakpoint(); } } while (0); |
710 | if (c->is_Region()) { |
711 | ResourceMark rm; |
712 | Unique_Node_List wq; |
713 | wq.push(c); |
714 | for (uint i = 0; i < wq.size(); i++) { |
715 | Node *n = wq.at(i); |
716 | if (n == next) { |
717 | continue; |
718 | } |
719 | if (n->is_Region()) { |
720 | for (uint j = 1; j < n->req(); j++) { |
721 | wq.push(n->in(j)); |
722 | } |
723 | } else { |
724 | wq.push(n->in(0)); |
725 | } |
726 | } |
727 | for (uint i = 0; i < wq.size(); i++) { |
728 | Node *n = wq.at(i); |
729 | assert(n->is_CFG(), "")do { if (!(n->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 729, "assert(" "n->is_CFG()" ") failed", ""); ::breakpoint (); } } while (0); |
730 | if (n->is_Multi()) { |
731 | for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { |
732 | Node* u = n->fast_out(j); |
733 | if (u->is_CFG()) { |
734 | if (!wq.member(u) && !u->as_Proj()->is_uncommon_trap_proj(Deoptimization::Reason_none)) { |
735 | return NodeSentinel(Node*)-1; |
736 | } |
737 | } |
738 | } |
739 | } |
740 | } |
741 | } else if (c->is_Proj()) { |
742 | if (c->is_IfProj()) { |
743 | if (c->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) != NULL__null) { |
744 | // continue; |
745 | } else { |
746 | if (!allow_one_proj) { |
747 | return NodeSentinel(Node*)-1; |
748 | } |
749 | if (iffproj == NULL__null) { |
750 | iffproj = c; |
751 | } else { |
752 | return NodeSentinel(Node*)-1; |
753 | } |
754 | } |
755 | } else if (c->Opcode() == Op_JumpProj) { |
756 | return NodeSentinel(Node*)-1; // unsupported |
757 | } else if (c->Opcode() == Op_CatchProj) { |
758 | return NodeSentinel(Node*)-1; // unsupported |
759 | } else if (c->Opcode() == Op_CProj && next->Opcode() == Op_NeverBranch) { |
760 | return NodeSentinel(Node*)-1; // unsupported |
761 | } else { |
762 | assert(next->unique_ctrl_out() == c, "unsupported branch pattern")do { if (!(next->unique_ctrl_out() == c)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 762, "assert(" "next->unique_ctrl_out() == c" ") failed" , "unsupported branch pattern"); ::breakpoint(); } } while (0 ); |
763 | } |
764 | } |
765 | c = next; |
766 | } |
767 | return iffproj; |
768 | } |
769 | |
770 | Node* ShenandoahBarrierC2Support::dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase) { |
771 | ResourceMark rm; |
772 | VectorSet wq; |
773 | wq.set(mem->_idx); |
774 | mem_ctrl = phase->ctrl_or_self(mem); |
775 | while (!phase->is_dominator(mem_ctrl, ctrl) || mem_ctrl == ctrl) { |
776 | mem = next_mem(mem, alias); |
777 | if (wq.test_set(mem->_idx)) { |
778 | return NULL__null; |
779 | } |
780 | mem_ctrl = phase->ctrl_or_self(mem); |
781 | } |
782 | if (mem->is_MergeMem()) { |
783 | mem = mem->as_MergeMem()->memory_at(alias); |
784 | mem_ctrl = phase->ctrl_or_self(mem); |
785 | } |
786 | return mem; |
787 | } |
788 | |
789 | Node* ShenandoahBarrierC2Support::find_bottom_mem(Node* ctrl, PhaseIdealLoop* phase) { |
790 | Node* mem = NULL__null; |
791 | Node* c = ctrl; |
792 | do { |
793 | if (c->is_Region()) { |
794 | for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax && mem == NULL__null; i++) { |
795 | Node* u = c->fast_out(i); |
796 | if (u->is_Phi() && u->bottom_type() == Type::MEMORY) { |
797 | if (u->adr_type() == TypePtr::BOTTOM) { |
798 | mem = u; |
799 | } |
800 | } |
801 | } |
802 | } else { |
803 | if (c->is_Call() && c->as_Call()->adr_type() != NULL__null) { |
804 | CallProjections projs; |
805 | c->as_Call()->extract_projections(&projs, true, false); |
806 | if (projs.fallthrough_memproj != NULL__null) { |
807 | if (projs.fallthrough_memproj->adr_type() == TypePtr::BOTTOM) { |
808 | if (projs.catchall_memproj == NULL__null) { |
809 | mem = projs.fallthrough_memproj; |
810 | } else { |
811 | if (phase->is_dominator(projs.fallthrough_catchproj, ctrl)) { |
812 | mem = projs.fallthrough_memproj; |
813 | } else { |
814 | assert(phase->is_dominator(projs.catchall_catchproj, ctrl), "one proj must dominate barrier")do { if (!(phase->is_dominator(projs.catchall_catchproj, ctrl ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 814, "assert(" "phase->is_dominator(projs.catchall_catchproj, ctrl)" ") failed", "one proj must dominate barrier"); ::breakpoint( ); } } while (0); |
815 | mem = projs.catchall_memproj; |
816 | } |
817 | } |
818 | } |
819 | } else { |
820 | Node* proj = c->as_Call()->proj_out(TypeFunc::Memory); |
821 | if (proj != NULL__null && |
822 | proj->adr_type() == TypePtr::BOTTOM) { |
823 | mem = proj; |
824 | } |
825 | } |
826 | } else { |
827 | for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax; i++) { |
828 | Node* u = c->fast_out(i); |
829 | if (u->is_Proj() && |
830 | u->bottom_type() == Type::MEMORY && |
831 | u->adr_type() == TypePtr::BOTTOM) { |
832 | assert(c->is_SafePoint() || c->is_MemBar() || c->is_Start(), "")do { if (!(c->is_SafePoint() || c->is_MemBar() || c-> is_Start())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 832, "assert(" "c->is_SafePoint() || c->is_MemBar() || c->is_Start()" ") failed", ""); ::breakpoint(); } } while (0); |
833 | assert(mem == NULL, "only one proj")do { if (!(mem == __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 833, "assert(" "mem == __null" ") failed", "only one proj") ; ::breakpoint(); } } while (0); |
834 | mem = u; |
835 | } |
836 | } |
837 | assert(!c->is_Call() || c->as_Call()->adr_type() != NULL || mem == NULL, "no mem projection expected")do { if (!(!c->is_Call() || c->as_Call()->adr_type() != __null || mem == __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 837, "assert(" "!c->is_Call() || c->as_Call()->adr_type() != __null || mem == __null" ") failed", "no mem projection expected"); ::breakpoint(); } } while (0); |
838 | } |
839 | } |
840 | c = phase->idom(c); |
841 | } while (mem == NULL__null); |
842 | return mem; |
843 | } |
844 | |
845 | void ShenandoahBarrierC2Support::follow_barrier_uses(Node* n, Node* ctrl, Unique_Node_List& uses, PhaseIdealLoop* phase) { |
846 | for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
847 | Node* u = n->fast_out(i); |
848 | if (!u->is_CFG() && phase->get_ctrl(u) == ctrl && (!u->is_Phi() || !u->in(0)->is_Loop() || u->in(LoopNode::LoopBackControl) != n)) { |
849 | uses.push(u); |
850 | } |
851 | } |
852 | } |
853 | |
854 | static void hide_strip_mined_loop(OuterStripMinedLoopNode* outer, CountedLoopNode* inner, PhaseIdealLoop* phase) { |
855 | OuterStripMinedLoopEndNode* le = inner->outer_loop_end(); |
856 | Node* new_outer = new LoopNode(outer->in(LoopNode::EntryControl), outer->in(LoopNode::LoopBackControl)); |
857 | phase->register_control(new_outer, phase->get_loop(outer), outer->in(LoopNode::EntryControl)); |
858 | Node* new_le = new IfNode(le->in(0), le->in(1), le->_prob, le->_fcnt); |
859 | phase->register_control(new_le, phase->get_loop(le), le->in(0)); |
860 | phase->lazy_replace(outer, new_outer); |
861 | phase->lazy_replace(le, new_le); |
862 | inner->clear_strip_mined(); |
863 | } |
864 | |
865 | void ShenandoahBarrierC2Support::test_gc_state(Node*& ctrl, Node* raw_mem, Node*& test_fail_ctrl, |
866 | PhaseIdealLoop* phase, int flags) { |
867 | PhaseIterGVN& igvn = phase->igvn(); |
868 | Node* old_ctrl = ctrl; |
869 | |
870 | Node* thread = new ThreadLocalNode(); |
871 | Node* gc_state_offset = igvn.MakeConXlongcon(in_bytes(ShenandoahThreadLocalData::gc_state_offset())); |
872 | Node* gc_state_addr = new AddPNode(phase->C->top(), thread, gc_state_offset); |
873 | Node* gc_state = new LoadBNode(old_ctrl, raw_mem, gc_state_addr, |
874 | DEBUG_ONLY(phase->C->get_adr_type(Compile::AliasIdxRaw))phase->C->get_adr_type(Compile::AliasIdxRaw) NOT_DEBUG(NULL), |
875 | TypeInt::BYTE, MemNode::unordered); |
876 | Node* gc_state_and = new AndINode(gc_state, igvn.intcon(flags)); |
877 | Node* gc_state_cmp = new CmpINode(gc_state_and, igvn.zerocon(T_INT)); |
878 | Node* gc_state_bool = new BoolNode(gc_state_cmp, BoolTest::ne); |
879 | |
880 | IfNode* gc_state_iff = new IfNode(old_ctrl, gc_state_bool, PROB_UNLIKELY(0.999)(1.0f - (float)(0.999)), COUNT_UNKNOWN(-1.0f)); |
881 | ctrl = new IfTrueNode(gc_state_iff); |
882 | test_fail_ctrl = new IfFalseNode(gc_state_iff); |
883 | |
884 | IdealLoopTree* loop = phase->get_loop(old_ctrl); |
885 | phase->register_control(gc_state_iff, loop, old_ctrl); |
886 | phase->register_control(ctrl, loop, gc_state_iff); |
887 | phase->register_control(test_fail_ctrl, loop, gc_state_iff); |
888 | |
889 | phase->register_new_node(thread, old_ctrl); |
890 | phase->register_new_node(gc_state_addr, old_ctrl); |
891 | phase->register_new_node(gc_state, old_ctrl); |
892 | phase->register_new_node(gc_state_and, old_ctrl); |
893 | phase->register_new_node(gc_state_cmp, old_ctrl); |
894 | phase->register_new_node(gc_state_bool, old_ctrl); |
895 | |
896 | phase->set_ctrl(gc_state_offset, phase->C->root()); |
897 | |
898 | assert(is_gc_state_test(gc_state_iff, flags), "Should match the shape")do { if (!(is_gc_state_test(gc_state_iff, flags))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 898, "assert(" "is_gc_state_test(gc_state_iff, flags)" ") failed" , "Should match the shape"); ::breakpoint(); } } while (0); |
899 | } |
900 | |
901 | void ShenandoahBarrierC2Support::test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase) { |
902 | Node* old_ctrl = ctrl; |
903 | PhaseIterGVN& igvn = phase->igvn(); |
904 | |
905 | const Type* val_t = igvn.type(val); |
906 | if (val_t->meet(TypePtr::NULL_PTR) == val_t) { |
907 | Node* null_cmp = new CmpPNode(val, igvn.zerocon(T_OBJECT)); |
908 | Node* null_test = new BoolNode(null_cmp, BoolTest::ne); |
909 | |
910 | IfNode* null_iff = new IfNode(old_ctrl, null_test, PROB_LIKELY(0.999)((float) (0.999)), COUNT_UNKNOWN(-1.0f)); |
911 | ctrl = new IfTrueNode(null_iff); |
912 | null_ctrl = new IfFalseNode(null_iff); |
913 | |
914 | IdealLoopTree* loop = phase->get_loop(old_ctrl); |
915 | phase->register_control(null_iff, loop, old_ctrl); |
916 | phase->register_control(ctrl, loop, null_iff); |
917 | phase->register_control(null_ctrl, loop, null_iff); |
918 | |
919 | phase->register_new_node(null_cmp, old_ctrl); |
920 | phase->register_new_node(null_test, old_ctrl); |
921 | } |
922 | } |
923 | |
924 | void ShenandoahBarrierC2Support::test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase) { |
925 | Node* old_ctrl = ctrl; |
926 | PhaseIterGVN& igvn = phase->igvn(); |
927 | |
928 | Node* raw_val = new CastP2XNode(old_ctrl, val); |
929 | Node* cset_idx = new URShiftXNodeURShiftLNode(raw_val, igvn.intcon(ShenandoahHeapRegion::region_size_bytes_shift_jint())); |
930 | |
931 | // Figure out the target cset address with raw pointer math. |
932 | // This avoids matching AddP+LoadB that would emit inefficient code. |
933 | // See JDK-8245465. |
934 | Node* cset_addr_ptr = igvn.makecon(TypeRawPtr::make(ShenandoahHeap::in_cset_fast_test_addr())); |
935 | Node* cset_addr = new CastP2XNode(old_ctrl, cset_addr_ptr); |
936 | Node* cset_load_addr = new AddXNodeAddLNode(cset_addr, cset_idx); |
937 | Node* cset_load_ptr = new CastX2PNode(cset_load_addr); |
938 | |
939 | Node* cset_load = new LoadBNode(old_ctrl, raw_mem, cset_load_ptr, |
940 | DEBUG_ONLY(phase->C->get_adr_type(Compile::AliasIdxRaw))phase->C->get_adr_type(Compile::AliasIdxRaw) NOT_DEBUG(NULL), |
941 | TypeInt::BYTE, MemNode::unordered); |
942 | Node* cset_cmp = new CmpINode(cset_load, igvn.zerocon(T_INT)); |
943 | Node* cset_bool = new BoolNode(cset_cmp, BoolTest::ne); |
944 | |
945 | IfNode* cset_iff = new IfNode(old_ctrl, cset_bool, PROB_UNLIKELY(0.999)(1.0f - (float)(0.999)), COUNT_UNKNOWN(-1.0f)); |
946 | ctrl = new IfTrueNode(cset_iff); |
947 | not_cset_ctrl = new IfFalseNode(cset_iff); |
948 | |
949 | IdealLoopTree *loop = phase->get_loop(old_ctrl); |
950 | phase->register_control(cset_iff, loop, old_ctrl); |
951 | phase->register_control(ctrl, loop, cset_iff); |
952 | phase->register_control(not_cset_ctrl, loop, cset_iff); |
953 | |
954 | phase->set_ctrl(cset_addr_ptr, phase->C->root()); |
955 | |
956 | phase->register_new_node(raw_val, old_ctrl); |
957 | phase->register_new_node(cset_idx, old_ctrl); |
958 | phase->register_new_node(cset_addr, old_ctrl); |
959 | phase->register_new_node(cset_load_addr, old_ctrl); |
960 | phase->register_new_node(cset_load_ptr, old_ctrl); |
961 | phase->register_new_node(cset_load, old_ctrl); |
962 | phase->register_new_node(cset_cmp, old_ctrl); |
963 | phase->register_new_node(cset_bool, old_ctrl); |
964 | } |
965 | |
966 | void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, |
967 | DecoratorSet decorators, PhaseIdealLoop* phase) { |
968 | IdealLoopTree*loop = phase->get_loop(ctrl); |
969 | const TypePtr* obj_type = phase->igvn().type(val)->is_oopptr(); |
970 | |
971 | address calladdr = NULL__null; |
972 | const char* name = NULL__null; |
973 | bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); |
974 | bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); |
975 | bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); |
976 | bool is_native = ShenandoahBarrierSet::is_native_access(decorators); |
977 | bool is_narrow = UseCompressedOops && !is_native; |
978 | if (is_strong) { |
979 | if (is_narrow) { |
980 | calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong_narrow)((address)((address_word)(ShenandoahRuntime::load_reference_barrier_strong_narrow ))); |
981 | name = "load_reference_barrier_strong_narrow"; |
982 | } else { |
983 | calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong)((address)((address_word)(ShenandoahRuntime::load_reference_barrier_strong ))); |
984 | name = "load_reference_barrier_strong"; |
985 | } |
986 | } else if (is_weak) { |
987 | if (is_narrow) { |
988 | calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow)((address)((address_word)(ShenandoahRuntime::load_reference_barrier_weak_narrow ))); |
989 | name = "load_reference_barrier_weak_narrow"; |
990 | } else { |
991 | calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak)((address)((address_word)(ShenandoahRuntime::load_reference_barrier_weak ))); |
992 | name = "load_reference_barrier_weak"; |
993 | } |
994 | } else { |
995 | assert(is_phantom, "only remaining strength")do { if (!(is_phantom)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 995, "assert(" "is_phantom" ") failed", "only remaining strength" ); ::breakpoint(); } } while (0); |
996 | if (is_narrow) { |
997 | calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom_narrow)((address)((address_word)(ShenandoahRuntime::load_reference_barrier_phantom_narrow ))); |
998 | name = "load_reference_barrier_phantom_narrow"; |
999 | } else { |
1000 | calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom)((address)((address_word)(ShenandoahRuntime::load_reference_barrier_phantom ))); |
1001 | name = "load_reference_barrier_phantom"; |
1002 | } |
1003 | } |
1004 | Node* call = new CallLeafNode(ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type(), calladdr, name, TypeRawPtr::BOTTOM); |
1005 | |
1006 | call->init_req(TypeFunc::Control, ctrl); |
1007 | call->init_req(TypeFunc::I_O, phase->C->top()); |
1008 | call->init_req(TypeFunc::Memory, phase->C->top()); |
1009 | call->init_req(TypeFunc::FramePtr, phase->C->top()); |
1010 | call->init_req(TypeFunc::ReturnAdr, phase->C->top()); |
1011 | call->init_req(TypeFunc::Parms, val); |
1012 | call->init_req(TypeFunc::Parms+1, load_addr); |
1013 | phase->register_control(call, loop, ctrl); |
1014 | ctrl = new ProjNode(call, TypeFunc::Control); |
1015 | phase->register_control(ctrl, loop, call); |
1016 | val = new ProjNode(call, TypeFunc::Parms); |
1017 | phase->register_new_node(val, call); |
1018 | val = new CheckCastPPNode(ctrl, val, obj_type); |
1019 | phase->register_new_node(val, ctrl); |
1020 | } |
1021 | |
1022 | void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase) { |
1023 | Node* ctrl = phase->get_ctrl(barrier); |
1024 | Node* init_raw_mem = fixer.find_mem(ctrl, barrier); |
1025 | |
1026 | // Update the control of all nodes that should be after the |
1027 | // barrier control flow |
1028 | uses.clear(); |
1029 | // Every node that is control dependent on the barrier's input |
1030 | // control will be after the expanded barrier. The raw memory (if |
1031 | // its memory is control dependent on the barrier's input control) |
1032 | // must stay above the barrier. |
1033 | uses_to_ignore.clear(); |
1034 | if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) { |
1035 | uses_to_ignore.push(init_raw_mem); |
1036 | } |
1037 | for (uint next = 0; next < uses_to_ignore.size(); next++) { |
1038 | Node *n = uses_to_ignore.at(next); |
1039 | for (uint i = 0; i < n->req(); i++) { |
1040 | Node* in = n->in(i); |
1041 | if (in != NULL__null && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) { |
1042 | uses_to_ignore.push(in); |
1043 | } |
1044 | } |
1045 | } |
1046 | for (DUIterator_Fast imax, i = ctrl->fast_outs(imax); i < imax; i++) { |
1047 | Node* u = ctrl->fast_out(i); |
1048 | if (u->_idx < last && |
1049 | u != barrier && |
1050 | !uses_to_ignore.member(u) && |
1051 | (u->in(0) != ctrl || (!u->is_Region() && !u->is_Phi())) && |
1052 | (ctrl->Opcode() != Op_CatchProj || u->Opcode() != Op_CreateEx)) { |
1053 | Node* old_c = phase->ctrl_or_self(u); |
1054 | Node* c = old_c; |
1055 | if (c != ctrl || |
1056 | is_dominator_same_ctrl(old_c, barrier, u, phase) || |
1057 | ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) { |
1058 | phase->igvn().rehash_node_delayed(u); |
1059 | int nb = u->replace_edge(ctrl, region, &phase->igvn()); |
1060 | if (u->is_CFG()) { |
1061 | if (phase->idom(u) == ctrl) { |
1062 | phase->set_idom(u, region, phase->dom_depth(region)); |
1063 | } |
1064 | } else if (phase->get_ctrl(u) == ctrl) { |
1065 | assert(u != init_raw_mem, "should leave input raw mem above the barrier")do { if (!(u != init_raw_mem)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1065, "assert(" "u != init_raw_mem" ") failed", "should leave input raw mem above the barrier" ); ::breakpoint(); } } while (0); |
1066 | uses.push(u); |
1067 | } |
1068 | assert(nb == 1, "more than 1 ctrl input?")do { if (!(nb == 1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1068, "assert(" "nb == 1" ") failed", "more than 1 ctrl input?" ); ::breakpoint(); } } while (0); |
1069 | --i, imax -= nb; |
1070 | } |
1071 | } |
1072 | } |
1073 | } |
1074 | |
1075 | static Node* create_phis_on_call_return(Node* ctrl, Node* c, Node* n, Node* n_clone, const CallProjections& projs, PhaseIdealLoop* phase) { |
1076 | Node* region = NULL__null; |
1077 | while (c != ctrl) { |
1078 | if (c->is_Region()) { |
1079 | region = c; |
1080 | } |
1081 | c = phase->idom(c); |
1082 | } |
1083 | assert(region != NULL, "")do { if (!(region != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1083, "assert(" "region != __null" ") failed", ""); ::breakpoint (); } } while (0); |
1084 | Node* phi = new PhiNode(region, n->bottom_type()); |
1085 | for (uint j = 1; j < region->req(); j++) { |
1086 | Node* in = region->in(j); |
1087 | if (phase->is_dominator(projs.fallthrough_catchproj, in)) { |
1088 | phi->init_req(j, n); |
1089 | } else if (phase->is_dominator(projs.catchall_catchproj, in)) { |
1090 | phi->init_req(j, n_clone); |
1091 | } else { |
1092 | phi->init_req(j, create_phis_on_call_return(ctrl, in, n, n_clone, projs, phase)); |
1093 | } |
1094 | } |
1095 | phase->register_new_node(phi, region); |
1096 | return phi; |
1097 | } |
1098 | |
1099 | void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { |
1100 | ShenandoahBarrierSetC2State* state = ShenandoahBarrierSetC2::bsc2()->state(); |
1101 | |
1102 | Unique_Node_List uses; |
1103 | for (int i = 0; i < state->iu_barriers_count(); i++) { |
1104 | Node* barrier = state->iu_barrier(i); |
1105 | Node* ctrl = phase->get_ctrl(barrier); |
1106 | IdealLoopTree* loop = phase->get_loop(ctrl); |
1107 | Node* head = loop->head(); |
1108 | if (head->is_OuterStripMinedLoop()) { |
1109 | // Expanding a barrier here will break loop strip mining |
1110 | // verification. Transform the loop so the loop nest doesn't |
1111 | // appear as strip mined. |
1112 | OuterStripMinedLoopNode* outer = head->as_OuterStripMinedLoop(); |
1113 | hide_strip_mined_loop(outer, outer->unique_ctrl_out()->as_CountedLoop(), phase); |
1114 | } |
1115 | } |
1116 | |
1117 | Node_Stack stack(0); |
1118 | Node_List clones; |
1119 | for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) { |
1120 | ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i); |
1121 | |
1122 | Node* ctrl = phase->get_ctrl(lrb); |
1123 | Node* val = lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn); |
1124 | |
1125 | CallStaticJavaNode* unc = NULL__null; |
1126 | Node* unc_ctrl = NULL__null; |
1127 | Node* uncasted_val = val; |
1128 | |
1129 | for (DUIterator_Fast imax, i = lrb->fast_outs(imax); i < imax; i++) { |
1130 | Node* u = lrb->fast_out(i); |
1131 | if (u->Opcode() == Op_CastPP && |
1132 | u->in(0) != NULL__null && |
1133 | phase->is_dominator(u->in(0), ctrl)) { |
1134 | const Type* u_t = phase->igvn().type(u); |
1135 | |
1136 | if (u_t->meet(TypePtr::NULL_PTR) != u_t && |
1137 | u->in(0)->Opcode() == Op_IfTrue && |
1138 | u->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) && |
1139 | u->in(0)->in(0)->is_If() && |
1140 | u->in(0)->in(0)->in(1)->Opcode() == Op_Bool && |
1141 | u->in(0)->in(0)->in(1)->as_Bool()->_test._test == BoolTest::ne && |
1142 | u->in(0)->in(0)->in(1)->in(1)->Opcode() == Op_CmpP && |
1143 | u->in(0)->in(0)->in(1)->in(1)->in(1) == val && |
1144 | u->in(0)->in(0)->in(1)->in(1)->in(2)->bottom_type() == TypePtr::NULL_PTR) { |
1145 | IdealLoopTree* loop = phase->get_loop(ctrl); |
1146 | IdealLoopTree* unc_loop = phase->get_loop(u->in(0)); |
1147 | |
1148 | if (!unc_loop->is_member(loop)) { |
1149 | continue; |
1150 | } |
1151 | |
1152 | Node* branch = no_branches(ctrl, u->in(0), false, phase); |
1153 | assert(branch == NULL || branch == NodeSentinel, "was not looking for a branch")do { if (!(branch == __null || branch == (Node*)-1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1153, "assert(" "branch == __null || branch == (Node*)-1" ") failed" , "was not looking for a branch"); ::breakpoint(); } } while ( 0); |
1154 | if (branch == NodeSentinel(Node*)-1) { |
1155 | continue; |
1156 | } |
1157 | |
1158 | Node* iff = u->in(0)->in(0); |
1159 | Node* bol = iff->in(1)->clone(); |
1160 | Node* cmp = bol->in(1)->clone(); |
1161 | cmp->set_req(1, lrb); |
1162 | bol->set_req(1, cmp); |
1163 | phase->igvn().replace_input_of(iff, 1, bol); |
1164 | phase->set_ctrl(lrb, iff->in(0)); |
1165 | phase->register_new_node(cmp, iff->in(0)); |
1166 | phase->register_new_node(bol, iff->in(0)); |
1167 | break; |
1168 | } |
1169 | } |
1170 | } |
1171 | if ((ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) || ctrl->is_CallJava()) { |
1172 | CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava(); |
1173 | if (call->entry_point() == OptoRuntime::rethrow_stub()) { |
1174 | // The rethrow call may have too many projections to be |
1175 | // properly handled here. Given there's no reason for a |
1176 | // barrier to depend on the call, move it above the call |
1177 | stack.push(lrb, 0); |
1178 | do { |
1179 | Node* n = stack.node(); |
1180 | uint idx = stack.index(); |
1181 | if (idx < n->req()) { |
1182 | Node* in = n->in(idx); |
1183 | stack.set_index(idx+1); |
1184 | if (in != NULL__null) { |
1185 | if (phase->has_ctrl(in)) { |
1186 | if (phase->is_dominator(call, phase->get_ctrl(in))) { |
1187 | #ifdef ASSERT1 |
1188 | for (uint i = 0; i < stack.size(); i++) { |
1189 | assert(stack.node_at(i) != in, "node shouldn't have been seen yet")do { if (!(stack.node_at(i) != in)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1189, "assert(" "stack.node_at(i) != in" ") failed", "node shouldn't have been seen yet" ); ::breakpoint(); } } while (0); |
1190 | } |
1191 | #endif |
1192 | stack.push(in, 0); |
1193 | } |
1194 | } else { |
1195 | assert(phase->is_dominator(in, call->in(0)), "no dependency on the call")do { if (!(phase->is_dominator(in, call->in(0)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1195, "assert(" "phase->is_dominator(in, call->in(0))" ") failed", "no dependency on the call"); ::breakpoint(); } } while (0); |
1196 | } |
1197 | } |
1198 | } else { |
1199 | phase->set_ctrl(n, call->in(0)); |
1200 | stack.pop(); |
1201 | } |
1202 | } while(stack.size() > 0); |
1203 | continue; |
1204 | } |
1205 | CallProjections projs; |
1206 | call->extract_projections(&projs, false, false); |
1207 | |
1208 | #ifdef ASSERT1 |
1209 | VectorSet cloned; |
1210 | #endif |
1211 | Node* lrb_clone = lrb->clone(); |
1212 | phase->register_new_node(lrb_clone, projs.catchall_catchproj); |
1213 | phase->set_ctrl(lrb, projs.fallthrough_catchproj); |
1214 | |
1215 | stack.push(lrb, 0); |
1216 | clones.push(lrb_clone); |
1217 | |
1218 | do { |
1219 | assert(stack.size() == clones.size(), "")do { if (!(stack.size() == clones.size())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1219, "assert(" "stack.size() == clones.size()" ") failed", ""); ::breakpoint(); } } while (0); |
1220 | Node* n = stack.node(); |
1221 | #ifdef ASSERT1 |
1222 | if (n->is_Load()) { |
1223 | Node* mem = n->in(MemNode::Memory); |
1224 | for (DUIterator_Fast jmax, j = mem->fast_outs(jmax); j < jmax; j++) { |
1225 | Node* u = mem->fast_out(j); |
1226 | assert(!u->is_Store() || !u->is_LoadStore() || phase->get_ctrl(u) != ctrl, "anti dependent store?")do { if (!(!u->is_Store() || !u->is_LoadStore() || phase ->get_ctrl(u) != ctrl)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1226, "assert(" "!u->is_Store() || !u->is_LoadStore() || phase->get_ctrl(u) != ctrl" ") failed", "anti dependent store?"); ::breakpoint(); } } while (0); |
1227 | } |
1228 | } |
1229 | #endif |
1230 | uint idx = stack.index(); |
1231 | Node* n_clone = clones.at(clones.size()-1); |
1232 | if (idx < n->outcnt()) { |
1233 | Node* u = n->raw_out(idx); |
1234 | Node* c = phase->ctrl_or_self(u); |
1235 | if (phase->is_dominator(call, c) && phase->is_dominator(c, projs.fallthrough_proj)) { |
1236 | stack.set_index(idx+1); |
1237 | assert(!u->is_CFG(), "")do { if (!(!u->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1237, "assert(" "!u->is_CFG()" ") failed", ""); ::breakpoint (); } } while (0); |
1238 | stack.push(u, 0); |
1239 | assert(!cloned.test_set(u->_idx), "only one clone")do { if (!(!cloned.test_set(u->_idx))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1239, "assert(" "!cloned.test_set(u->_idx)" ") failed", "only one clone" ); ::breakpoint(); } } while (0); |
1240 | Node* u_clone = u->clone(); |
1241 | int nb = u_clone->replace_edge(n, n_clone, &phase->igvn()); |
1242 | assert(nb > 0, "should have replaced some uses")do { if (!(nb > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1242, "assert(" "nb > 0" ") failed", "should have replaced some uses" ); ::breakpoint(); } } while (0); |
1243 | phase->register_new_node(u_clone, projs.catchall_catchproj); |
1244 | clones.push(u_clone); |
1245 | phase->set_ctrl(u, projs.fallthrough_catchproj); |
1246 | } else { |
1247 | bool replaced = false; |
1248 | if (u->is_Phi()) { |
1249 | for (uint k = 1; k < u->req(); k++) { |
1250 | if (u->in(k) == n) { |
1251 | if (phase->is_dominator(projs.catchall_catchproj, u->in(0)->in(k))) { |
1252 | phase->igvn().replace_input_of(u, k, n_clone); |
1253 | replaced = true; |
1254 | } else if (!phase->is_dominator(projs.fallthrough_catchproj, u->in(0)->in(k))) { |
1255 | phase->igvn().replace_input_of(u, k, create_phis_on_call_return(ctrl, u->in(0)->in(k), n, n_clone, projs, phase)); |
1256 | replaced = true; |
1257 | } |
1258 | } |
1259 | } |
1260 | } else { |
1261 | if (phase->is_dominator(projs.catchall_catchproj, c)) { |
1262 | phase->igvn().rehash_node_delayed(u); |
1263 | int nb = u->replace_edge(n, n_clone, &phase->igvn()); |
1264 | assert(nb > 0, "should have replaced some uses")do { if (!(nb > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1264, "assert(" "nb > 0" ") failed", "should have replaced some uses" ); ::breakpoint(); } } while (0); |
1265 | replaced = true; |
1266 | } else if (!phase->is_dominator(projs.fallthrough_catchproj, c)) { |
1267 | if (u->is_If()) { |
1268 | // Can't break If/Bool/Cmp chain |
1269 | assert(n->is_Bool(), "unexpected If shape")do { if (!(n->is_Bool())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1269, "assert(" "n->is_Bool()" ") failed", "unexpected If shape" ); ::breakpoint(); } } while (0); |
1270 | assert(stack.node_at(stack.size()-2)->is_Cmp(), "unexpected If shape")do { if (!(stack.node_at(stack.size()-2)->is_Cmp())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1270, "assert(" "stack.node_at(stack.size()-2)->is_Cmp()" ") failed", "unexpected If shape"); ::breakpoint(); } } while (0); |
1271 | assert(n_clone->is_Bool(), "unexpected clone")do { if (!(n_clone->is_Bool())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1271, "assert(" "n_clone->is_Bool()" ") failed", "unexpected clone" ); ::breakpoint(); } } while (0); |
1272 | assert(clones.at(clones.size()-2)->is_Cmp(), "unexpected clone")do { if (!(clones.at(clones.size()-2)->is_Cmp())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1272, "assert(" "clones.at(clones.size()-2)->is_Cmp()" ") failed" , "unexpected clone"); ::breakpoint(); } } while (0); |
1273 | Node* bol_clone = n->clone(); |
1274 | Node* cmp_clone = stack.node_at(stack.size()-2)->clone(); |
1275 | bol_clone->set_req(1, cmp_clone); |
1276 | |
1277 | Node* nn = stack.node_at(stack.size()-3); |
1278 | Node* nn_clone = clones.at(clones.size()-3); |
1279 | assert(nn->Opcode() == nn_clone->Opcode(), "mismatch")do { if (!(nn->Opcode() == nn_clone->Opcode())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1279, "assert(" "nn->Opcode() == nn_clone->Opcode()" ") failed" , "mismatch"); ::breakpoint(); } } while (0); |
1280 | |
1281 | int nb = cmp_clone->replace_edge(nn, create_phis_on_call_return(ctrl, c, nn, nn_clone, projs, phase), |
1282 | &phase->igvn()); |
1283 | assert(nb > 0, "should have replaced some uses")do { if (!(nb > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1283, "assert(" "nb > 0" ") failed", "should have replaced some uses" ); ::breakpoint(); } } while (0); |
1284 | |
1285 | phase->register_new_node(bol_clone, u->in(0)); |
1286 | phase->register_new_node(cmp_clone, u->in(0)); |
1287 | |
1288 | phase->igvn().replace_input_of(u, 1, bol_clone); |
1289 | |
1290 | } else { |
1291 | phase->igvn().rehash_node_delayed(u); |
1292 | int nb = u->replace_edge(n, create_phis_on_call_return(ctrl, c, n, n_clone, projs, phase), &phase->igvn()); |
1293 | assert(nb > 0, "should have replaced some uses")do { if (!(nb > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1293, "assert(" "nb > 0" ") failed", "should have replaced some uses" ); ::breakpoint(); } } while (0); |
1294 | } |
1295 | replaced = true; |
1296 | } |
1297 | } |
1298 | if (!replaced) { |
1299 | stack.set_index(idx+1); |
1300 | } |
1301 | } |
1302 | } else { |
1303 | stack.pop(); |
1304 | clones.pop(); |
1305 | } |
1306 | } while (stack.size() > 0); |
1307 | assert(stack.size() == 0 && clones.size() == 0, "")do { if (!(stack.size() == 0 && clones.size() == 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1307, "assert(" "stack.size() == 0 && clones.size() == 0" ") failed", ""); ::breakpoint(); } } while (0); |
1308 | } |
1309 | } |
1310 | |
1311 | for (int i = 0; i < state->load_reference_barriers_count(); i++) { |
1312 | ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i); |
1313 | Node* ctrl = phase->get_ctrl(lrb); |
1314 | IdealLoopTree* loop = phase->get_loop(ctrl); |
1315 | Node* head = loop->head(); |
1316 | if (head->is_OuterStripMinedLoop()) { |
1317 | // Expanding a barrier here will break loop strip mining |
1318 | // verification. Transform the loop so the loop nest doesn't |
1319 | // appear as strip mined. |
1320 | OuterStripMinedLoopNode* outer = head->as_OuterStripMinedLoop(); |
1321 | hide_strip_mined_loop(outer, outer->unique_ctrl_out()->as_CountedLoop(), phase); |
1322 | } |
1323 | } |
1324 | |
1325 | // Expand load-reference-barriers |
1326 | MemoryGraphFixer fixer(Compile::AliasIdxRaw, true, phase); |
1327 | Unique_Node_List uses_to_ignore; |
1328 | for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) { |
1329 | ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i); |
1330 | uint last = phase->C->unique(); |
1331 | Node* ctrl = phase->get_ctrl(lrb); |
1332 | Node* val = lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn); |
1333 | |
1334 | Node* orig_ctrl = ctrl; |
1335 | |
1336 | Node* raw_mem = fixer.find_mem(ctrl, lrb); |
1337 | |
1338 | IdealLoopTree *loop = phase->get_loop(ctrl); |
1339 | |
1340 | Node* heap_stable_ctrl = NULL__null; |
1341 | Node* null_ctrl = NULL__null; |
1342 | |
1343 | assert(val->bottom_type()->make_oopptr(), "need oop")do { if (!(val->bottom_type()->make_oopptr())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1343, "assert(" "val->bottom_type()->make_oopptr()" ") failed" , "need oop"); ::breakpoint(); } } while (0); |
1344 | assert(val->bottom_type()->make_oopptr()->const_oop() == NULL, "expect non-constant")do { if (!(val->bottom_type()->make_oopptr()->const_oop () == __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1344, "assert(" "val->bottom_type()->make_oopptr()->const_oop() == __null" ") failed", "expect non-constant"); ::breakpoint(); } } while (0); |
1345 | |
1346 | enum { _heap_stable = 1, _evac_path, _not_cset, PATH_LIMIT }; |
1347 | Node* region = new RegionNode(PATH_LIMIT); |
1348 | Node* val_phi = new PhiNode(region, val->bottom_type()->is_oopptr()); |
1349 | |
1350 | // Stable path. |
1351 | int flags = ShenandoahHeap::HAS_FORWARDED; |
1352 | if (!ShenandoahBarrierSet::is_strong_access(lrb->decorators())) { |
1353 | flags |= ShenandoahHeap::WEAK_ROOTS; |
1354 | } |
1355 | test_gc_state(ctrl, raw_mem, heap_stable_ctrl, phase, flags); |
1356 | IfNode* heap_stable_iff = heap_stable_ctrl->in(0)->as_If(); |
1357 | |
1358 | // Heap stable case |
1359 | region->init_req(_heap_stable, heap_stable_ctrl); |
1360 | val_phi->init_req(_heap_stable, val); |
1361 | |
1362 | // Test for in-cset, unless it's a native-LRB. Native LRBs need to return NULL |
1363 | // even for non-cset objects to prevent ressurrection of such objects. |
1364 | // Wires !in_cset(obj) to slot 2 of region and phis |
1365 | Node* not_cset_ctrl = NULL__null; |
1366 | if (ShenandoahBarrierSet::is_strong_access(lrb->decorators())) { |
1367 | test_in_cset(ctrl, not_cset_ctrl, val, raw_mem, phase); |
1368 | } |
1369 | if (not_cset_ctrl != NULL__null) { |
1370 | region->init_req(_not_cset, not_cset_ctrl); |
1371 | val_phi->init_req(_not_cset, val); |
1372 | } else { |
1373 | region->del_req(_not_cset); |
1374 | val_phi->del_req(_not_cset); |
1375 | } |
1376 | |
1377 | // Resolve object when orig-value is in cset. |
1378 | // Make the unconditional resolve for fwdptr. |
1379 | |
1380 | // Call lrb-stub and wire up that path in slots 4 |
1381 | Node* result_mem = NULL__null; |
1382 | |
1383 | Node* addr; |
1384 | if (ShenandoahSelfFixing) { |
1385 | VectorSet visited; |
1386 | addr = get_load_addr(phase, visited, lrb); |
1387 | } else { |
1388 | addr = phase->igvn().zerocon(T_OBJECT); |
1389 | } |
1390 | if (addr->Opcode() == Op_AddP) { |
1391 | Node* orig_base = addr->in(AddPNode::Base); |
1392 | Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), ConstraintCastNode::StrongDependency); |
1393 | phase->register_new_node(base, ctrl); |
1394 | if (addr->in(AddPNode::Base) == addr->in((AddPNode::Address))) { |
1395 | // Field access |
1396 | addr = addr->clone(); |
1397 | addr->set_req(AddPNode::Base, base); |
1398 | addr->set_req(AddPNode::Address, base); |
1399 | phase->register_new_node(addr, ctrl); |
1400 | } else { |
1401 | Node* addr2 = addr->in(AddPNode::Address); |
1402 | if (addr2->Opcode() == Op_AddP && addr2->in(AddPNode::Base) == addr2->in(AddPNode::Address) && |
1403 | addr2->in(AddPNode::Base) == orig_base) { |
1404 | addr2 = addr2->clone(); |
1405 | addr2->set_req(AddPNode::Base, base); |
1406 | addr2->set_req(AddPNode::Address, base); |
1407 | phase->register_new_node(addr2, ctrl); |
1408 | addr = addr->clone(); |
1409 | addr->set_req(AddPNode::Base, base); |
1410 | addr->set_req(AddPNode::Address, addr2); |
1411 | phase->register_new_node(addr, ctrl); |
1412 | } |
1413 | } |
1414 | } |
1415 | call_lrb_stub(ctrl, val, addr, lrb->decorators(), phase); |
1416 | region->init_req(_evac_path, ctrl); |
1417 | val_phi->init_req(_evac_path, val); |
1418 | |
1419 | phase->register_control(region, loop, heap_stable_iff); |
1420 | Node* out_val = val_phi; |
1421 | phase->register_new_node(val_phi, region); |
1422 | |
1423 | fix_ctrl(lrb, region, fixer, uses, uses_to_ignore, last, phase); |
1424 | |
1425 | ctrl = orig_ctrl; |
1426 | |
1427 | phase->igvn().replace_node(lrb, out_val); |
1428 | |
1429 | follow_barrier_uses(out_val, ctrl, uses, phase); |
1430 | |
1431 | for(uint next = 0; next < uses.size(); next++ ) { |
1432 | Node *n = uses.at(next); |
1433 | assert(phase->get_ctrl(n) == ctrl, "bad control")do { if (!(phase->get_ctrl(n) == ctrl)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1433, "assert(" "phase->get_ctrl(n) == ctrl" ") failed", "bad control"); ::breakpoint(); } } while (0); |
1434 | assert(n != raw_mem, "should leave input raw mem above the barrier")do { if (!(n != raw_mem)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1434, "assert(" "n != raw_mem" ") failed", "should leave input raw mem above the barrier" ); ::breakpoint(); } } while (0); |
1435 | phase->set_ctrl(n, region); |
1436 | follow_barrier_uses(n, ctrl, uses, phase); |
1437 | } |
1438 | } |
1439 | // Done expanding load-reference-barriers. |
1440 | assert(ShenandoahBarrierSetC2::bsc2()->state()->load_reference_barriers_count() == 0, "all load reference barrier nodes should have been replaced")do { if (!(ShenandoahBarrierSetC2::bsc2()->state()->load_reference_barriers_count () == 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1440, "assert(" "ShenandoahBarrierSetC2::bsc2()->state()->load_reference_barriers_count() == 0" ") failed", "all load reference barrier nodes should have been replaced" ); ::breakpoint(); } } while (0); |
1441 | |
1442 | for (int i = state->iu_barriers_count() - 1; i >= 0; i--) { |
1443 | Node* barrier = state->iu_barrier(i); |
1444 | Node* pre_val = barrier->in(1); |
1445 | |
1446 | if (phase->igvn().type(pre_val)->higher_equal(TypePtr::NULL_PTR)) { |
1447 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1447); ::breakpoint(); } while (0); |
1448 | continue; |
1449 | } |
1450 | |
1451 | Node* ctrl = phase->get_ctrl(barrier); |
1452 | |
1453 | if (ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) { |
1454 | assert(is_dominator(phase->get_ctrl(pre_val), ctrl->in(0)->in(0), pre_val, ctrl->in(0), phase), "can't move")do { if (!(is_dominator(phase->get_ctrl(pre_val), ctrl-> in(0)->in(0), pre_val, ctrl->in(0), phase))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1454, "assert(" "is_dominator(phase->get_ctrl(pre_val), ctrl->in(0)->in(0), pre_val, ctrl->in(0), phase)" ") failed", "can't move"); ::breakpoint(); } } while (0); |
1455 | ctrl = ctrl->in(0)->in(0); |
1456 | phase->set_ctrl(barrier, ctrl); |
1457 | } else if (ctrl->is_CallRuntime()) { |
1458 | assert(is_dominator(phase->get_ctrl(pre_val), ctrl->in(0), pre_val, ctrl, phase), "can't move")do { if (!(is_dominator(phase->get_ctrl(pre_val), ctrl-> in(0), pre_val, ctrl, phase))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1458, "assert(" "is_dominator(phase->get_ctrl(pre_val), ctrl->in(0), pre_val, ctrl, phase)" ") failed", "can't move"); ::breakpoint(); } } while (0); |
1459 | ctrl = ctrl->in(0); |
1460 | phase->set_ctrl(barrier, ctrl); |
1461 | } |
1462 | |
1463 | Node* init_ctrl = ctrl; |
1464 | IdealLoopTree* loop = phase->get_loop(ctrl); |
1465 | Node* raw_mem = fixer.find_mem(ctrl, barrier); |
1466 | Node* init_raw_mem = raw_mem; |
1467 | Node* raw_mem_for_ctrl = fixer.find_mem(ctrl, NULL__null); |
1468 | Node* heap_stable_ctrl = NULL__null; |
1469 | Node* null_ctrl = NULL__null; |
1470 | uint last = phase->C->unique(); |
1471 | |
1472 | enum { _heap_stable = 1, _heap_unstable, PATH_LIMIT }; |
1473 | Node* region = new RegionNode(PATH_LIMIT); |
1474 | Node* phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM); |
1475 | |
1476 | enum { _fast_path = 1, _slow_path, _null_path, PATH_LIMIT2 }; |
1477 | Node* region2 = new RegionNode(PATH_LIMIT2); |
1478 | Node* phi2 = PhiNode::make(region2, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM); |
1479 | |
1480 | // Stable path. |
1481 | test_gc_state(ctrl, raw_mem, heap_stable_ctrl, phase, ShenandoahHeap::MARKING); |
1482 | region->init_req(_heap_stable, heap_stable_ctrl); |
1483 | phi->init_req(_heap_stable, raw_mem); |
1484 | |
1485 | // Null path |
1486 | Node* reg2_ctrl = NULL__null; |
1487 | test_null(ctrl, pre_val, null_ctrl, phase); |
1488 | if (null_ctrl != NULL__null) { |
1489 | reg2_ctrl = null_ctrl->in(0); |
1490 | region2->init_req(_null_path, null_ctrl); |
1491 | phi2->init_req(_null_path, raw_mem); |
1492 | } else { |
1493 | region2->del_req(_null_path); |
1494 | phi2->del_req(_null_path); |
1495 | } |
1496 | |
1497 | const int index_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()); |
1498 | const int buffer_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()); |
1499 | Node* thread = new ThreadLocalNode(); |
1500 | phase->register_new_node(thread, ctrl); |
1501 | Node* buffer_adr = new AddPNode(phase->C->top(), thread, phase->igvn().MakeConXlongcon(buffer_offset)); |
1502 | phase->register_new_node(buffer_adr, ctrl); |
1503 | Node* index_adr = new AddPNode(phase->C->top(), thread, phase->igvn().MakeConXlongcon(index_offset)); |
1504 | phase->register_new_node(index_adr, ctrl); |
1505 | |
1506 | BasicType index_bt = TypeX_XTypeLong::LONG->basic_type(); |
1507 | assert(sizeof(size_t) == type2aelembytes(index_bt), "Loading Shenandoah SATBMarkQueue::_index with wrong size.")do { if (!(sizeof(size_t) == type2aelembytes(index_bt))) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1507, "assert(" "sizeof(size_t) == type2aelembytes(index_bt)" ") failed", "Loading Shenandoah SATBMarkQueue::_index with wrong size." ); ::breakpoint(); } } while (0); |
1508 | const TypePtr* adr_type = TypeRawPtr::BOTTOM; |
1509 | Node* index = new LoadXNodeLoadLNode(ctrl, raw_mem, index_adr, adr_type, TypeX_XTypeLong::LONG, MemNode::unordered); |
1510 | phase->register_new_node(index, ctrl); |
1511 | Node* index_cmp = new CmpXNodeCmpLNode(index, phase->igvn().MakeConXlongcon(0)); |
1512 | phase->register_new_node(index_cmp, ctrl); |
1513 | Node* index_test = new BoolNode(index_cmp, BoolTest::ne); |
1514 | phase->register_new_node(index_test, ctrl); |
1515 | IfNode* queue_full_iff = new IfNode(ctrl, index_test, PROB_LIKELY(0.999)((float) (0.999)), COUNT_UNKNOWN(-1.0f)); |
1516 | if (reg2_ctrl == NULL__null) reg2_ctrl = queue_full_iff; |
1517 | phase->register_control(queue_full_iff, loop, ctrl); |
1518 | Node* not_full = new IfTrueNode(queue_full_iff); |
1519 | phase->register_control(not_full, loop, queue_full_iff); |
1520 | Node* full = new IfFalseNode(queue_full_iff); |
1521 | phase->register_control(full, loop, queue_full_iff); |
1522 | |
1523 | ctrl = not_full; |
1524 | |
1525 | Node* next_index = new SubXNodeSubLNode(index, phase->igvn().MakeConXlongcon(sizeof(intptr_t))); |
1526 | phase->register_new_node(next_index, ctrl); |
1527 | |
1528 | Node* buffer = new LoadPNode(ctrl, raw_mem, buffer_adr, adr_type, TypeRawPtr::NOTNULL, MemNode::unordered); |
1529 | phase->register_new_node(buffer, ctrl); |
1530 | Node *log_addr = new AddPNode(phase->C->top(), buffer, next_index); |
1531 | phase->register_new_node(log_addr, ctrl); |
1532 | Node* log_store = new StorePNode(ctrl, raw_mem, log_addr, adr_type, pre_val, MemNode::unordered); |
1533 | phase->register_new_node(log_store, ctrl); |
1534 | // update the index |
1535 | Node* index_update = new StoreXNodeStoreLNode(ctrl, log_store, index_adr, adr_type, next_index, MemNode::unordered); |
1536 | phase->register_new_node(index_update, ctrl); |
1537 | |
1538 | // Fast-path case |
1539 | region2->init_req(_fast_path, ctrl); |
1540 | phi2->init_req(_fast_path, index_update); |
1541 | |
1542 | ctrl = full; |
1543 | |
1544 | Node* base = find_bottom_mem(ctrl, phase); |
1545 | |
1546 | MergeMemNode* mm = MergeMemNode::make(base); |
1547 | mm->set_memory_at(Compile::AliasIdxRaw, raw_mem); |
1548 | phase->register_new_node(mm, ctrl); |
1549 | |
1550 | Node* call = new CallLeafNode(ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type(), CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry)((address)((address_word)(ShenandoahRuntime::write_ref_field_pre_entry ))), "shenandoah_wb_pre", TypeRawPtr::BOTTOM); |
1551 | call->init_req(TypeFunc::Control, ctrl); |
1552 | call->init_req(TypeFunc::I_O, phase->C->top()); |
1553 | call->init_req(TypeFunc::Memory, mm); |
1554 | call->init_req(TypeFunc::FramePtr, phase->C->top()); |
1555 | call->init_req(TypeFunc::ReturnAdr, phase->C->top()); |
1556 | call->init_req(TypeFunc::Parms, pre_val); |
1557 | call->init_req(TypeFunc::Parms+1, thread); |
1558 | phase->register_control(call, loop, ctrl); |
1559 | |
1560 | Node* ctrl_proj = new ProjNode(call, TypeFunc::Control); |
1561 | phase->register_control(ctrl_proj, loop, call); |
1562 | Node* mem_proj = new ProjNode(call, TypeFunc::Memory); |
1563 | phase->register_new_node(mem_proj, call); |
1564 | |
1565 | // Slow-path case |
1566 | region2->init_req(_slow_path, ctrl_proj); |
1567 | phi2->init_req(_slow_path, mem_proj); |
1568 | |
1569 | phase->register_control(region2, loop, reg2_ctrl); |
1570 | phase->register_new_node(phi2, region2); |
1571 | |
1572 | region->init_req(_heap_unstable, region2); |
1573 | phi->init_req(_heap_unstable, phi2); |
1574 | |
1575 | phase->register_control(region, loop, heap_stable_ctrl->in(0)); |
1576 | phase->register_new_node(phi, region); |
1577 | |
1578 | fix_ctrl(barrier, region, fixer, uses, uses_to_ignore, last, phase); |
1579 | for(uint next = 0; next < uses.size(); next++ ) { |
1580 | Node *n = uses.at(next); |
1581 | assert(phase->get_ctrl(n) == init_ctrl, "bad control")do { if (!(phase->get_ctrl(n) == init_ctrl)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1581, "assert(" "phase->get_ctrl(n) == init_ctrl" ") failed" , "bad control"); ::breakpoint(); } } while (0); |
1582 | assert(n != init_raw_mem, "should leave input raw mem above the barrier")do { if (!(n != init_raw_mem)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1582, "assert(" "n != init_raw_mem" ") failed", "should leave input raw mem above the barrier" ); ::breakpoint(); } } while (0); |
1583 | phase->set_ctrl(n, region); |
1584 | follow_barrier_uses(n, init_ctrl, uses, phase); |
1585 | } |
1586 | fixer.fix_mem(init_ctrl, region, init_raw_mem, raw_mem_for_ctrl, phi, uses); |
1587 | |
1588 | phase->igvn().replace_node(barrier, pre_val); |
1589 | } |
1590 | assert(state->iu_barriers_count() == 0, "all enqueue barrier nodes should have been replaced")do { if (!(state->iu_barriers_count() == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1590, "assert(" "state->iu_barriers_count() == 0" ") failed" , "all enqueue barrier nodes should have been replaced"); ::breakpoint (); } } while (0); |
1591 | |
1592 | } |
1593 | |
1594 | Node* ShenandoahBarrierC2Support::get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* in) { |
1595 | if (visited.test_set(in->_idx)) { |
1596 | return NULL__null; |
1597 | } |
1598 | switch (in->Opcode()) { |
1599 | case Op_Proj: |
1600 | return get_load_addr(phase, visited, in->in(0)); |
1601 | case Op_CastPP: |
1602 | case Op_CheckCastPP: |
1603 | case Op_DecodeN: |
1604 | case Op_EncodeP: |
1605 | return get_load_addr(phase, visited, in->in(1)); |
1606 | case Op_LoadN: |
1607 | case Op_LoadP: |
1608 | return in->in(MemNode::Address); |
1609 | case Op_CompareAndExchangeN: |
1610 | case Op_CompareAndExchangeP: |
1611 | case Op_GetAndSetN: |
1612 | case Op_GetAndSetP: |
1613 | case Op_ShenandoahCompareAndExchangeP: |
1614 | case Op_ShenandoahCompareAndExchangeN: |
1615 | // Those instructions would just have stored a different |
1616 | // value into the field. No use to attempt to fix it at this point. |
1617 | return phase->igvn().zerocon(T_OBJECT); |
1618 | case Op_CMoveP: |
1619 | case Op_CMoveN: { |
1620 | Node* t = get_load_addr(phase, visited, in->in(CMoveNode::IfTrue)); |
1621 | Node* f = get_load_addr(phase, visited, in->in(CMoveNode::IfFalse)); |
1622 | // Handle unambiguous cases: single address reported on both branches. |
1623 | if (t != NULL__null && f == NULL__null) return t; |
1624 | if (t == NULL__null && f != NULL__null) return f; |
1625 | if (t != NULL__null && t == f) return t; |
1626 | // Ambiguity. |
1627 | return phase->igvn().zerocon(T_OBJECT); |
1628 | } |
1629 | case Op_Phi: { |
1630 | Node* addr = NULL__null; |
1631 | for (uint i = 1; i < in->req(); i++) { |
1632 | Node* addr1 = get_load_addr(phase, visited, in->in(i)); |
1633 | if (addr == NULL__null) { |
1634 | addr = addr1; |
1635 | } |
1636 | if (addr != addr1) { |
1637 | return phase->igvn().zerocon(T_OBJECT); |
1638 | } |
1639 | } |
1640 | return addr; |
1641 | } |
1642 | case Op_ShenandoahLoadReferenceBarrier: |
1643 | return get_load_addr(phase, visited, in->in(ShenandoahLoadReferenceBarrierNode::ValueIn)); |
1644 | case Op_ShenandoahIUBarrier: |
1645 | return get_load_addr(phase, visited, in->in(1)); |
1646 | case Op_CallDynamicJava: |
1647 | case Op_CallLeaf: |
1648 | case Op_CallStaticJava: |
1649 | case Op_ConN: |
1650 | case Op_ConP: |
1651 | case Op_Parm: |
1652 | case Op_CreateEx: |
1653 | return phase->igvn().zerocon(T_OBJECT); |
1654 | default: |
1655 | #ifdef ASSERT1 |
1656 | fatal("Unknown node in get_load_addr: %s", NodeClassNames[in->Opcode()])do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1656, "Unknown node in get_load_addr: %s", NodeClassNames[in ->Opcode()]); ::breakpoint(); } while (0); |
1657 | #endif |
1658 | return phase->igvn().zerocon(T_OBJECT); |
1659 | } |
1660 | |
1661 | } |
1662 | |
1663 | void ShenandoahBarrierC2Support::move_gc_state_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase) { |
1664 | IdealLoopTree *loop = phase->get_loop(iff); |
1665 | Node* loop_head = loop->_head; |
1666 | Node* entry_c = loop_head->in(LoopNode::EntryControl); |
1667 | |
1668 | Node* bol = iff->in(1); |
1669 | Node* cmp = bol->in(1); |
1670 | Node* andi = cmp->in(1); |
1671 | Node* load = andi->in(1); |
1672 | |
1673 | assert(is_gc_state_load(load), "broken")do { if (!(is_gc_state_load(load))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1673, "assert(" "is_gc_state_load(load)" ") failed", "broken" ); ::breakpoint(); } } while (0); |
1674 | if (!phase->is_dominator(load->in(0), entry_c)) { |
1675 | Node* mem_ctrl = NULL__null; |
1676 | Node* mem = dom_mem(load->in(MemNode::Memory), loop_head, Compile::AliasIdxRaw, mem_ctrl, phase); |
1677 | load = load->clone(); |
1678 | load->set_req(MemNode::Memory, mem); |
1679 | load->set_req(0, entry_c); |
1680 | phase->register_new_node(load, entry_c); |
1681 | andi = andi->clone(); |
1682 | andi->set_req(1, load); |
1683 | phase->register_new_node(andi, entry_c); |
1684 | cmp = cmp->clone(); |
1685 | cmp->set_req(1, andi); |
1686 | phase->register_new_node(cmp, entry_c); |
1687 | bol = bol->clone(); |
1688 | bol->set_req(1, cmp); |
1689 | phase->register_new_node(bol, entry_c); |
1690 | |
1691 | phase->igvn().replace_input_of(iff, 1, bol); |
1692 | } |
1693 | } |
1694 | |
1695 | bool ShenandoahBarrierC2Support::identical_backtoback_ifs(Node* n, PhaseIdealLoop* phase) { |
1696 | if (!n->is_If() || n->is_CountedLoopEnd()) { |
1697 | return false; |
1698 | } |
1699 | Node* region = n->in(0); |
1700 | |
1701 | if (!region->is_Region()) { |
1702 | return false; |
1703 | } |
1704 | Node* dom = phase->idom(region); |
1705 | if (!dom->is_If()) { |
1706 | return false; |
1707 | } |
1708 | |
1709 | if (!is_heap_stable_test(n) || !is_heap_stable_test(dom)) { |
1710 | return false; |
1711 | } |
1712 | |
1713 | IfNode* dom_if = dom->as_If(); |
1714 | Node* proj_true = dom_if->proj_out(1); |
1715 | Node* proj_false = dom_if->proj_out(0); |
1716 | |
1717 | for (uint i = 1; i < region->req(); i++) { |
1718 | if (phase->is_dominator(proj_true, region->in(i))) { |
1719 | continue; |
1720 | } |
1721 | if (phase->is_dominator(proj_false, region->in(i))) { |
1722 | continue; |
1723 | } |
1724 | return false; |
1725 | } |
1726 | |
1727 | return true; |
1728 | } |
1729 | |
1730 | void ShenandoahBarrierC2Support::merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase) { |
1731 | assert(is_heap_stable_test(n), "no other tests")do { if (!(is_heap_stable_test(n))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1731, "assert(" "is_heap_stable_test(n)" ") failed", "no other tests" ); ::breakpoint(); } } while (0); |
1732 | if (identical_backtoback_ifs(n, phase)) { |
1733 | Node* n_ctrl = n->in(0); |
1734 | if (phase->can_split_if(n_ctrl)) { |
1735 | IfNode* dom_if = phase->idom(n_ctrl)->as_If(); |
1736 | if (is_heap_stable_test(n)) { |
1737 | Node* gc_state_load = n->in(1)->in(1)->in(1)->in(1); |
1738 | assert(is_gc_state_load(gc_state_load), "broken")do { if (!(is_gc_state_load(gc_state_load))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1738, "assert(" "is_gc_state_load(gc_state_load)" ") failed" , "broken"); ::breakpoint(); } } while (0); |
1739 | Node* dom_gc_state_load = dom_if->in(1)->in(1)->in(1)->in(1); |
1740 | assert(is_gc_state_load(dom_gc_state_load), "broken")do { if (!(is_gc_state_load(dom_gc_state_load))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1740, "assert(" "is_gc_state_load(dom_gc_state_load)" ") failed" , "broken"); ::breakpoint(); } } while (0); |
1741 | if (gc_state_load != dom_gc_state_load) { |
1742 | phase->igvn().replace_node(gc_state_load, dom_gc_state_load); |
1743 | } |
1744 | } |
1745 | PhiNode* bolphi = PhiNode::make_blank(n_ctrl, n->in(1)); |
1746 | Node* proj_true = dom_if->proj_out(1); |
1747 | Node* proj_false = dom_if->proj_out(0); |
1748 | Node* con_true = phase->igvn().makecon(TypeInt::ONE); |
1749 | Node* con_false = phase->igvn().makecon(TypeInt::ZERO); |
1750 | |
1751 | for (uint i = 1; i < n_ctrl->req(); i++) { |
1752 | if (phase->is_dominator(proj_true, n_ctrl->in(i))) { |
1753 | bolphi->init_req(i, con_true); |
1754 | } else { |
1755 | assert(phase->is_dominator(proj_false, n_ctrl->in(i)), "bad if")do { if (!(phase->is_dominator(proj_false, n_ctrl->in(i )))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1755, "assert(" "phase->is_dominator(proj_false, n_ctrl->in(i))" ") failed", "bad if"); ::breakpoint(); } } while (0); |
1756 | bolphi->init_req(i, con_false); |
1757 | } |
1758 | } |
1759 | phase->register_new_node(bolphi, n_ctrl); |
1760 | phase->igvn().replace_input_of(n, 1, bolphi); |
1761 | phase->do_split_if(n); |
1762 | } |
1763 | } |
1764 | } |
1765 | |
1766 | IfNode* ShenandoahBarrierC2Support::find_unswitching_candidate(const IdealLoopTree* loop, PhaseIdealLoop* phase) { |
1767 | // Find first invariant test that doesn't exit the loop |
1768 | LoopNode *head = loop->_head->as_Loop(); |
1769 | IfNode* unswitch_iff = NULL__null; |
1770 | Node* n = head->in(LoopNode::LoopBackControl); |
1771 | int loop_has_sfpts = -1; |
1772 | while (n != head) { |
1773 | Node* n_dom = phase->idom(n); |
1774 | if (n->is_Region()) { |
1775 | if (n_dom->is_If()) { |
1776 | IfNode* iff = n_dom->as_If(); |
1777 | if (iff->in(1)->is_Bool()) { |
1778 | BoolNode* bol = iff->in(1)->as_Bool(); |
1779 | if (bol->in(1)->is_Cmp()) { |
1780 | // If condition is invariant and not a loop exit, |
1781 | // then found reason to unswitch. |
1782 | if (is_heap_stable_test(iff) && |
1783 | (loop_has_sfpts == -1 || loop_has_sfpts == 0)) { |
1784 | assert(!loop->is_loop_exit(iff), "both branches should be in the loop")do { if (!(!loop->is_loop_exit(iff))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1784, "assert(" "!loop->is_loop_exit(iff)" ") failed", "both branches should be in the loop" ); ::breakpoint(); } } while (0); |
1785 | if (loop_has_sfpts == -1) { |
1786 | for(uint i = 0; i < loop->_body.size(); i++) { |
1787 | Node *m = loop->_body[i]; |
1788 | if (m->is_SafePoint() && !m->is_CallLeaf()) { |
1789 | loop_has_sfpts = 1; |
1790 | break; |
1791 | } |
1792 | } |
1793 | if (loop_has_sfpts == -1) { |
1794 | loop_has_sfpts = 0; |
1795 | } |
1796 | } |
1797 | if (!loop_has_sfpts) { |
1798 | unswitch_iff = iff; |
1799 | } |
1800 | } |
1801 | } |
1802 | } |
1803 | } |
1804 | } |
1805 | n = n_dom; |
1806 | } |
1807 | return unswitch_iff; |
1808 | } |
1809 | |
1810 | |
1811 | void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, Node_Stack &stack, Node_List &old_new, PhaseIdealLoop* phase) { |
1812 | Node_List heap_stable_tests; |
1813 | stack.push(phase->C->start(), 0); |
1814 | do { |
1815 | Node* n = stack.node(); |
1816 | uint i = stack.index(); |
1817 | |
1818 | if (i < n->outcnt()) { |
1819 | Node* u = n->raw_out(i); |
1820 | stack.set_index(i+1); |
1821 | if (!visited.test_set(u->_idx)) { |
1822 | stack.push(u, 0); |
1823 | } |
1824 | } else { |
1825 | stack.pop(); |
1826 | if (n->is_If() && is_heap_stable_test(n)) { |
1827 | heap_stable_tests.push(n); |
1828 | } |
1829 | } |
1830 | } while (stack.size() > 0); |
1831 | |
1832 | for (uint i = 0; i < heap_stable_tests.size(); i++) { |
1833 | Node* n = heap_stable_tests.at(i); |
1834 | assert(is_heap_stable_test(n), "only evacuation test")do { if (!(is_heap_stable_test(n))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1834, "assert(" "is_heap_stable_test(n)" ") failed", "only evacuation test" ); ::breakpoint(); } } while (0); |
1835 | merge_back_to_back_tests(n, phase); |
1836 | } |
1837 | |
1838 | if (!phase->C->major_progress()) { |
1839 | VectorSet seen; |
1840 | for (uint i = 0; i < heap_stable_tests.size(); i++) { |
1841 | Node* n = heap_stable_tests.at(i); |
1842 | IdealLoopTree* loop = phase->get_loop(n); |
1843 | if (loop != phase->ltree_root() && |
1844 | loop->_child == NULL__null && |
1845 | !loop->_irreducible) { |
1846 | Node* head = loop->_head; |
1847 | if (head->is_Loop() && |
1848 | (!head->is_CountedLoop() || head->as_CountedLoop()->is_main_loop() || head->as_CountedLoop()->is_normal_loop()) && |
1849 | !seen.test_set(head->_idx)) { |
1850 | IfNode* iff = find_unswitching_candidate(loop, phase); |
1851 | if (iff != NULL__null) { |
1852 | Node* bol = iff->in(1); |
1853 | if (head->as_Loop()->is_strip_mined()) { |
1854 | head->as_Loop()->verify_strip_mined(0); |
1855 | } |
1856 | move_gc_state_test_out_of_loop(iff, phase); |
1857 | |
1858 | AutoNodeBudget node_budget(phase); |
1859 | |
1860 | if (loop->policy_unswitching(phase)) { |
1861 | if (head->as_Loop()->is_strip_mined()) { |
1862 | OuterStripMinedLoopNode* outer = head->as_CountedLoop()->outer_loop(); |
1863 | hide_strip_mined_loop(outer, head->as_CountedLoop(), phase); |
1864 | } |
1865 | phase->do_unswitching(loop, old_new); |
1866 | } else { |
1867 | // Not proceeding with unswitching. Move load back in |
1868 | // the loop. |
1869 | phase->igvn().replace_input_of(iff, 1, bol); |
1870 | } |
1871 | } |
1872 | } |
1873 | } |
1874 | } |
1875 | } |
1876 | } |
1877 | |
1878 | ShenandoahIUBarrierNode::ShenandoahIUBarrierNode(Node* val) : Node(NULL__null, val) { |
1879 | ShenandoahBarrierSetC2::bsc2()->state()->add_iu_barrier(this); |
1880 | } |
1881 | |
1882 | const Type* ShenandoahIUBarrierNode::bottom_type() const { |
1883 | if (in(1) == NULL__null || in(1)->is_top()) { |
1884 | return Type::TOP; |
1885 | } |
1886 | const Type* t = in(1)->bottom_type(); |
1887 | if (t == TypePtr::NULL_PTR) { |
1888 | return t; |
1889 | } |
1890 | return t->is_oopptr(); |
1891 | } |
1892 | |
1893 | const Type* ShenandoahIUBarrierNode::Value(PhaseGVN* phase) const { |
1894 | if (in(1) == NULL__null) { |
1895 | return Type::TOP; |
1896 | } |
1897 | const Type* t = phase->type(in(1)); |
1898 | if (t == Type::TOP) { |
1899 | return Type::TOP; |
1900 | } |
1901 | if (t == TypePtr::NULL_PTR) { |
1902 | return t; |
1903 | } |
1904 | return t->is_oopptr(); |
1905 | } |
1906 | |
1907 | int ShenandoahIUBarrierNode::needed(Node* n) { |
1908 | if (n == NULL__null || |
1909 | n->is_Allocate() || |
1910 | n->Opcode() == Op_ShenandoahIUBarrier || |
1911 | n->bottom_type() == TypePtr::NULL_PTR || |
1912 | (n->bottom_type()->make_oopptr() != NULL__null && n->bottom_type()->make_oopptr()->const_oop() != NULL__null)) { |
1913 | return NotNeeded; |
1914 | } |
1915 | if (n->is_Phi() || |
1916 | n->is_CMove()) { |
1917 | return MaybeNeeded; |
1918 | } |
1919 | return Needed; |
1920 | } |
1921 | |
1922 | Node* ShenandoahIUBarrierNode::next(Node* n) { |
1923 | for (;;) { |
1924 | if (n == NULL__null) { |
1925 | return n; |
1926 | } else if (n->bottom_type() == TypePtr::NULL_PTR) { |
1927 | return n; |
1928 | } else if (n->bottom_type()->make_oopptr() != NULL__null && n->bottom_type()->make_oopptr()->const_oop() != NULL__null) { |
1929 | return n; |
1930 | } else if (n->is_ConstraintCast() || |
1931 | n->Opcode() == Op_DecodeN || |
1932 | n->Opcode() == Op_EncodeP) { |
1933 | n = n->in(1); |
1934 | } else if (n->is_Proj()) { |
1935 | n = n->in(0); |
1936 | } else { |
1937 | return n; |
1938 | } |
1939 | } |
1940 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1940); ::breakpoint(); } while (0); |
1941 | return NULL__null; |
1942 | } |
1943 | |
1944 | Node* ShenandoahIUBarrierNode::Identity(PhaseGVN* phase) { |
1945 | PhaseIterGVN* igvn = phase->is_IterGVN(); |
1946 | |
1947 | Node* n = next(in(1)); |
1948 | |
1949 | int cont = needed(n); |
1950 | |
1951 | if (cont == NotNeeded) { |
1952 | return in(1); |
1953 | } else if (cont == MaybeNeeded) { |
1954 | if (igvn == NULL__null) { |
1955 | phase->record_for_igvn(this); |
1956 | return this; |
1957 | } else { |
1958 | ResourceMark rm; |
1959 | Unique_Node_List wq; |
1960 | uint wq_i = 0; |
1961 | |
1962 | for (;;) { |
1963 | if (n->is_Phi()) { |
1964 | for (uint i = 1; i < n->req(); i++) { |
1965 | Node* m = n->in(i); |
1966 | if (m != NULL__null) { |
1967 | wq.push(m); |
1968 | } |
1969 | } |
1970 | } else { |
1971 | assert(n->is_CMove(), "nothing else here")do { if (!(n->is_CMove())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 1971, "assert(" "n->is_CMove()" ") failed", "nothing else here" ); ::breakpoint(); } } while (0); |
1972 | Node* m = n->in(CMoveNode::IfFalse); |
1973 | wq.push(m); |
1974 | m = n->in(CMoveNode::IfTrue); |
1975 | wq.push(m); |
1976 | } |
1977 | Node* orig_n = NULL__null; |
1978 | do { |
1979 | if (wq_i >= wq.size()) { |
1980 | return in(1); |
1981 | } |
1982 | n = wq.at(wq_i); |
1983 | wq_i++; |
1984 | orig_n = n; |
1985 | n = next(n); |
1986 | cont = needed(n); |
1987 | if (cont == Needed) { |
1988 | return this; |
1989 | } |
1990 | } while (cont != MaybeNeeded || (orig_n != n && wq.member(n))); |
1991 | } |
1992 | } |
1993 | } |
1994 | |
1995 | return this; |
1996 | } |
1997 | |
1998 | #ifdef ASSERT1 |
1999 | static bool has_never_branch(Node* root) { |
2000 | for (uint i = 1; i < root->req(); i++) { |
2001 | Node* in = root->in(i); |
2002 | if (in != NULL__null && in->Opcode() == Op_Halt && in->in(0)->is_Proj() && in->in(0)->in(0)->Opcode() == Op_NeverBranch) { |
2003 | return true; |
2004 | } |
2005 | } |
2006 | return false; |
2007 | } |
2008 | #endif |
2009 | |
2010 | void MemoryGraphFixer::collect_memory_nodes() { |
2011 | Node_Stack stack(0); |
2012 | VectorSet visited; |
2013 | Node_List regions; |
2014 | |
2015 | // Walk the raw memory graph and create a mapping from CFG node to |
2016 | // memory node. Exclude phis for now. |
2017 | stack.push(_phase->C->root(), 1); |
2018 | do { |
2019 | Node* n = stack.node(); |
2020 | int opc = n->Opcode(); |
2021 | uint i = stack.index(); |
2022 | if (i < n->req()) { |
2023 | Node* mem = NULL__null; |
2024 | if (opc == Op_Root) { |
2025 | Node* in = n->in(i); |
2026 | int in_opc = in->Opcode(); |
2027 | if (in_opc == Op_Return || in_opc == Op_Rethrow) { |
2028 | mem = in->in(TypeFunc::Memory); |
2029 | } else if (in_opc == Op_Halt) { |
2030 | if (in->in(0)->is_Region()) { |
2031 | Node* r = in->in(0); |
2032 | for (uint j = 1; j < r->req(); j++) { |
2033 | assert(r->in(j)->Opcode() != Op_NeverBranch, "")do { if (!(r->in(j)->Opcode() != Op_NeverBranch)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2033, "assert(" "r->in(j)->Opcode() != Op_NeverBranch" ") failed", ""); ::breakpoint(); } } while (0); |
2034 | } |
2035 | } else { |
2036 | Node* proj = in->in(0); |
2037 | assert(proj->is_Proj(), "")do { if (!(proj->is_Proj())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2037, "assert(" "proj->is_Proj()" ") failed", ""); ::breakpoint (); } } while (0); |
2038 | Node* in = proj->in(0); |
2039 | assert(in->is_CallStaticJava() || in->Opcode() == Op_NeverBranch || in->Opcode() == Op_Catch || proj->is_IfProj(), "")do { if (!(in->is_CallStaticJava() || in->Opcode() == Op_NeverBranch || in->Opcode() == Op_Catch || proj->is_IfProj())) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2039, "assert(" "in->is_CallStaticJava() || in->Opcode() == Op_NeverBranch || in->Opcode() == Op_Catch || proj->is_IfProj()" ") failed", ""); ::breakpoint(); } } while (0); |
2040 | if (in->is_CallStaticJava()) { |
2041 | mem = in->in(TypeFunc::Memory); |
2042 | } else if (in->Opcode() == Op_Catch) { |
2043 | Node* call = in->in(0)->in(0); |
2044 | assert(call->is_Call(), "")do { if (!(call->is_Call())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2044, "assert(" "call->is_Call()" ") failed", ""); ::breakpoint (); } } while (0); |
2045 | mem = call->in(TypeFunc::Memory); |
2046 | } else if (in->Opcode() == Op_NeverBranch) { |
2047 | mem = collect_memory_for_infinite_loop(in); |
2048 | } |
2049 | } |
2050 | } else { |
2051 | #ifdef ASSERT1 |
2052 | n->dump(); |
2053 | in->dump(); |
2054 | #endif |
2055 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2055); ::breakpoint(); } while (0); |
2056 | } |
2057 | } else { |
2058 | assert(n->is_Phi() && n->bottom_type() == Type::MEMORY, "")do { if (!(n->is_Phi() && n->bottom_type() == Type ::MEMORY)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2058, "assert(" "n->is_Phi() && n->bottom_type() == Type::MEMORY" ") failed", ""); ::breakpoint(); } } while (0); |
2059 | assert(n->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(n->adr_type()) == _alias, "")do { if (!(n->adr_type() == TypePtr::BOTTOM || _phase-> C->get_alias_index(n->adr_type()) == _alias)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2059, "assert(" "n->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(n->adr_type()) == _alias" ") failed", ""); ::breakpoint(); } } while (0); |
2060 | mem = n->in(i); |
2061 | } |
2062 | i++; |
2063 | stack.set_index(i); |
2064 | if (mem == NULL__null) { |
2065 | continue; |
2066 | } |
2067 | for (;;) { |
2068 | if (visited.test_set(mem->_idx) || mem->is_Start()) { |
2069 | break; |
2070 | } |
2071 | if (mem->is_Phi()) { |
2072 | stack.push(mem, 2); |
2073 | mem = mem->in(1); |
2074 | } else if (mem->is_Proj()) { |
2075 | stack.push(mem, mem->req()); |
2076 | mem = mem->in(0); |
2077 | } else if (mem->is_SafePoint() || mem->is_MemBar()) { |
2078 | mem = mem->in(TypeFunc::Memory); |
2079 | } else if (mem->is_MergeMem()) { |
2080 | MergeMemNode* mm = mem->as_MergeMem(); |
2081 | mem = mm->memory_at(_alias); |
2082 | } else if (mem->is_Store() || mem->is_LoadStore() || mem->is_ClearArray()) { |
2083 | assert(_alias == Compile::AliasIdxRaw, "")do { if (!(_alias == Compile::AliasIdxRaw)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2083, "assert(" "_alias == Compile::AliasIdxRaw" ") failed" , ""); ::breakpoint(); } } while (0); |
2084 | stack.push(mem, mem->req()); |
2085 | mem = mem->in(MemNode::Memory); |
2086 | } else { |
2087 | #ifdef ASSERT1 |
2088 | mem->dump(); |
2089 | #endif |
2090 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2090); ::breakpoint(); } while (0); |
2091 | } |
2092 | } |
2093 | } else { |
2094 | if (n->is_Phi()) { |
2095 | // Nothing |
2096 | } else if (!n->is_Root()) { |
2097 | Node* c = get_ctrl(n); |
2098 | _memory_nodes.map(c->_idx, n); |
2099 | } |
2100 | stack.pop(); |
2101 | } |
2102 | } while(stack.is_nonempty()); |
2103 | |
2104 | // Iterate over CFG nodes in rpo and propagate memory state to |
2105 | // compute memory state at regions, creating new phis if needed. |
2106 | Node_List rpo_list; |
2107 | visited.clear(); |
2108 | _phase->rpo(_phase->C->root(), stack, visited, rpo_list); |
2109 | Node* root = rpo_list.pop(); |
2110 | assert(root == _phase->C->root(), "")do { if (!(root == _phase->C->root())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2110, "assert(" "root == _phase->C->root()" ") failed" , ""); ::breakpoint(); } } while (0); |
2111 | |
2112 | const bool trace = false; |
2113 | #ifdef ASSERT1 |
2114 | if (trace) { |
2115 | for (int i = rpo_list.size() - 1; i >= 0; i--) { |
2116 | Node* c = rpo_list.at(i); |
2117 | if (_memory_nodes[c->_idx] != NULL__null) { |
2118 | tty->print("X %d", c->_idx); _memory_nodes[c->_idx]->dump(); |
2119 | } |
2120 | } |
2121 | } |
2122 | #endif |
2123 | uint last = _phase->C->unique(); |
2124 | |
2125 | #ifdef ASSERT1 |
2126 | uint16_t max_depth = 0; |
2127 | for (LoopTreeIterator iter(_phase->ltree_root()); !iter.done(); iter.next()) { |
2128 | IdealLoopTree* lpt = iter.current(); |
2129 | max_depth = MAX2(max_depth, lpt->_nest); |
2130 | } |
2131 | #endif |
2132 | |
2133 | bool progress = true; |
2134 | int iteration = 0; |
2135 | Node_List dead_phis; |
2136 | while (progress) { |
2137 | progress = false; |
2138 | iteration++; |
2139 | assert(iteration <= 2+max_depth || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "")do { if (!(iteration <= 2+max_depth || _phase->C->has_irreducible_loop () || has_never_branch(_phase->C->root()))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2139, "assert(" "iteration <= 2+max_depth || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root())" ") failed", ""); ::breakpoint(); } } while (0); |
2140 | if (trace) { tty->print_cr("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); } |
2141 | |
2142 | for (int i = rpo_list.size() - 1; i >= 0; i--) { |
2143 | Node* c = rpo_list.at(i); |
2144 | |
2145 | Node* prev_mem = _memory_nodes[c->_idx]; |
2146 | if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) { |
2147 | Node* prev_region = regions[c->_idx]; |
2148 | Node* unique = NULL__null; |
2149 | for (uint j = 1; j < c->req() && unique != NodeSentinel(Node*)-1; j++) { |
2150 | Node* m = _memory_nodes[c->in(j)->_idx]; |
2151 | assert(m != NULL || (c->is_Loop() && j == LoopNode::LoopBackControl && iteration == 1) || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "expect memory state")do { if (!(m != __null || (c->is_Loop() && j == LoopNode ::LoopBackControl && iteration == 1) || _phase->C-> has_irreducible_loop() || has_never_branch(_phase->C->root ()))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2151, "assert(" "m != __null || (c->is_Loop() && j == LoopNode::LoopBackControl && iteration == 1) || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root())" ") failed", "expect memory state"); ::breakpoint(); } } while (0); |
2152 | if (m != NULL__null) { |
2153 | if (m == prev_region && ((c->is_Loop() && j == LoopNode::LoopBackControl) || (prev_region->is_Phi() && prev_region->in(0) == c))) { |
2154 | assert(c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "")do { if (!(c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop() || has_never_branch (_phase->C->root()))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2154, "assert(" "c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root())" ") failed", ""); ::breakpoint(); } } while (0); |
2155 | // continue |
2156 | } else if (unique == NULL__null) { |
2157 | unique = m; |
2158 | } else if (m == unique) { |
2159 | // continue |
2160 | } else { |
2161 | unique = NodeSentinel(Node*)-1; |
2162 | } |
2163 | } |
2164 | } |
2165 | assert(unique != NULL, "empty phi???")do { if (!(unique != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2165, "assert(" "unique != __null" ") failed", "empty phi???" ); ::breakpoint(); } } while (0); |
2166 | if (unique != NodeSentinel(Node*)-1) { |
2167 | if (prev_region != NULL__null && prev_region->is_Phi() && prev_region->in(0) == c) { |
2168 | dead_phis.push(prev_region); |
2169 | } |
2170 | regions.map(c->_idx, unique); |
2171 | } else { |
2172 | Node* phi = NULL__null; |
2173 | if (prev_region != NULL__null && prev_region->is_Phi() && prev_region->in(0) == c && prev_region->_idx >= last) { |
2174 | phi = prev_region; |
2175 | for (uint k = 1; k < c->req(); k++) { |
2176 | Node* m = _memory_nodes[c->in(k)->_idx]; |
2177 | assert(m != NULL, "expect memory state")do { if (!(m != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2177, "assert(" "m != __null" ") failed", "expect memory state" ); ::breakpoint(); } } while (0); |
2178 | phi->set_req(k, m); |
2179 | } |
2180 | } else { |
2181 | for (DUIterator_Fast jmax, j = c->fast_outs(jmax); j < jmax && phi == NULL__null; j++) { |
2182 | Node* u = c->fast_out(j); |
2183 | if (u->is_Phi() && u->bottom_type() == Type::MEMORY && |
2184 | (u->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(u->adr_type()) == _alias)) { |
2185 | phi = u; |
2186 | for (uint k = 1; k < c->req() && phi != NULL__null; k++) { |
2187 | Node* m = _memory_nodes[c->in(k)->_idx]; |
2188 | assert(m != NULL, "expect memory state")do { if (!(m != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2188, "assert(" "m != __null" ") failed", "expect memory state" ); ::breakpoint(); } } while (0); |
2189 | if (u->in(k) != m) { |
2190 | phi = NodeSentinel(Node*)-1; |
2191 | } |
2192 | } |
2193 | } |
2194 | } |
2195 | if (phi == NodeSentinel(Node*)-1) { |
2196 | phi = new PhiNode(c, Type::MEMORY, _phase->C->get_adr_type(_alias)); |
2197 | for (uint k = 1; k < c->req(); k++) { |
2198 | Node* m = _memory_nodes[c->in(k)->_idx]; |
2199 | assert(m != NULL, "expect memory state")do { if (!(m != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2199, "assert(" "m != __null" ") failed", "expect memory state" ); ::breakpoint(); } } while (0); |
2200 | phi->init_req(k, m); |
2201 | } |
2202 | } |
2203 | } |
2204 | if (phi != NULL__null) { |
2205 | regions.map(c->_idx, phi); |
2206 | } else { |
2207 | assert(c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state")do { if (!(c->unique_ctrl_out()->Opcode() == Op_Halt)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2207, "assert(" "c->unique_ctrl_out()->Opcode() == Op_Halt" ") failed", "expected memory state"); ::breakpoint(); } } while (0); |
2208 | } |
2209 | } |
2210 | Node* current_region = regions[c->_idx]; |
2211 | if (current_region != prev_region) { |
2212 | progress = true; |
2213 | if (prev_region == prev_mem) { |
2214 | _memory_nodes.map(c->_idx, current_region); |
2215 | } |
2216 | } |
2217 | } else if (prev_mem == NULL__null || prev_mem->is_Phi() || ctrl_or_self(prev_mem) != c) { |
2218 | Node* m = _memory_nodes[_phase->idom(c)->_idx]; |
2219 | assert(m != NULL || c->Opcode() == Op_Halt, "expect memory state")do { if (!(m != __null || c->Opcode() == Op_Halt)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2219, "assert(" "m != __null || c->Opcode() == Op_Halt" ") failed" , "expect memory state"); ::breakpoint(); } } while (0); |
2220 | if (m != prev_mem) { |
2221 | _memory_nodes.map(c->_idx, m); |
2222 | progress = true; |
2223 | } |
2224 | } |
2225 | #ifdef ASSERT1 |
2226 | if (trace) { tty->print("X %d", c->_idx); _memory_nodes[c->_idx]->dump(); } |
2227 | #endif |
2228 | } |
2229 | } |
2230 | |
2231 | // Replace existing phi with computed memory state for that region |
2232 | // if different (could be a new phi or a dominating memory node if |
2233 | // that phi was found to be useless). |
2234 | while (dead_phis.size() > 0) { |
2235 | Node* n = dead_phis.pop(); |
2236 | n->replace_by(_phase->C->top()); |
2237 | n->destruct(&_phase->igvn()); |
2238 | } |
2239 | for (int i = rpo_list.size() - 1; i >= 0; i--) { |
2240 | Node* c = rpo_list.at(i); |
2241 | if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) { |
2242 | Node* n = regions[c->_idx]; |
2243 | assert(n != NULL || c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state")do { if (!(n != __null || c->unique_ctrl_out()->Opcode( ) == Op_Halt)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2243, "assert(" "n != __null || c->unique_ctrl_out()->Opcode() == Op_Halt" ") failed", "expected memory state"); ::breakpoint(); } } while (0); |
2244 | if (n != NULL__null && n->is_Phi() && n->_idx >= last && n->in(0) == c) { |
2245 | _phase->register_new_node(n, c); |
2246 | } |
2247 | } |
2248 | } |
2249 | for (int i = rpo_list.size() - 1; i >= 0; i--) { |
2250 | Node* c = rpo_list.at(i); |
2251 | if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) { |
2252 | Node* n = regions[c->_idx]; |
2253 | assert(n != NULL || c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state")do { if (!(n != __null || c->unique_ctrl_out()->Opcode( ) == Op_Halt)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2253, "assert(" "n != __null || c->unique_ctrl_out()->Opcode() == Op_Halt" ") failed", "expected memory state"); ::breakpoint(); } } while (0); |
2254 | for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax; i++) { |
2255 | Node* u = c->fast_out(i); |
2256 | if (u->is_Phi() && u->bottom_type() == Type::MEMORY && |
2257 | u != n) { |
2258 | assert(c->unique_ctrl_out()->Opcode() != Op_Halt, "expected memory state")do { if (!(c->unique_ctrl_out()->Opcode() != Op_Halt)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2258, "assert(" "c->unique_ctrl_out()->Opcode() != Op_Halt" ") failed", "expected memory state"); ::breakpoint(); } } while (0); |
2259 | if (u->adr_type() == TypePtr::BOTTOM) { |
2260 | fix_memory_uses(u, n, n, c); |
2261 | } else if (_phase->C->get_alias_index(u->adr_type()) == _alias) { |
2262 | _phase->lazy_replace(u, n); |
2263 | --i; --imax; |
2264 | } |
2265 | } |
2266 | } |
2267 | } |
2268 | } |
2269 | } |
2270 | |
2271 | Node* MemoryGraphFixer::collect_memory_for_infinite_loop(const Node* in) { |
2272 | Node* mem = NULL__null; |
2273 | Node* head = in->in(0); |
2274 | assert(head->is_Region(), "unexpected infinite loop graph shape")do { if (!(head->is_Region())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2274, "assert(" "head->is_Region()" ") failed", "unexpected infinite loop graph shape" ); ::breakpoint(); } } while (0); |
2275 | |
2276 | Node* phi_mem = NULL__null; |
2277 | for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) { |
2278 | Node* u = head->fast_out(j); |
2279 | if (u->is_Phi() && u->bottom_type() == Type::MEMORY) { |
2280 | if (_phase->C->get_alias_index(u->adr_type()) == _alias) { |
2281 | assert(phi_mem == NULL || phi_mem->adr_type() == TypePtr::BOTTOM, "")do { if (!(phi_mem == __null || phi_mem->adr_type() == TypePtr ::BOTTOM)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2281, "assert(" "phi_mem == __null || phi_mem->adr_type() == TypePtr::BOTTOM" ") failed", ""); ::breakpoint(); } } while (0); |
2282 | phi_mem = u; |
2283 | } else if (u->adr_type() == TypePtr::BOTTOM) { |
2284 | assert(phi_mem == NULL || _phase->C->get_alias_index(phi_mem->adr_type()) == _alias, "")do { if (!(phi_mem == __null || _phase->C->get_alias_index (phi_mem->adr_type()) == _alias)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2284, "assert(" "phi_mem == __null || _phase->C->get_alias_index(phi_mem->adr_type()) == _alias" ") failed", ""); ::breakpoint(); } } while (0); |
2285 | if (phi_mem == NULL__null) { |
2286 | phi_mem = u; |
2287 | } |
2288 | } |
2289 | } |
2290 | } |
2291 | if (phi_mem == NULL__null) { |
2292 | ResourceMark rm; |
2293 | Node_Stack stack(0); |
2294 | stack.push(head, 1); |
2295 | do { |
2296 | Node* n = stack.node(); |
2297 | uint i = stack.index(); |
2298 | if (i >= n->req()) { |
2299 | stack.pop(); |
2300 | } else { |
2301 | stack.set_index(i + 1); |
2302 | Node* c = n->in(i); |
2303 | assert(c != head, "should have found a safepoint on the way")do { if (!(c != head)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2303, "assert(" "c != head" ") failed", "should have found a safepoint on the way" ); ::breakpoint(); } } while (0); |
2304 | if (stack.size() != 1 || _phase->is_dominator(head, c)) { |
2305 | for (;;) { |
2306 | if (c->is_Region()) { |
2307 | stack.push(c, 1); |
2308 | break; |
2309 | } else if (c->is_SafePoint() && !c->is_CallLeaf()) { |
2310 | Node* m = c->in(TypeFunc::Memory); |
2311 | if (m->is_MergeMem()) { |
2312 | m = m->as_MergeMem()->memory_at(_alias); |
2313 | } |
2314 | assert(mem == NULL || mem == m, "several memory states")do { if (!(mem == __null || mem == m)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2314, "assert(" "mem == __null || mem == m" ") failed", "several memory states" ); ::breakpoint(); } } while (0); |
2315 | mem = m; |
2316 | break; |
2317 | } else { |
2318 | assert(c != c->in(0), "")do { if (!(c != c->in(0))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2318, "assert(" "c != c->in(0)" ") failed", ""); ::breakpoint (); } } while (0); |
2319 | c = c->in(0); |
2320 | } |
2321 | } |
2322 | } |
2323 | } |
2324 | } while (stack.size() > 0); |
2325 | assert(mem != NULL, "should have found safepoint")do { if (!(mem != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2325, "assert(" "mem != __null" ") failed", "should have found safepoint" ); ::breakpoint(); } } while (0); |
2326 | } else { |
2327 | mem = phi_mem; |
2328 | } |
2329 | return mem; |
2330 | } |
2331 | |
2332 | Node* MemoryGraphFixer::get_ctrl(Node* n) const { |
2333 | Node* c = _phase->get_ctrl(n); |
2334 | if (n->is_Proj() && n->in(0) != NULL__null && n->in(0)->is_Call()) { |
2335 | assert(c == n->in(0), "")do { if (!(c == n->in(0))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2335, "assert(" "c == n->in(0)" ") failed", ""); ::breakpoint (); } } while (0); |
2336 | CallNode* call = c->as_Call(); |
2337 | CallProjections projs; |
2338 | call->extract_projections(&projs, true, false); |
2339 | if (projs.catchall_memproj != NULL__null) { |
2340 | if (projs.fallthrough_memproj == n) { |
2341 | c = projs.fallthrough_catchproj; |
2342 | } else { |
2343 | assert(projs.catchall_memproj == n, "")do { if (!(projs.catchall_memproj == n)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2343, "assert(" "projs.catchall_memproj == n" ") failed", "" ); ::breakpoint(); } } while (0); |
2344 | c = projs.catchall_catchproj; |
2345 | } |
2346 | } |
2347 | } |
2348 | return c; |
2349 | } |
2350 | |
2351 | Node* MemoryGraphFixer::ctrl_or_self(Node* n) const { |
2352 | if (_phase->has_ctrl(n)) |
2353 | return get_ctrl(n); |
2354 | else { |
2355 | assert (n->is_CFG(), "must be a CFG node")do { if (!(n->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2355, "assert(" "n->is_CFG()" ") failed", "must be a CFG node" ); ::breakpoint(); } } while (0); |
2356 | return n; |
2357 | } |
2358 | } |
2359 | |
2360 | bool MemoryGraphFixer::mem_is_valid(Node* m, Node* c) const { |
2361 | return m != NULL__null && get_ctrl(m) == c; |
2362 | } |
2363 | |
2364 | Node* MemoryGraphFixer::find_mem(Node* ctrl, Node* n) const { |
2365 | assert(n == NULL || _phase->ctrl_or_self(n) == ctrl, "")do { if (!(n == __null || _phase->ctrl_or_self(n) == ctrl) ) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2365, "assert(" "n == __null || _phase->ctrl_or_self(n) == ctrl" ") failed", ""); ::breakpoint(); } } while (0); |
2366 | assert(!ctrl->is_Call() || ctrl == n, "projection expected")do { if (!(!ctrl->is_Call() || ctrl == n)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2366, "assert(" "!ctrl->is_Call() || ctrl == n" ") failed" , "projection expected"); ::breakpoint(); } } while (0); |
2367 | #ifdef ASSERT1 |
2368 | if ((ctrl->is_Proj() && ctrl->in(0)->is_Call()) || |
2369 | (ctrl->is_Catch() && ctrl->in(0)->in(0)->is_Call())) { |
2370 | CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_Call() : ctrl->in(0)->in(0)->as_Call(); |
2371 | int mems = 0; |
2372 | for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) { |
2373 | Node* u = call->fast_out(i); |
2374 | if (u->bottom_type() == Type::MEMORY) { |
2375 | mems++; |
2376 | } |
2377 | } |
2378 | assert(mems <= 1, "No node right after call if multiple mem projections")do { if (!(mems <= 1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2378, "assert(" "mems <= 1" ") failed", "No node right after call if multiple mem projections" ); ::breakpoint(); } } while (0); |
2379 | } |
2380 | #endif |
2381 | Node* mem = _memory_nodes[ctrl->_idx]; |
2382 | Node* c = ctrl; |
2383 | while (!mem_is_valid(mem, c) && |
2384 | (!c->is_CatchProj() || mem == NULL__null || c->in(0)->in(0)->in(0) != get_ctrl(mem))) { |
2385 | c = _phase->idom(c); |
2386 | mem = _memory_nodes[c->_idx]; |
2387 | } |
2388 | if (n != NULL__null && mem_is_valid(mem, c)) { |
2389 | while (!ShenandoahBarrierC2Support::is_dominator_same_ctrl(c, mem, n, _phase) && _phase->ctrl_or_self(mem) == ctrl) { |
2390 | mem = next_mem(mem, _alias); |
2391 | } |
2392 | if (mem->is_MergeMem()) { |
2393 | mem = mem->as_MergeMem()->memory_at(_alias); |
2394 | } |
2395 | if (!mem_is_valid(mem, c)) { |
2396 | do { |
2397 | c = _phase->idom(c); |
2398 | mem = _memory_nodes[c->_idx]; |
2399 | } while (!mem_is_valid(mem, c) && |
2400 | (!c->is_CatchProj() || mem == NULL__null || c->in(0)->in(0)->in(0) != get_ctrl(mem))); |
2401 | } |
2402 | } |
2403 | assert(mem->bottom_type() == Type::MEMORY, "")do { if (!(mem->bottom_type() == Type::MEMORY)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2403, "assert(" "mem->bottom_type() == Type::MEMORY" ") failed" , ""); ::breakpoint(); } } while (0); |
2404 | return mem; |
2405 | } |
2406 | |
2407 | bool MemoryGraphFixer::has_mem_phi(Node* region) const { |
2408 | for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { |
2409 | Node* use = region->fast_out(i); |
2410 | if (use->is_Phi() && use->bottom_type() == Type::MEMORY && |
2411 | (_phase->C->get_alias_index(use->adr_type()) == _alias)) { |
2412 | return true; |
2413 | } |
2414 | } |
2415 | return false; |
2416 | } |
2417 | |
2418 | void MemoryGraphFixer::fix_mem(Node* ctrl, Node* new_ctrl, Node* mem, Node* mem_for_ctrl, Node* new_mem, Unique_Node_List& uses) { |
2419 | assert(_phase->ctrl_or_self(new_mem) == new_ctrl, "")do { if (!(_phase->ctrl_or_self(new_mem) == new_ctrl)) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2419, "assert(" "_phase->ctrl_or_self(new_mem) == new_ctrl" ") failed", ""); ::breakpoint(); } } while (0); |
2420 | const bool trace = false; |
2421 | DEBUG_ONLY(if (trace) { tty->print("ZZZ control is"); ctrl->dump(); })if (trace) { tty->print("ZZZ control is"); ctrl->dump() ; }; |
2422 | DEBUG_ONLY(if (trace) { tty->print("ZZZ mem is"); mem->dump(); })if (trace) { tty->print("ZZZ mem is"); mem->dump(); }; |
2423 | GrowableArray<Node*> phis; |
2424 | if (mem_for_ctrl != mem) { |
2425 | Node* old = mem_for_ctrl; |
2426 | Node* prev = NULL__null; |
2427 | while (old != mem) { |
2428 | prev = old; |
2429 | if (old->is_Store() || old->is_ClearArray() || old->is_LoadStore()) { |
2430 | assert(_alias == Compile::AliasIdxRaw, "")do { if (!(_alias == Compile::AliasIdxRaw)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2430, "assert(" "_alias == Compile::AliasIdxRaw" ") failed" , ""); ::breakpoint(); } } while (0); |
2431 | old = old->in(MemNode::Memory); |
2432 | } else if (old->Opcode() == Op_SCMemProj) { |
2433 | assert(_alias == Compile::AliasIdxRaw, "")do { if (!(_alias == Compile::AliasIdxRaw)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2433, "assert(" "_alias == Compile::AliasIdxRaw" ") failed" , ""); ::breakpoint(); } } while (0); |
2434 | old = old->in(0); |
2435 | } else { |
2436 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2436); ::breakpoint(); } while (0); |
2437 | } |
2438 | } |
2439 | assert(prev != NULL, "")do { if (!(prev != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2439, "assert(" "prev != __null" ") failed", ""); ::breakpoint (); } } while (0); |
2440 | if (new_ctrl != ctrl) { |
2441 | _memory_nodes.map(ctrl->_idx, mem); |
2442 | _memory_nodes.map(new_ctrl->_idx, mem_for_ctrl); |
2443 | } |
2444 | uint input = (uint)MemNode::Memory; |
2445 | _phase->igvn().replace_input_of(prev, input, new_mem); |
2446 | } else { |
2447 | uses.clear(); |
2448 | _memory_nodes.map(new_ctrl->_idx, new_mem); |
2449 | uses.push(new_ctrl); |
2450 | for(uint next = 0; next < uses.size(); next++ ) { |
2451 | Node *n = uses.at(next); |
2452 | assert(n->is_CFG(), "")do { if (!(n->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2452, "assert(" "n->is_CFG()" ") failed", ""); ::breakpoint (); } } while (0); |
2453 | DEBUG_ONLY(if (trace) { tty->print("ZZZ ctrl"); n->dump(); })if (trace) { tty->print("ZZZ ctrl"); n->dump(); }; |
2454 | for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { |
2455 | Node* u = n->fast_out(i); |
2456 | if (!u->is_Root() && u->is_CFG() && u != n) { |
2457 | Node* m = _memory_nodes[u->_idx]; |
2458 | if (u->is_Region() && (!u->is_OuterStripMinedLoop() || _include_lsm) && |
2459 | !has_mem_phi(u) && |
2460 | u->unique_ctrl_out()->Opcode() != Op_Halt) { |
2461 | DEBUG_ONLY(if (trace) { tty->print("ZZZ region"); u->dump(); })if (trace) { tty->print("ZZZ region"); u->dump(); }; |
2462 | DEBUG_ONLY(if (trace && m != NULL) { tty->print("ZZZ mem"); m->dump(); })if (trace && m != __null) { tty->print("ZZZ mem"); m->dump(); }; |
2463 | |
2464 | if (!mem_is_valid(m, u) || !m->is_Phi()) { |
2465 | bool push = true; |
2466 | bool create_phi = true; |
2467 | if (_phase->is_dominator(new_ctrl, u)) { |
2468 | create_phi = false; |
2469 | } |
2470 | if (create_phi) { |
2471 | Node* phi = new PhiNode(u, Type::MEMORY, _phase->C->get_adr_type(_alias)); |
2472 | _phase->register_new_node(phi, u); |
2473 | phis.push(phi); |
2474 | DEBUG_ONLY(if (trace) { tty->print("ZZZ new phi"); phi->dump(); })if (trace) { tty->print("ZZZ new phi"); phi->dump(); }; |
2475 | if (!mem_is_valid(m, u)) { |
2476 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting mem"); phi->dump(); })if (trace) { tty->print("ZZZ setting mem"); phi->dump() ; }; |
2477 | _memory_nodes.map(u->_idx, phi); |
2478 | } else { |
2479 | DEBUG_ONLY(if (trace) { tty->print("ZZZ NOT setting mem"); m->dump(); })if (trace) { tty->print("ZZZ NOT setting mem"); m->dump (); }; |
2480 | for (;;) { |
2481 | assert(m->is_Mem() || m->is_LoadStore() || m->is_Proj(), "")do { if (!(m->is_Mem() || m->is_LoadStore() || m->is_Proj ())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2481, "assert(" "m->is_Mem() || m->is_LoadStore() || m->is_Proj()" ") failed", ""); ::breakpoint(); } } while (0); |
2482 | Node* next = NULL__null; |
2483 | if (m->is_Proj()) { |
2484 | next = m->in(0); |
2485 | } else { |
2486 | assert(m->is_Mem() || m->is_LoadStore(), "")do { if (!(m->is_Mem() || m->is_LoadStore())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2486, "assert(" "m->is_Mem() || m->is_LoadStore()" ") failed" , ""); ::breakpoint(); } } while (0); |
2487 | assert(_alias == Compile::AliasIdxRaw, "")do { if (!(_alias == Compile::AliasIdxRaw)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2487, "assert(" "_alias == Compile::AliasIdxRaw" ") failed" , ""); ::breakpoint(); } } while (0); |
2488 | next = m->in(MemNode::Memory); |
2489 | } |
2490 | if (_phase->get_ctrl(next) != u) { |
2491 | break; |
2492 | } |
2493 | if (next->is_MergeMem()) { |
2494 | assert(_phase->get_ctrl(next->as_MergeMem()->memory_at(_alias)) != u, "")do { if (!(_phase->get_ctrl(next->as_MergeMem()->memory_at (_alias)) != u)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2494, "assert(" "_phase->get_ctrl(next->as_MergeMem()->memory_at(_alias)) != u" ") failed", ""); ::breakpoint(); } } while (0); |
2495 | break; |
2496 | } |
2497 | if (next->is_Phi()) { |
2498 | assert(next->adr_type() == TypePtr::BOTTOM && next->in(0) == u, "")do { if (!(next->adr_type() == TypePtr::BOTTOM && next ->in(0) == u)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2498, "assert(" "next->adr_type() == TypePtr::BOTTOM && next->in(0) == u" ") failed", ""); ::breakpoint(); } } while (0); |
2499 | break; |
2500 | } |
2501 | m = next; |
2502 | } |
2503 | |
2504 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting to phi"); m->dump(); })if (trace) { tty->print("ZZZ setting to phi"); m->dump( ); }; |
2505 | assert(m->is_Mem() || m->is_LoadStore(), "")do { if (!(m->is_Mem() || m->is_LoadStore())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2505, "assert(" "m->is_Mem() || m->is_LoadStore()" ") failed" , ""); ::breakpoint(); } } while (0); |
2506 | uint input = (uint)MemNode::Memory; |
2507 | _phase->igvn().replace_input_of(m, input, phi); |
2508 | push = false; |
2509 | } |
2510 | } else { |
2511 | DEBUG_ONLY(if (trace) { tty->print("ZZZ skipping region"); u->dump(); })if (trace) { tty->print("ZZZ skipping region"); u->dump (); }; |
2512 | } |
2513 | if (push) { |
2514 | uses.push(u); |
2515 | } |
2516 | } |
2517 | } else if (!mem_is_valid(m, u) && |
2518 | !(u->Opcode() == Op_CProj && u->in(0)->Opcode() == Op_NeverBranch && u->as_Proj()->_con == 1)) { |
2519 | uses.push(u); |
2520 | } |
2521 | } |
2522 | } |
2523 | } |
2524 | for (int i = 0; i < phis.length(); i++) { |
2525 | Node* n = phis.at(i); |
2526 | Node* r = n->in(0); |
2527 | DEBUG_ONLY(if (trace) { tty->print("ZZZ fixing new phi"); n->dump(); })if (trace) { tty->print("ZZZ fixing new phi"); n->dump( ); }; |
2528 | for (uint j = 1; j < n->req(); j++) { |
2529 | Node* m = find_mem(r->in(j), NULL__null); |
2530 | _phase->igvn().replace_input_of(n, j, m); |
2531 | DEBUG_ONLY(if (trace) { tty->print("ZZZ fixing new phi: %d", j); m->dump(); })if (trace) { tty->print("ZZZ fixing new phi: %d", j); m-> dump(); }; |
2532 | } |
2533 | } |
2534 | } |
2535 | uint last = _phase->C->unique(); |
2536 | MergeMemNode* mm = NULL__null; |
2537 | int alias = _alias; |
2538 | DEBUG_ONLY(if (trace) { tty->print("ZZZ raw mem is"); mem->dump(); })if (trace) { tty->print("ZZZ raw mem is"); mem->dump(); }; |
2539 | // Process loads first to not miss an anti-dependency: if the memory |
2540 | // edge of a store is updated before a load is processed then an |
2541 | // anti-dependency may be missed. |
2542 | for (DUIterator i = mem->outs(); mem->has_out(i); i++) { |
2543 | Node* u = mem->out(i); |
2544 | if (u->_idx < last && u->is_Load() && _phase->C->get_alias_index(u->adr_type()) == alias) { |
2545 | Node* m = find_mem(_phase->get_ctrl(u), u); |
2546 | if (m != mem) { |
2547 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); })if (trace) { tty->print("ZZZ setting memory of use"); u-> dump(); }; |
2548 | _phase->igvn().replace_input_of(u, MemNode::Memory, m); |
2549 | --i; |
2550 | } |
2551 | } |
2552 | } |
2553 | for (DUIterator i = mem->outs(); mem->has_out(i); i++) { |
2554 | Node* u = mem->out(i); |
2555 | if (u->_idx < last) { |
2556 | if (u->is_Mem()) { |
2557 | if (_phase->C->get_alias_index(u->adr_type()) == alias) { |
2558 | Node* m = find_mem(_phase->get_ctrl(u), u); |
2559 | if (m != mem) { |
2560 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); })if (trace) { tty->print("ZZZ setting memory of use"); u-> dump(); }; |
2561 | _phase->igvn().replace_input_of(u, MemNode::Memory, m); |
2562 | --i; |
2563 | } |
2564 | } |
2565 | } else if (u->is_MergeMem()) { |
2566 | MergeMemNode* u_mm = u->as_MergeMem(); |
2567 | if (u_mm->memory_at(alias) == mem) { |
2568 | MergeMemNode* newmm = NULL__null; |
2569 | for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) { |
2570 | Node* uu = u->fast_out(j); |
2571 | assert(!uu->is_MergeMem(), "chain of MergeMems?")do { if (!(!uu->is_MergeMem())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2571, "assert(" "!uu->is_MergeMem()" ") failed", "chain of MergeMems?" ); ::breakpoint(); } } while (0); |
2572 | if (uu->is_Phi()) { |
2573 | assert(uu->adr_type() == TypePtr::BOTTOM, "")do { if (!(uu->adr_type() == TypePtr::BOTTOM)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2573, "assert(" "uu->adr_type() == TypePtr::BOTTOM" ") failed" , ""); ::breakpoint(); } } while (0); |
2574 | Node* region = uu->in(0); |
2575 | int nb = 0; |
2576 | for (uint k = 1; k < uu->req(); k++) { |
2577 | if (uu->in(k) == u) { |
2578 | Node* m = find_mem(region->in(k), NULL__null); |
2579 | if (m != mem) { |
2580 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of phi %d", k); uu->dump(); })if (trace) { tty->print("ZZZ setting memory of phi %d", k) ; uu->dump(); }; |
2581 | newmm = clone_merge_mem(u, mem, m, _phase->ctrl_or_self(m), i); |
2582 | if (newmm != u) { |
2583 | _phase->igvn().replace_input_of(uu, k, newmm); |
2584 | nb++; |
2585 | --jmax; |
2586 | } |
2587 | } |
2588 | } |
2589 | } |
2590 | if (nb > 0) { |
2591 | --j; |
2592 | } |
2593 | } else { |
2594 | Node* m = find_mem(_phase->ctrl_or_self(uu), uu); |
2595 | if (m != mem) { |
2596 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); uu->dump(); })if (trace) { tty->print("ZZZ setting memory of use"); uu-> dump(); }; |
2597 | newmm = clone_merge_mem(u, mem, m, _phase->ctrl_or_self(m), i); |
2598 | if (newmm != u) { |
2599 | _phase->igvn().replace_input_of(uu, uu->find_edge(u), newmm); |
2600 | --j, --jmax; |
2601 | } |
2602 | } |
2603 | } |
2604 | } |
2605 | } |
2606 | } else if (u->is_Phi()) { |
2607 | assert(u->bottom_type() == Type::MEMORY, "what else?")do { if (!(u->bottom_type() == Type::MEMORY)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2607, "assert(" "u->bottom_type() == Type::MEMORY" ") failed" , "what else?"); ::breakpoint(); } } while (0); |
2608 | if (_phase->C->get_alias_index(u->adr_type()) == alias || u->adr_type() == TypePtr::BOTTOM) { |
2609 | Node* region = u->in(0); |
2610 | bool replaced = false; |
2611 | for (uint j = 1; j < u->req(); j++) { |
2612 | if (u->in(j) == mem) { |
2613 | Node* m = find_mem(region->in(j), NULL__null); |
2614 | Node* nnew = m; |
2615 | if (m != mem) { |
2616 | if (u->adr_type() == TypePtr::BOTTOM) { |
2617 | mm = allocate_merge_mem(mem, m, _phase->ctrl_or_self(m)); |
2618 | nnew = mm; |
2619 | } |
2620 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of phi %d", j); u->dump(); })if (trace) { tty->print("ZZZ setting memory of phi %d", j) ; u->dump(); }; |
2621 | _phase->igvn().replace_input_of(u, j, nnew); |
2622 | replaced = true; |
2623 | } |
2624 | } |
2625 | } |
2626 | if (replaced) { |
2627 | --i; |
2628 | } |
2629 | } |
2630 | } else if ((u->adr_type() == TypePtr::BOTTOM && u->Opcode() != Op_StrInflatedCopy) || |
2631 | u->adr_type() == NULL__null) { |
2632 | assert(u->adr_type() != NULL ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava ()->uncommon_trap_request() != 0) || (u->is_CallStaticJava () && u->as_CallStaticJava()->_entry_point == OptoRuntime ::rethrow_stub()) || u->Opcode() == Op_CallLeaf)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2638, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", ""); ::breakpoint(); } } while (0) |
2633 | u->Opcode() == Op_Rethrow ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava ()->uncommon_trap_request() != 0) || (u->is_CallStaticJava () && u->as_CallStaticJava()->_entry_point == OptoRuntime ::rethrow_stub()) || u->Opcode() == Op_CallLeaf)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2638, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", ""); ::breakpoint(); } } while (0) |
2634 | u->Opcode() == Op_Return ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava ()->uncommon_trap_request() != 0) || (u->is_CallStaticJava () && u->as_CallStaticJava()->_entry_point == OptoRuntime ::rethrow_stub()) || u->Opcode() == Op_CallLeaf)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2638, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", ""); ::breakpoint(); } } while (0) |
2635 | u->Opcode() == Op_SafePoint ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava ()->uncommon_trap_request() != 0) || (u->is_CallStaticJava () && u->as_CallStaticJava()->_entry_point == OptoRuntime ::rethrow_stub()) || u->Opcode() == Op_CallLeaf)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2638, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", ""); ::breakpoint(); } } while (0) |
2636 | (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava ()->uncommon_trap_request() != 0) || (u->is_CallStaticJava () && u->as_CallStaticJava()->_entry_point == OptoRuntime ::rethrow_stub()) || u->Opcode() == Op_CallLeaf)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2638, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", ""); ::breakpoint(); } } while (0) |
2637 | (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava ()->uncommon_trap_request() != 0) || (u->is_CallStaticJava () && u->as_CallStaticJava()->_entry_point == OptoRuntime ::rethrow_stub()) || u->Opcode() == Op_CallLeaf)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2638, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", ""); ::breakpoint(); } } while (0) |
2638 | u->Opcode() == Op_CallLeaf, "")do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava ()->uncommon_trap_request() != 0) || (u->is_CallStaticJava () && u->as_CallStaticJava()->_entry_point == OptoRuntime ::rethrow_stub()) || u->Opcode() == Op_CallLeaf)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2638, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", ""); ::breakpoint(); } } while (0); |
2639 | Node* m = find_mem(_phase->ctrl_or_self(u), u); |
2640 | if (m != mem) { |
2641 | mm = allocate_merge_mem(mem, m, _phase->get_ctrl(m)); |
2642 | _phase->igvn().replace_input_of(u, u->find_edge(mem), mm); |
2643 | --i; |
2644 | } |
2645 | } else if (_phase->C->get_alias_index(u->adr_type()) == alias) { |
2646 | Node* m = find_mem(_phase->ctrl_or_self(u), u); |
2647 | if (m != mem) { |
2648 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); })if (trace) { tty->print("ZZZ setting memory of use"); u-> dump(); }; |
2649 | _phase->igvn().replace_input_of(u, u->find_edge(mem), m); |
2650 | --i; |
2651 | } |
2652 | } else if (u->adr_type() != TypePtr::BOTTOM && |
2653 | _memory_nodes[_phase->ctrl_or_self(u)->_idx] == u) { |
2654 | Node* m = find_mem(_phase->ctrl_or_self(u), u); |
2655 | assert(m != mem, "")do { if (!(m != mem)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2655, "assert(" "m != mem" ") failed", ""); ::breakpoint(); } } while (0); |
2656 | // u is on the wrong slice... |
2657 | assert(u->is_ClearArray(), "")do { if (!(u->is_ClearArray())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2657, "assert(" "u->is_ClearArray()" ") failed", ""); :: breakpoint(); } } while (0); |
2658 | DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); })if (trace) { tty->print("ZZZ setting memory of use"); u-> dump(); }; |
2659 | _phase->igvn().replace_input_of(u, u->find_edge(mem), m); |
2660 | --i; |
2661 | } |
2662 | } |
2663 | } |
2664 | #ifdef ASSERT1 |
2665 | assert(new_mem->outcnt() > 0, "")do { if (!(new_mem->outcnt() > 0)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2665, "assert(" "new_mem->outcnt() > 0" ") failed", "" ); ::breakpoint(); } } while (0); |
2666 | for (int i = 0; i < phis.length(); i++) { |
2667 | Node* n = phis.at(i); |
2668 | assert(n->outcnt() > 0, "new phi must have uses now")do { if (!(n->outcnt() > 0)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2668, "assert(" "n->outcnt() > 0" ") failed", "new phi must have uses now" ); ::breakpoint(); } } while (0); |
2669 | } |
2670 | #endif |
2671 | } |
2672 | |
2673 | MergeMemNode* MemoryGraphFixer::allocate_merge_mem(Node* mem, Node* rep_proj, Node* rep_ctrl) const { |
2674 | MergeMemNode* mm = MergeMemNode::make(mem); |
2675 | mm->set_memory_at(_alias, rep_proj); |
2676 | _phase->register_new_node(mm, rep_ctrl); |
2677 | return mm; |
2678 | } |
2679 | |
2680 | MergeMemNode* MemoryGraphFixer::clone_merge_mem(Node* u, Node* mem, Node* rep_proj, Node* rep_ctrl, DUIterator& i) const { |
2681 | MergeMemNode* newmm = NULL__null; |
2682 | MergeMemNode* u_mm = u->as_MergeMem(); |
2683 | Node* c = _phase->get_ctrl(u); |
2684 | if (_phase->is_dominator(c, rep_ctrl)) { |
2685 | c = rep_ctrl; |
2686 | } else { |
2687 | assert(_phase->is_dominator(rep_ctrl, c), "one must dominate the other")do { if (!(_phase->is_dominator(rep_ctrl, c))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2687, "assert(" "_phase->is_dominator(rep_ctrl, c)" ") failed" , "one must dominate the other"); ::breakpoint(); } } while ( 0); |
2688 | } |
2689 | if (u->outcnt() == 1) { |
2690 | if (u->req() > (uint)_alias && u->in(_alias) == mem) { |
2691 | _phase->igvn().replace_input_of(u, _alias, rep_proj); |
2692 | --i; |
2693 | } else { |
2694 | _phase->igvn().rehash_node_delayed(u); |
2695 | u_mm->set_memory_at(_alias, rep_proj); |
2696 | } |
2697 | newmm = u_mm; |
2698 | _phase->set_ctrl_and_loop(u, c); |
2699 | } else { |
2700 | // can't simply clone u and then change one of its input because |
2701 | // it adds and then removes an edge which messes with the |
2702 | // DUIterator |
2703 | newmm = MergeMemNode::make(u_mm->base_memory()); |
2704 | for (uint j = 0; j < u->req(); j++) { |
2705 | if (j < newmm->req()) { |
2706 | if (j == (uint)_alias) { |
2707 | newmm->set_req(j, rep_proj); |
2708 | } else if (newmm->in(j) != u->in(j)) { |
2709 | newmm->set_req(j, u->in(j)); |
2710 | } |
2711 | } else if (j == (uint)_alias) { |
2712 | newmm->add_req(rep_proj); |
2713 | } else { |
2714 | newmm->add_req(u->in(j)); |
2715 | } |
2716 | } |
2717 | if ((uint)_alias >= u->req()) { |
2718 | newmm->set_memory_at(_alias, rep_proj); |
2719 | } |
2720 | _phase->register_new_node(newmm, c); |
2721 | } |
2722 | return newmm; |
2723 | } |
2724 | |
2725 | bool MemoryGraphFixer::should_process_phi(Node* phi) const { |
2726 | if (phi->adr_type() == TypePtr::BOTTOM) { |
2727 | Node* region = phi->in(0); |
2728 | for (DUIterator_Fast jmax, j = region->fast_outs(jmax); j < jmax; j++) { |
2729 | Node* uu = region->fast_out(j); |
2730 | if (uu->is_Phi() && uu != phi && uu->bottom_type() == Type::MEMORY && _phase->C->get_alias_index(uu->adr_type()) == _alias) { |
2731 | return false; |
2732 | } |
2733 | } |
2734 | return true; |
2735 | } |
2736 | return _phase->C->get_alias_index(phi->adr_type()) == _alias; |
2737 | } |
2738 | |
2739 | void MemoryGraphFixer::fix_memory_uses(Node* mem, Node* replacement, Node* rep_proj, Node* rep_ctrl) const { |
2740 | uint last = _phase-> C->unique(); |
2741 | MergeMemNode* mm = NULL__null; |
2742 | assert(mem->bottom_type() == Type::MEMORY, "")do { if (!(mem->bottom_type() == Type::MEMORY)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2742, "assert(" "mem->bottom_type() == Type::MEMORY" ") failed" , ""); ::breakpoint(); } } while (0); |
2743 | for (DUIterator i = mem->outs(); mem->has_out(i); i++) { |
2744 | Node* u = mem->out(i); |
2745 | if (u != replacement && u->_idx < last) { |
2746 | if (u->is_MergeMem()) { |
2747 | MergeMemNode* u_mm = u->as_MergeMem(); |
2748 | if (u_mm->memory_at(_alias) == mem) { |
2749 | MergeMemNode* newmm = NULL__null; |
2750 | for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) { |
2751 | Node* uu = u->fast_out(j); |
2752 | assert(!uu->is_MergeMem(), "chain of MergeMems?")do { if (!(!uu->is_MergeMem())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2752, "assert(" "!uu->is_MergeMem()" ") failed", "chain of MergeMems?" ); ::breakpoint(); } } while (0); |
2753 | if (uu->is_Phi()) { |
2754 | if (should_process_phi(uu)) { |
2755 | Node* region = uu->in(0); |
2756 | int nb = 0; |
2757 | for (uint k = 1; k < uu->req(); k++) { |
2758 | if (uu->in(k) == u && _phase->is_dominator(rep_ctrl, region->in(k))) { |
2759 | if (newmm == NULL__null) { |
2760 | newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i); |
2761 | } |
2762 | if (newmm != u) { |
2763 | _phase->igvn().replace_input_of(uu, k, newmm); |
2764 | nb++; |
2765 | --jmax; |
2766 | } |
2767 | } |
2768 | } |
2769 | if (nb > 0) { |
2770 | --j; |
2771 | } |
2772 | } |
2773 | } else { |
2774 | if (rep_ctrl != uu && ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(uu), replacement, uu, _phase)) { |
2775 | if (newmm == NULL__null) { |
2776 | newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i); |
2777 | } |
2778 | if (newmm != u) { |
2779 | _phase->igvn().replace_input_of(uu, uu->find_edge(u), newmm); |
2780 | --j, --jmax; |
2781 | } |
2782 | } |
2783 | } |
2784 | } |
2785 | } |
2786 | } else if (u->is_Phi()) { |
2787 | assert(u->bottom_type() == Type::MEMORY, "what else?")do { if (!(u->bottom_type() == Type::MEMORY)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2787, "assert(" "u->bottom_type() == Type::MEMORY" ") failed" , "what else?"); ::breakpoint(); } } while (0); |
2788 | Node* region = u->in(0); |
2789 | if (should_process_phi(u)) { |
2790 | bool replaced = false; |
2791 | for (uint j = 1; j < u->req(); j++) { |
2792 | if (u->in(j) == mem && _phase->is_dominator(rep_ctrl, region->in(j))) { |
2793 | Node* nnew = rep_proj; |
2794 | if (u->adr_type() == TypePtr::BOTTOM) { |
2795 | if (mm == NULL__null) { |
2796 | mm = allocate_merge_mem(mem, rep_proj, rep_ctrl); |
2797 | } |
2798 | nnew = mm; |
2799 | } |
2800 | _phase->igvn().replace_input_of(u, j, nnew); |
2801 | replaced = true; |
2802 | } |
2803 | } |
2804 | if (replaced) { |
2805 | --i; |
2806 | } |
2807 | |
2808 | } |
2809 | } else if ((u->adr_type() == TypePtr::BOTTOM && u->Opcode() != Op_StrInflatedCopy) || |
2810 | u->adr_type() == NULL__null) { |
2811 | assert(u->adr_type() != NULL ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0) |
2812 | u->Opcode() == Op_Rethrow ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0) |
2813 | u->Opcode() == Op_Return ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0) |
2814 | u->Opcode() == Op_SafePoint ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0) |
2815 | u->Opcode() == Op_StoreIConditional ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0) |
2816 | u->Opcode() == Op_StoreLConditional ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0) |
2817 | (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0) |
2818 | (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0) |
2819 | u->Opcode() == Op_CallLeaf, "%s", u->Name())do { if (!(u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava ()->_entry_point == OptoRuntime::rethrow_stub()) || u-> Opcode() == Op_CallLeaf)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2819, "assert(" "u->adr_type() != __null || u->Opcode() == Op_Rethrow || u->Opcode() == Op_Return || u->Opcode() == Op_SafePoint || u->Opcode() == Op_StoreIConditional || u->Opcode() == Op_StoreLConditional || (u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) || (u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) || u->Opcode() == Op_CallLeaf" ") failed", "%s", u->Name()); ::breakpoint(); } } while ( 0); |
2820 | if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) { |
2821 | if (mm == NULL__null) { |
2822 | mm = allocate_merge_mem(mem, rep_proj, rep_ctrl); |
2823 | } |
2824 | _phase->igvn().replace_input_of(u, u->find_edge(mem), mm); |
2825 | --i; |
2826 | } |
2827 | } else if (_phase->C->get_alias_index(u->adr_type()) == _alias) { |
2828 | if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) { |
2829 | _phase->igvn().replace_input_of(u, u->find_edge(mem), rep_proj); |
2830 | --i; |
2831 | } |
2832 | } |
2833 | } |
2834 | } |
2835 | } |
2836 | |
2837 | ShenandoahLoadReferenceBarrierNode::ShenandoahLoadReferenceBarrierNode(Node* ctrl, Node* obj, DecoratorSet decorators) |
2838 | : Node(ctrl, obj), _decorators(decorators) { |
2839 | ShenandoahBarrierSetC2::bsc2()->state()->add_load_reference_barrier(this); |
2840 | } |
2841 | |
2842 | DecoratorSet ShenandoahLoadReferenceBarrierNode::decorators() const { |
2843 | return _decorators; |
2844 | } |
2845 | |
2846 | uint ShenandoahLoadReferenceBarrierNode::size_of() const { |
2847 | return sizeof(*this); |
2848 | } |
2849 | |
2850 | static DecoratorSet mask_decorators(DecoratorSet decorators) { |
2851 | return decorators & (ON_STRONG_OOP_REF | ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF | IN_NATIVE); |
2852 | } |
2853 | |
2854 | uint ShenandoahLoadReferenceBarrierNode::hash() const { |
2855 | uint hash = Node::hash(); |
2856 | hash += mask_decorators(_decorators); |
2857 | return hash; |
2858 | } |
2859 | |
2860 | bool ShenandoahLoadReferenceBarrierNode::cmp( const Node &n ) const { |
2861 | return Node::cmp(n) && n.Opcode() == Op_ShenandoahLoadReferenceBarrier && |
2862 | mask_decorators(_decorators) == mask_decorators(((const ShenandoahLoadReferenceBarrierNode&)n)._decorators); |
2863 | } |
2864 | |
2865 | const Type* ShenandoahLoadReferenceBarrierNode::bottom_type() const { |
2866 | if (in(ValueIn) == NULL__null || in(ValueIn)->is_top()) { |
2867 | return Type::TOP; |
2868 | } |
2869 | const Type* t = in(ValueIn)->bottom_type(); |
2870 | if (t == TypePtr::NULL_PTR) { |
2871 | return t; |
2872 | } |
2873 | |
2874 | if (ShenandoahBarrierSet::is_strong_access(decorators())) { |
2875 | return t; |
2876 | } |
2877 | |
2878 | return t->meet(TypePtr::NULL_PTR); |
2879 | } |
2880 | |
2881 | const Type* ShenandoahLoadReferenceBarrierNode::Value(PhaseGVN* phase) const { |
2882 | // Either input is TOP ==> the result is TOP |
2883 | const Type *t2 = phase->type(in(ValueIn)); |
2884 | if( t2 == Type::TOP ) return Type::TOP; |
2885 | |
2886 | if (t2 == TypePtr::NULL_PTR) { |
2887 | return t2; |
2888 | } |
2889 | |
2890 | if (ShenandoahBarrierSet::is_strong_access(decorators())) { |
2891 | return t2; |
2892 | } |
2893 | |
2894 | return t2->meet(TypePtr::NULL_PTR); |
2895 | } |
2896 | |
2897 | Node* ShenandoahLoadReferenceBarrierNode::Identity(PhaseGVN* phase) { |
2898 | Node* value = in(ValueIn); |
2899 | if (!needs_barrier(phase, value)) { |
2900 | return value; |
2901 | } |
2902 | return this; |
2903 | } |
2904 | |
2905 | bool ShenandoahLoadReferenceBarrierNode::needs_barrier(PhaseGVN* phase, Node* n) { |
2906 | Unique_Node_List visited; |
2907 | return needs_barrier_impl(phase, n, visited); |
2908 | } |
2909 | |
2910 | bool ShenandoahLoadReferenceBarrierNode::needs_barrier_impl(PhaseGVN* phase, Node* n, Unique_Node_List &visited) { |
2911 | if (n == NULL__null) return false; |
2912 | if (visited.member(n)) { |
2913 | return false; // Been there. |
2914 | } |
2915 | visited.push(n); |
2916 | |
2917 | if (n->is_Allocate()) { |
2918 | // tty->print_cr("optimize barrier on alloc"); |
2919 | return false; |
2920 | } |
2921 | if (n->is_Call()) { |
2922 | // tty->print_cr("optimize barrier on call"); |
2923 | return false; |
2924 | } |
2925 | |
2926 | const Type* type = phase->type(n); |
2927 | if (type == Type::TOP) { |
2928 | return false; |
2929 | } |
2930 | if (type->make_ptr()->higher_equal(TypePtr::NULL_PTR)) { |
2931 | // tty->print_cr("optimize barrier on null"); |
2932 | return false; |
2933 | } |
2934 | if (type->make_oopptr() && type->make_oopptr()->const_oop() != NULL__null) { |
2935 | // tty->print_cr("optimize barrier on constant"); |
2936 | return false; |
2937 | } |
2938 | |
2939 | switch (n->Opcode()) { |
2940 | case Op_AddP: |
2941 | return true; // TODO: Can refine? |
2942 | case Op_LoadP: |
2943 | case Op_ShenandoahCompareAndExchangeN: |
2944 | case Op_ShenandoahCompareAndExchangeP: |
2945 | case Op_CompareAndExchangeN: |
2946 | case Op_CompareAndExchangeP: |
2947 | case Op_GetAndSetN: |
2948 | case Op_GetAndSetP: |
2949 | return true; |
2950 | case Op_Phi: { |
2951 | for (uint i = 1; i < n->req(); i++) { |
2952 | if (needs_barrier_impl(phase, n->in(i), visited)) return true; |
2953 | } |
2954 | return false; |
2955 | } |
2956 | case Op_CheckCastPP: |
2957 | case Op_CastPP: |
2958 | return needs_barrier_impl(phase, n->in(1), visited); |
2959 | case Op_Proj: |
2960 | return needs_barrier_impl(phase, n->in(0), visited); |
2961 | case Op_ShenandoahLoadReferenceBarrier: |
2962 | // tty->print_cr("optimize barrier on barrier"); |
2963 | return false; |
2964 | case Op_Parm: |
2965 | // tty->print_cr("optimize barrier on input arg"); |
2966 | return false; |
2967 | case Op_DecodeN: |
2968 | case Op_EncodeP: |
2969 | return needs_barrier_impl(phase, n->in(1), visited); |
2970 | case Op_LoadN: |
2971 | return true; |
2972 | case Op_CMoveN: |
2973 | case Op_CMoveP: |
2974 | return needs_barrier_impl(phase, n->in(2), visited) || |
2975 | needs_barrier_impl(phase, n->in(3), visited); |
2976 | case Op_ShenandoahIUBarrier: |
2977 | return needs_barrier_impl(phase, n->in(1), visited); |
2978 | case Op_CreateEx: |
2979 | return false; |
2980 | default: |
2981 | break; |
2982 | } |
2983 | #ifdef ASSERT1 |
2984 | tty->print("need barrier on?: "); |
2985 | tty->print_cr("ins:"); |
2986 | n->dump(2); |
2987 | tty->print_cr("outs:"); |
2988 | n->dump(-2); |
2989 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp" , 2989); ::breakpoint(); } while (0); |
2990 | #endif |
2991 | return true; |
2992 | } |