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