Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
40976 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(), true);
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
Node* head = in->in(0);
2174
assert(head->is_Region(), "unexpected infinite loop graph shape");
2175
2176
Node* phi_mem = NULL;
2177
for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) {
2178
Node* u = head->fast_out(j);
2179
if (u->is_Phi() && u->bottom_type() == Type::MEMORY) {
2180
if (_phase->C->get_alias_index(u->adr_type()) == _alias) {
2181
assert(phi_mem == NULL || phi_mem->adr_type() == TypePtr::BOTTOM, "");
2182
phi_mem = u;
2183
} else if (u->adr_type() == TypePtr::BOTTOM) {
2184
assert(phi_mem == NULL || _phase->C->get_alias_index(phi_mem->adr_type()) == _alias, "");
2185
if (phi_mem == NULL) {
2186
phi_mem = u;
2187
}
2188
}
2189
}
2190
}
2191
if (phi_mem == NULL) {
2192
for (uint j = 1; j < head->req(); j++) {
2193
Node* tail = head->in(j);
2194
if (!_phase->is_dominator(head, tail)) {
2195
continue;
2196
}
2197
Node* c = tail;
2198
while (c != head) {
2199
if (c->is_SafePoint() && !c->is_CallLeaf()) {
2200
Node* m =c->in(TypeFunc::Memory);
2201
if (m->is_MergeMem()) {
2202
m = m->as_MergeMem()->memory_at(_alias);
2203
}
2204
assert(mem == NULL || mem == m, "several memory states");
2205
mem = m;
2206
}
2207
c = _phase->idom(c);
2208
}
2209
assert(mem != NULL, "should have found safepoint");
2210
}
2211
assert(mem != NULL, "should have found safepoint");
2212
} else {
2213
mem = phi_mem;
2214
}
2215
}
2216
}
2217
} else {
2218
#ifdef ASSERT
2219
n->dump();
2220
in->dump();
2221
#endif
2222
ShouldNotReachHere();
2223
}
2224
} else {
2225
assert(n->is_Phi() && n->bottom_type() == Type::MEMORY, "");
2226
assert(n->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(n->adr_type()) == _alias, "");
2227
mem = n->in(i);
2228
}
2229
i++;
2230
stack.set_index(i);
2231
if (mem == NULL) {
2232
continue;
2233
}
2234
for (;;) {
2235
if (visited.test_set(mem->_idx) || mem->is_Start()) {
2236
break;
2237
}
2238
if (mem->is_Phi()) {
2239
stack.push(mem, 2);
2240
mem = mem->in(1);
2241
} else if (mem->is_Proj()) {
2242
stack.push(mem, mem->req());
2243
mem = mem->in(0);
2244
} else if (mem->is_SafePoint() || mem->is_MemBar()) {
2245
mem = mem->in(TypeFunc::Memory);
2246
} else if (mem->is_MergeMem()) {
2247
MergeMemNode* mm = mem->as_MergeMem();
2248
mem = mm->memory_at(_alias);
2249
} else if (mem->is_Store() || mem->is_LoadStore() || mem->is_ClearArray()) {
2250
assert(_alias == Compile::AliasIdxRaw, "");
2251
stack.push(mem, mem->req());
2252
mem = mem->in(MemNode::Memory);
2253
} else {
2254
#ifdef ASSERT
2255
mem->dump();
2256
#endif
2257
ShouldNotReachHere();
2258
}
2259
}
2260
} else {
2261
if (n->is_Phi()) {
2262
// Nothing
2263
} else if (!n->is_Root()) {
2264
Node* c = get_ctrl(n);
2265
_memory_nodes.map(c->_idx, n);
2266
}
2267
stack.pop();
2268
}
2269
} while(stack.is_nonempty());
2270
2271
// Iterate over CFG nodes in rpo and propagate memory state to
2272
// compute memory state at regions, creating new phis if needed.
2273
Node_List rpo_list;
2274
visited.clear();
2275
_phase->rpo(_phase->C->root(), stack, visited, rpo_list);
2276
Node* root = rpo_list.pop();
2277
assert(root == _phase->C->root(), "");
2278
2279
const bool trace = false;
2280
#ifdef ASSERT
2281
if (trace) {
2282
for (int i = rpo_list.size() - 1; i >= 0; i--) {
2283
Node* c = rpo_list.at(i);
2284
if (_memory_nodes[c->_idx] != NULL) {
2285
tty->print("X %d", c->_idx); _memory_nodes[c->_idx]->dump();
2286
}
2287
}
2288
}
2289
#endif
2290
uint last = _phase->C->unique();
2291
2292
#ifdef ASSERT
2293
uint16_t max_depth = 0;
2294
for (LoopTreeIterator iter(_phase->ltree_root()); !iter.done(); iter.next()) {
2295
IdealLoopTree* lpt = iter.current();
2296
max_depth = MAX2(max_depth, lpt->_nest);
2297
}
2298
#endif
2299
2300
bool progress = true;
2301
int iteration = 0;
2302
Node_List dead_phis;
2303
while (progress) {
2304
progress = false;
2305
iteration++;
2306
assert(iteration <= 2+max_depth || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "");
2307
if (trace) { tty->print_cr("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); }
2308
2309
for (int i = rpo_list.size() - 1; i >= 0; i--) {
2310
Node* c = rpo_list.at(i);
2311
2312
Node* prev_mem = _memory_nodes[c->_idx];
2313
if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {
2314
Node* prev_region = regions[c->_idx];
2315
Node* unique = NULL;
2316
for (uint j = 1; j < c->req() && unique != NodeSentinel; j++) {
2317
Node* m = _memory_nodes[c->in(j)->_idx];
2318
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");
2319
if (m != NULL) {
2320
if (m == prev_region && ((c->is_Loop() && j == LoopNode::LoopBackControl) || (prev_region->is_Phi() && prev_region->in(0) == c))) {
2321
assert(c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "");
2322
// continue
2323
} else if (unique == NULL) {
2324
unique = m;
2325
} else if (m == unique) {
2326
// continue
2327
} else {
2328
unique = NodeSentinel;
2329
}
2330
}
2331
}
2332
assert(unique != NULL, "empty phi???");
2333
if (unique != NodeSentinel) {
2334
if (prev_region != NULL && prev_region->is_Phi() && prev_region->in(0) == c) {
2335
dead_phis.push(prev_region);
2336
}
2337
regions.map(c->_idx, unique);
2338
} else {
2339
Node* phi = NULL;
2340
if (prev_region != NULL && prev_region->is_Phi() && prev_region->in(0) == c && prev_region->_idx >= last) {
2341
phi = prev_region;
2342
for (uint k = 1; k < c->req(); k++) {
2343
Node* m = _memory_nodes[c->in(k)->_idx];
2344
assert(m != NULL, "expect memory state");
2345
phi->set_req(k, m);
2346
}
2347
} else {
2348
for (DUIterator_Fast jmax, j = c->fast_outs(jmax); j < jmax && phi == NULL; j++) {
2349
Node* u = c->fast_out(j);
2350
if (u->is_Phi() && u->bottom_type() == Type::MEMORY &&
2351
(u->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(u->adr_type()) == _alias)) {
2352
phi = u;
2353
for (uint k = 1; k < c->req() && phi != NULL; k++) {
2354
Node* m = _memory_nodes[c->in(k)->_idx];
2355
assert(m != NULL, "expect memory state");
2356
if (u->in(k) != m) {
2357
phi = NodeSentinel;
2358
}
2359
}
2360
}
2361
}
2362
if (phi == NodeSentinel) {
2363
phi = new PhiNode(c, Type::MEMORY, _phase->C->get_adr_type(_alias));
2364
for (uint k = 1; k < c->req(); k++) {
2365
Node* m = _memory_nodes[c->in(k)->_idx];
2366
assert(m != NULL, "expect memory state");
2367
phi->init_req(k, m);
2368
}
2369
}
2370
}
2371
if (phi != NULL) {
2372
regions.map(c->_idx, phi);
2373
} else {
2374
assert(c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");
2375
}
2376
}
2377
Node* current_region = regions[c->_idx];
2378
if (current_region != prev_region) {
2379
progress = true;
2380
if (prev_region == prev_mem) {
2381
_memory_nodes.map(c->_idx, current_region);
2382
}
2383
}
2384
} else if (prev_mem == NULL || prev_mem->is_Phi() || ctrl_or_self(prev_mem) != c) {
2385
Node* m = _memory_nodes[_phase->idom(c)->_idx];
2386
assert(m != NULL || c->Opcode() == Op_Halt, "expect memory state");
2387
if (m != prev_mem) {
2388
_memory_nodes.map(c->_idx, m);
2389
progress = true;
2390
}
2391
}
2392
#ifdef ASSERT
2393
if (trace) { tty->print("X %d", c->_idx); _memory_nodes[c->_idx]->dump(); }
2394
#endif
2395
}
2396
}
2397
2398
// Replace existing phi with computed memory state for that region
2399
// if different (could be a new phi or a dominating memory node if
2400
// that phi was found to be useless).
2401
while (dead_phis.size() > 0) {
2402
Node* n = dead_phis.pop();
2403
n->replace_by(_phase->C->top());
2404
n->destruct(&_phase->igvn());
2405
}
2406
for (int i = rpo_list.size() - 1; i >= 0; i--) {
2407
Node* c = rpo_list.at(i);
2408
if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {
2409
Node* n = regions[c->_idx];
2410
assert(n != NULL || c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");
2411
if (n != NULL && n->is_Phi() && n->_idx >= last && n->in(0) == c) {
2412
_phase->register_new_node(n, c);
2413
}
2414
}
2415
}
2416
for (int i = rpo_list.size() - 1; i >= 0; i--) {
2417
Node* c = rpo_list.at(i);
2418
if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {
2419
Node* n = regions[c->_idx];
2420
assert(n != NULL || c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");
2421
for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax; i++) {
2422
Node* u = c->fast_out(i);
2423
if (u->is_Phi() && u->bottom_type() == Type::MEMORY &&
2424
u != n) {
2425
assert(c->unique_ctrl_out()->Opcode() != Op_Halt, "expected memory state");
2426
if (u->adr_type() == TypePtr::BOTTOM) {
2427
fix_memory_uses(u, n, n, c);
2428
} else if (_phase->C->get_alias_index(u->adr_type()) == _alias) {
2429
_phase->lazy_replace(u, n);
2430
--i; --imax;
2431
}
2432
}
2433
}
2434
}
2435
}
2436
}
2437
2438
Node* MemoryGraphFixer::get_ctrl(Node* n) const {
2439
Node* c = _phase->get_ctrl(n);
2440
if (n->is_Proj() && n->in(0) != NULL && n->in(0)->is_Call()) {
2441
assert(c == n->in(0), "");
2442
CallNode* call = c->as_Call();
2443
CallProjections projs;
2444
call->extract_projections(&projs, true, false);
2445
if (projs.catchall_memproj != NULL) {
2446
if (projs.fallthrough_memproj == n) {
2447
c = projs.fallthrough_catchproj;
2448
} else {
2449
assert(projs.catchall_memproj == n, "");
2450
c = projs.catchall_catchproj;
2451
}
2452
}
2453
}
2454
return c;
2455
}
2456
2457
Node* MemoryGraphFixer::ctrl_or_self(Node* n) const {
2458
if (_phase->has_ctrl(n))
2459
return get_ctrl(n);
2460
else {
2461
assert (n->is_CFG(), "must be a CFG node");
2462
return n;
2463
}
2464
}
2465
2466
bool MemoryGraphFixer::mem_is_valid(Node* m, Node* c) const {
2467
return m != NULL && get_ctrl(m) == c;
2468
}
2469
2470
Node* MemoryGraphFixer::find_mem(Node* ctrl, Node* n) const {
2471
assert(n == NULL || _phase->ctrl_or_self(n) == ctrl, "");
2472
assert(!ctrl->is_Call() || ctrl == n, "projection expected");
2473
#ifdef ASSERT
2474
if ((ctrl->is_Proj() && ctrl->in(0)->is_Call()) ||
2475
(ctrl->is_Catch() && ctrl->in(0)->in(0)->is_Call())) {
2476
CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_Call() : ctrl->in(0)->in(0)->as_Call();
2477
int mems = 0;
2478
for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) {
2479
Node* u = call->fast_out(i);
2480
if (u->bottom_type() == Type::MEMORY) {
2481
mems++;
2482
}
2483
}
2484
assert(mems <= 1, "No node right after call if multiple mem projections");
2485
}
2486
#endif
2487
Node* mem = _memory_nodes[ctrl->_idx];
2488
Node* c = ctrl;
2489
while (!mem_is_valid(mem, c) &&
2490
(!c->is_CatchProj() || mem == NULL || c->in(0)->in(0)->in(0) != get_ctrl(mem))) {
2491
c = _phase->idom(c);
2492
mem = _memory_nodes[c->_idx];
2493
}
2494
if (n != NULL && mem_is_valid(mem, c)) {
2495
while (!ShenandoahBarrierC2Support::is_dominator_same_ctrl(c, mem, n, _phase) && _phase->ctrl_or_self(mem) == ctrl) {
2496
mem = next_mem(mem, _alias);
2497
}
2498
if (mem->is_MergeMem()) {
2499
mem = mem->as_MergeMem()->memory_at(_alias);
2500
}
2501
if (!mem_is_valid(mem, c)) {
2502
do {
2503
c = _phase->idom(c);
2504
mem = _memory_nodes[c->_idx];
2505
} while (!mem_is_valid(mem, c) &&
2506
(!c->is_CatchProj() || mem == NULL || c->in(0)->in(0)->in(0) != get_ctrl(mem)));
2507
}
2508
}
2509
assert(mem->bottom_type() == Type::MEMORY, "");
2510
return mem;
2511
}
2512
2513
bool MemoryGraphFixer::has_mem_phi(Node* region) const {
2514
for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
2515
Node* use = region->fast_out(i);
2516
if (use->is_Phi() && use->bottom_type() == Type::MEMORY &&
2517
(_phase->C->get_alias_index(use->adr_type()) == _alias)) {
2518
return true;
2519
}
2520
}
2521
return false;
2522
}
2523
2524
void MemoryGraphFixer::fix_mem(Node* ctrl, Node* new_ctrl, Node* mem, Node* mem_for_ctrl, Node* new_mem, Unique_Node_List& uses) {
2525
assert(_phase->ctrl_or_self(new_mem) == new_ctrl, "");
2526
const bool trace = false;
2527
DEBUG_ONLY(if (trace) { tty->print("ZZZ control is"); ctrl->dump(); });
2528
DEBUG_ONLY(if (trace) { tty->print("ZZZ mem is"); mem->dump(); });
2529
GrowableArray<Node*> phis;
2530
if (mem_for_ctrl != mem) {
2531
Node* old = mem_for_ctrl;
2532
Node* prev = NULL;
2533
while (old != mem) {
2534
prev = old;
2535
if (old->is_Store() || old->is_ClearArray() || old->is_LoadStore()) {
2536
assert(_alias == Compile::AliasIdxRaw, "");
2537
old = old->in(MemNode::Memory);
2538
} else if (old->Opcode() == Op_SCMemProj) {
2539
assert(_alias == Compile::AliasIdxRaw, "");
2540
old = old->in(0);
2541
} else {
2542
ShouldNotReachHere();
2543
}
2544
}
2545
assert(prev != NULL, "");
2546
if (new_ctrl != ctrl) {
2547
_memory_nodes.map(ctrl->_idx, mem);
2548
_memory_nodes.map(new_ctrl->_idx, mem_for_ctrl);
2549
}
2550
uint input = (uint)MemNode::Memory;
2551
_phase->igvn().replace_input_of(prev, input, new_mem);
2552
} else {
2553
uses.clear();
2554
_memory_nodes.map(new_ctrl->_idx, new_mem);
2555
uses.push(new_ctrl);
2556
for(uint next = 0; next < uses.size(); next++ ) {
2557
Node *n = uses.at(next);
2558
assert(n->is_CFG(), "");
2559
DEBUG_ONLY(if (trace) { tty->print("ZZZ ctrl"); n->dump(); });
2560
for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
2561
Node* u = n->fast_out(i);
2562
if (!u->is_Root() && u->is_CFG() && u != n) {
2563
Node* m = _memory_nodes[u->_idx];
2564
if (u->is_Region() && (!u->is_OuterStripMinedLoop() || _include_lsm) &&
2565
!has_mem_phi(u) &&
2566
u->unique_ctrl_out()->Opcode() != Op_Halt) {
2567
DEBUG_ONLY(if (trace) { tty->print("ZZZ region"); u->dump(); });
2568
DEBUG_ONLY(if (trace && m != NULL) { tty->print("ZZZ mem"); m->dump(); });
2569
2570
if (!mem_is_valid(m, u) || !m->is_Phi()) {
2571
bool push = true;
2572
bool create_phi = true;
2573
if (_phase->is_dominator(new_ctrl, u)) {
2574
create_phi = false;
2575
}
2576
if (create_phi) {
2577
Node* phi = new PhiNode(u, Type::MEMORY, _phase->C->get_adr_type(_alias));
2578
_phase->register_new_node(phi, u);
2579
phis.push(phi);
2580
DEBUG_ONLY(if (trace) { tty->print("ZZZ new phi"); phi->dump(); });
2581
if (!mem_is_valid(m, u)) {
2582
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting mem"); phi->dump(); });
2583
_memory_nodes.map(u->_idx, phi);
2584
} else {
2585
DEBUG_ONLY(if (trace) { tty->print("ZZZ NOT setting mem"); m->dump(); });
2586
for (;;) {
2587
assert(m->is_Mem() || m->is_LoadStore() || m->is_Proj(), "");
2588
Node* next = NULL;
2589
if (m->is_Proj()) {
2590
next = m->in(0);
2591
} else {
2592
assert(m->is_Mem() || m->is_LoadStore(), "");
2593
assert(_alias == Compile::AliasIdxRaw, "");
2594
next = m->in(MemNode::Memory);
2595
}
2596
if (_phase->get_ctrl(next) != u) {
2597
break;
2598
}
2599
if (next->is_MergeMem()) {
2600
assert(_phase->get_ctrl(next->as_MergeMem()->memory_at(_alias)) != u, "");
2601
break;
2602
}
2603
if (next->is_Phi()) {
2604
assert(next->adr_type() == TypePtr::BOTTOM && next->in(0) == u, "");
2605
break;
2606
}
2607
m = next;
2608
}
2609
2610
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting to phi"); m->dump(); });
2611
assert(m->is_Mem() || m->is_LoadStore(), "");
2612
uint input = (uint)MemNode::Memory;
2613
_phase->igvn().replace_input_of(m, input, phi);
2614
push = false;
2615
}
2616
} else {
2617
DEBUG_ONLY(if (trace) { tty->print("ZZZ skipping region"); u->dump(); });
2618
}
2619
if (push) {
2620
uses.push(u);
2621
}
2622
}
2623
} else if (!mem_is_valid(m, u) &&
2624
!(u->Opcode() == Op_CProj && u->in(0)->Opcode() == Op_NeverBranch && u->as_Proj()->_con == 1)) {
2625
uses.push(u);
2626
}
2627
}
2628
}
2629
}
2630
for (int i = 0; i < phis.length(); i++) {
2631
Node* n = phis.at(i);
2632
Node* r = n->in(0);
2633
DEBUG_ONLY(if (trace) { tty->print("ZZZ fixing new phi"); n->dump(); });
2634
for (uint j = 1; j < n->req(); j++) {
2635
Node* m = find_mem(r->in(j), NULL);
2636
_phase->igvn().replace_input_of(n, j, m);
2637
DEBUG_ONLY(if (trace) { tty->print("ZZZ fixing new phi: %d", j); m->dump(); });
2638
}
2639
}
2640
}
2641
uint last = _phase->C->unique();
2642
MergeMemNode* mm = NULL;
2643
int alias = _alias;
2644
DEBUG_ONLY(if (trace) { tty->print("ZZZ raw mem is"); mem->dump(); });
2645
// Process loads first to not miss an anti-dependency: if the memory
2646
// edge of a store is updated before a load is processed then an
2647
// anti-dependency may be missed.
2648
for (DUIterator i = mem->outs(); mem->has_out(i); i++) {
2649
Node* u = mem->out(i);
2650
if (u->_idx < last && u->is_Load() && _phase->C->get_alias_index(u->adr_type()) == alias) {
2651
Node* m = find_mem(_phase->get_ctrl(u), u);
2652
if (m != mem) {
2653
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });
2654
_phase->igvn().replace_input_of(u, MemNode::Memory, m);
2655
--i;
2656
}
2657
}
2658
}
2659
for (DUIterator i = mem->outs(); mem->has_out(i); i++) {
2660
Node* u = mem->out(i);
2661
if (u->_idx < last) {
2662
if (u->is_Mem()) {
2663
if (_phase->C->get_alias_index(u->adr_type()) == alias) {
2664
Node* m = find_mem(_phase->get_ctrl(u), u);
2665
if (m != mem) {
2666
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });
2667
_phase->igvn().replace_input_of(u, MemNode::Memory, m);
2668
--i;
2669
}
2670
}
2671
} else if (u->is_MergeMem()) {
2672
MergeMemNode* u_mm = u->as_MergeMem();
2673
if (u_mm->memory_at(alias) == mem) {
2674
MergeMemNode* newmm = NULL;
2675
for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) {
2676
Node* uu = u->fast_out(j);
2677
assert(!uu->is_MergeMem(), "chain of MergeMems?");
2678
if (uu->is_Phi()) {
2679
assert(uu->adr_type() == TypePtr::BOTTOM, "");
2680
Node* region = uu->in(0);
2681
int nb = 0;
2682
for (uint k = 1; k < uu->req(); k++) {
2683
if (uu->in(k) == u) {
2684
Node* m = find_mem(region->in(k), NULL);
2685
if (m != mem) {
2686
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of phi %d", k); uu->dump(); });
2687
newmm = clone_merge_mem(u, mem, m, _phase->ctrl_or_self(m), i);
2688
if (newmm != u) {
2689
_phase->igvn().replace_input_of(uu, k, newmm);
2690
nb++;
2691
--jmax;
2692
}
2693
}
2694
}
2695
}
2696
if (nb > 0) {
2697
--j;
2698
}
2699
} else {
2700
Node* m = find_mem(_phase->ctrl_or_self(uu), uu);
2701
if (m != mem) {
2702
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); uu->dump(); });
2703
newmm = clone_merge_mem(u, mem, m, _phase->ctrl_or_self(m), i);
2704
if (newmm != u) {
2705
_phase->igvn().replace_input_of(uu, uu->find_edge(u), newmm);
2706
--j, --jmax;
2707
}
2708
}
2709
}
2710
}
2711
}
2712
} else if (u->is_Phi()) {
2713
assert(u->bottom_type() == Type::MEMORY, "what else?");
2714
if (_phase->C->get_alias_index(u->adr_type()) == alias || u->adr_type() == TypePtr::BOTTOM) {
2715
Node* region = u->in(0);
2716
bool replaced = false;
2717
for (uint j = 1; j < u->req(); j++) {
2718
if (u->in(j) == mem) {
2719
Node* m = find_mem(region->in(j), NULL);
2720
Node* nnew = m;
2721
if (m != mem) {
2722
if (u->adr_type() == TypePtr::BOTTOM) {
2723
mm = allocate_merge_mem(mem, m, _phase->ctrl_or_self(m));
2724
nnew = mm;
2725
}
2726
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of phi %d", j); u->dump(); });
2727
_phase->igvn().replace_input_of(u, j, nnew);
2728
replaced = true;
2729
}
2730
}
2731
}
2732
if (replaced) {
2733
--i;
2734
}
2735
}
2736
} else if ((u->adr_type() == TypePtr::BOTTOM && u->Opcode() != Op_StrInflatedCopy) ||
2737
u->adr_type() == NULL) {
2738
assert(u->adr_type() != NULL ||
2739
u->Opcode() == Op_Rethrow ||
2740
u->Opcode() == Op_Return ||
2741
u->Opcode() == Op_SafePoint ||
2742
(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||
2743
(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||
2744
u->Opcode() == Op_CallLeaf, "");
2745
Node* m = find_mem(_phase->ctrl_or_self(u), u);
2746
if (m != mem) {
2747
mm = allocate_merge_mem(mem, m, _phase->get_ctrl(m));
2748
_phase->igvn().replace_input_of(u, u->find_edge(mem), mm);
2749
--i;
2750
}
2751
} else if (_phase->C->get_alias_index(u->adr_type()) == alias) {
2752
Node* m = find_mem(_phase->ctrl_or_self(u), u);
2753
if (m != mem) {
2754
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });
2755
_phase->igvn().replace_input_of(u, u->find_edge(mem), m);
2756
--i;
2757
}
2758
} else if (u->adr_type() != TypePtr::BOTTOM &&
2759
_memory_nodes[_phase->ctrl_or_self(u)->_idx] == u) {
2760
Node* m = find_mem(_phase->ctrl_or_self(u), u);
2761
assert(m != mem, "");
2762
// u is on the wrong slice...
2763
assert(u->is_ClearArray(), "");
2764
DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });
2765
_phase->igvn().replace_input_of(u, u->find_edge(mem), m);
2766
--i;
2767
}
2768
}
2769
}
2770
#ifdef ASSERT
2771
assert(new_mem->outcnt() > 0, "");
2772
for (int i = 0; i < phis.length(); i++) {
2773
Node* n = phis.at(i);
2774
assert(n->outcnt() > 0, "new phi must have uses now");
2775
}
2776
#endif
2777
}
2778
2779
MergeMemNode* MemoryGraphFixer::allocate_merge_mem(Node* mem, Node* rep_proj, Node* rep_ctrl) const {
2780
MergeMemNode* mm = MergeMemNode::make(mem);
2781
mm->set_memory_at(_alias, rep_proj);
2782
_phase->register_new_node(mm, rep_ctrl);
2783
return mm;
2784
}
2785
2786
MergeMemNode* MemoryGraphFixer::clone_merge_mem(Node* u, Node* mem, Node* rep_proj, Node* rep_ctrl, DUIterator& i) const {
2787
MergeMemNode* newmm = NULL;
2788
MergeMemNode* u_mm = u->as_MergeMem();
2789
Node* c = _phase->get_ctrl(u);
2790
if (_phase->is_dominator(c, rep_ctrl)) {
2791
c = rep_ctrl;
2792
} else {
2793
assert(_phase->is_dominator(rep_ctrl, c), "one must dominate the other");
2794
}
2795
if (u->outcnt() == 1) {
2796
if (u->req() > (uint)_alias && u->in(_alias) == mem) {
2797
_phase->igvn().replace_input_of(u, _alias, rep_proj);
2798
--i;
2799
} else {
2800
_phase->igvn().rehash_node_delayed(u);
2801
u_mm->set_memory_at(_alias, rep_proj);
2802
}
2803
newmm = u_mm;
2804
_phase->set_ctrl_and_loop(u, c);
2805
} else {
2806
// can't simply clone u and then change one of its input because
2807
// it adds and then removes an edge which messes with the
2808
// DUIterator
2809
newmm = MergeMemNode::make(u_mm->base_memory());
2810
for (uint j = 0; j < u->req(); j++) {
2811
if (j < newmm->req()) {
2812
if (j == (uint)_alias) {
2813
newmm->set_req(j, rep_proj);
2814
} else if (newmm->in(j) != u->in(j)) {
2815
newmm->set_req(j, u->in(j));
2816
}
2817
} else if (j == (uint)_alias) {
2818
newmm->add_req(rep_proj);
2819
} else {
2820
newmm->add_req(u->in(j));
2821
}
2822
}
2823
if ((uint)_alias >= u->req()) {
2824
newmm->set_memory_at(_alias, rep_proj);
2825
}
2826
_phase->register_new_node(newmm, c);
2827
}
2828
return newmm;
2829
}
2830
2831
bool MemoryGraphFixer::should_process_phi(Node* phi) const {
2832
if (phi->adr_type() == TypePtr::BOTTOM) {
2833
Node* region = phi->in(0);
2834
for (DUIterator_Fast jmax, j = region->fast_outs(jmax); j < jmax; j++) {
2835
Node* uu = region->fast_out(j);
2836
if (uu->is_Phi() && uu != phi && uu->bottom_type() == Type::MEMORY && _phase->C->get_alias_index(uu->adr_type()) == _alias) {
2837
return false;
2838
}
2839
}
2840
return true;
2841
}
2842
return _phase->C->get_alias_index(phi->adr_type()) == _alias;
2843
}
2844
2845
void MemoryGraphFixer::fix_memory_uses(Node* mem, Node* replacement, Node* rep_proj, Node* rep_ctrl) const {
2846
uint last = _phase-> C->unique();
2847
MergeMemNode* mm = NULL;
2848
assert(mem->bottom_type() == Type::MEMORY, "");
2849
for (DUIterator i = mem->outs(); mem->has_out(i); i++) {
2850
Node* u = mem->out(i);
2851
if (u != replacement && u->_idx < last) {
2852
if (u->is_MergeMem()) {
2853
MergeMemNode* u_mm = u->as_MergeMem();
2854
if (u_mm->memory_at(_alias) == mem) {
2855
MergeMemNode* newmm = NULL;
2856
for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) {
2857
Node* uu = u->fast_out(j);
2858
assert(!uu->is_MergeMem(), "chain of MergeMems?");
2859
if (uu->is_Phi()) {
2860
if (should_process_phi(uu)) {
2861
Node* region = uu->in(0);
2862
int nb = 0;
2863
for (uint k = 1; k < uu->req(); k++) {
2864
if (uu->in(k) == u && _phase->is_dominator(rep_ctrl, region->in(k))) {
2865
if (newmm == NULL) {
2866
newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i);
2867
}
2868
if (newmm != u) {
2869
_phase->igvn().replace_input_of(uu, k, newmm);
2870
nb++;
2871
--jmax;
2872
}
2873
}
2874
}
2875
if (nb > 0) {
2876
--j;
2877
}
2878
}
2879
} else {
2880
if (rep_ctrl != uu && ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(uu), replacement, uu, _phase)) {
2881
if (newmm == NULL) {
2882
newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i);
2883
}
2884
if (newmm != u) {
2885
_phase->igvn().replace_input_of(uu, uu->find_edge(u), newmm);
2886
--j, --jmax;
2887
}
2888
}
2889
}
2890
}
2891
}
2892
} else if (u->is_Phi()) {
2893
assert(u->bottom_type() == Type::MEMORY, "what else?");
2894
Node* region = u->in(0);
2895
if (should_process_phi(u)) {
2896
bool replaced = false;
2897
for (uint j = 1; j < u->req(); j++) {
2898
if (u->in(j) == mem && _phase->is_dominator(rep_ctrl, region->in(j))) {
2899
Node* nnew = rep_proj;
2900
if (u->adr_type() == TypePtr::BOTTOM) {
2901
if (mm == NULL) {
2902
mm = allocate_merge_mem(mem, rep_proj, rep_ctrl);
2903
}
2904
nnew = mm;
2905
}
2906
_phase->igvn().replace_input_of(u, j, nnew);
2907
replaced = true;
2908
}
2909
}
2910
if (replaced) {
2911
--i;
2912
}
2913
2914
}
2915
} else if ((u->adr_type() == TypePtr::BOTTOM && u->Opcode() != Op_StrInflatedCopy) ||
2916
u->adr_type() == NULL) {
2917
assert(u->adr_type() != NULL ||
2918
u->Opcode() == Op_Rethrow ||
2919
u->Opcode() == Op_Return ||
2920
u->Opcode() == Op_SafePoint ||
2921
u->Opcode() == Op_StoreIConditional ||
2922
u->Opcode() == Op_StoreLConditional ||
2923
(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||
2924
(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||
2925
u->Opcode() == Op_CallLeaf, "%s", u->Name());
2926
if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {
2927
if (mm == NULL) {
2928
mm = allocate_merge_mem(mem, rep_proj, rep_ctrl);
2929
}
2930
_phase->igvn().replace_input_of(u, u->find_edge(mem), mm);
2931
--i;
2932
}
2933
} else if (_phase->C->get_alias_index(u->adr_type()) == _alias) {
2934
if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {
2935
_phase->igvn().replace_input_of(u, u->find_edge(mem), rep_proj);
2936
--i;
2937
}
2938
}
2939
}
2940
}
2941
}
2942
2943
ShenandoahLoadReferenceBarrierNode::ShenandoahLoadReferenceBarrierNode(Node* ctrl, Node* obj, DecoratorSet decorators)
2944
: Node(ctrl, obj), _decorators(decorators) {
2945
ShenandoahBarrierSetC2::bsc2()->state()->add_load_reference_barrier(this);
2946
}
2947
2948
DecoratorSet ShenandoahLoadReferenceBarrierNode::decorators() const {
2949
return _decorators;
2950
}
2951
2952
uint ShenandoahLoadReferenceBarrierNode::size_of() const {
2953
return sizeof(*this);
2954
}
2955
2956
static DecoratorSet mask_decorators(DecoratorSet decorators) {
2957
return decorators & (ON_STRONG_OOP_REF | ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF | IN_NATIVE);
2958
}
2959
2960
uint ShenandoahLoadReferenceBarrierNode::hash() const {
2961
uint hash = Node::hash();
2962
hash += mask_decorators(_decorators);
2963
return hash;
2964
}
2965
2966
bool ShenandoahLoadReferenceBarrierNode::cmp( const Node &n ) const {
2967
return Node::cmp(n) && n.Opcode() == Op_ShenandoahLoadReferenceBarrier &&
2968
mask_decorators(_decorators) == mask_decorators(((const ShenandoahLoadReferenceBarrierNode&)n)._decorators);
2969
}
2970
2971
const Type* ShenandoahLoadReferenceBarrierNode::bottom_type() const {
2972
if (in(ValueIn) == NULL || in(ValueIn)->is_top()) {
2973
return Type::TOP;
2974
}
2975
const Type* t = in(ValueIn)->bottom_type();
2976
if (t == TypePtr::NULL_PTR) {
2977
return t;
2978
}
2979
2980
if (ShenandoahBarrierSet::is_strong_access(decorators())) {
2981
return t;
2982
}
2983
2984
return t->meet(TypePtr::NULL_PTR);
2985
}
2986
2987
const Type* ShenandoahLoadReferenceBarrierNode::Value(PhaseGVN* phase) const {
2988
// Either input is TOP ==> the result is TOP
2989
const Type *t2 = phase->type(in(ValueIn));
2990
if( t2 == Type::TOP ) return Type::TOP;
2991
2992
if (t2 == TypePtr::NULL_PTR) {
2993
return t2;
2994
}
2995
2996
if (ShenandoahBarrierSet::is_strong_access(decorators())) {
2997
return t2;
2998
}
2999
3000
return t2->meet(TypePtr::NULL_PTR);
3001
}
3002
3003
Node* ShenandoahLoadReferenceBarrierNode::Identity(PhaseGVN* phase) {
3004
Node* value = in(ValueIn);
3005
if (!needs_barrier(phase, value)) {
3006
return value;
3007
}
3008
return this;
3009
}
3010
3011
bool ShenandoahLoadReferenceBarrierNode::needs_barrier(PhaseGVN* phase, Node* n) {
3012
Unique_Node_List visited;
3013
return needs_barrier_impl(phase, n, visited);
3014
}
3015
3016
bool ShenandoahLoadReferenceBarrierNode::needs_barrier_impl(PhaseGVN* phase, Node* n, Unique_Node_List &visited) {
3017
if (n == NULL) return false;
3018
if (visited.member(n)) {
3019
return false; // Been there.
3020
}
3021
visited.push(n);
3022
3023
if (n->is_Allocate()) {
3024
// tty->print_cr("optimize barrier on alloc");
3025
return false;
3026
}
3027
if (n->is_Call()) {
3028
// tty->print_cr("optimize barrier on call");
3029
return false;
3030
}
3031
3032
const Type* type = phase->type(n);
3033
if (type == Type::TOP) {
3034
return false;
3035
}
3036
if (type->make_ptr()->higher_equal(TypePtr::NULL_PTR)) {
3037
// tty->print_cr("optimize barrier on null");
3038
return false;
3039
}
3040
if (type->make_oopptr() && type->make_oopptr()->const_oop() != NULL) {
3041
// tty->print_cr("optimize barrier on constant");
3042
return false;
3043
}
3044
3045
switch (n->Opcode()) {
3046
case Op_AddP:
3047
return true; // TODO: Can refine?
3048
case Op_LoadP:
3049
case Op_ShenandoahCompareAndExchangeN:
3050
case Op_ShenandoahCompareAndExchangeP:
3051
case Op_CompareAndExchangeN:
3052
case Op_CompareAndExchangeP:
3053
case Op_GetAndSetN:
3054
case Op_GetAndSetP:
3055
return true;
3056
case Op_Phi: {
3057
for (uint i = 1; i < n->req(); i++) {
3058
if (needs_barrier_impl(phase, n->in(i), visited)) return true;
3059
}
3060
return false;
3061
}
3062
case Op_CheckCastPP:
3063
case Op_CastPP:
3064
return needs_barrier_impl(phase, n->in(1), visited);
3065
case Op_Proj:
3066
return needs_barrier_impl(phase, n->in(0), visited);
3067
case Op_ShenandoahLoadReferenceBarrier:
3068
// tty->print_cr("optimize barrier on barrier");
3069
return false;
3070
case Op_Parm:
3071
// tty->print_cr("optimize barrier on input arg");
3072
return false;
3073
case Op_DecodeN:
3074
case Op_EncodeP:
3075
return needs_barrier_impl(phase, n->in(1), visited);
3076
case Op_LoadN:
3077
return true;
3078
case Op_CMoveN:
3079
case Op_CMoveP:
3080
return needs_barrier_impl(phase, n->in(2), visited) ||
3081
needs_barrier_impl(phase, n->in(3), visited);
3082
case Op_ShenandoahIUBarrier:
3083
return needs_barrier_impl(phase, n->in(1), visited);
3084
case Op_CreateEx:
3085
return false;
3086
default:
3087
break;
3088
}
3089
#ifdef ASSERT
3090
tty->print("need barrier on?: ");
3091
tty->print_cr("ins:");
3092
n->dump(2);
3093
tty->print_cr("outs:");
3094
n->dump(-2);
3095
ShouldNotReachHere();
3096
#endif
3097
return true;
3098
}
3099
3100