Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp
66646 views
1
/*
2
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. 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
#include "gc/shared/tlab_globals.hpp"
27
#include "gc/shared/c2/barrierSetC2.hpp"
28
#include "opto/arraycopynode.hpp"
29
#include "opto/convertnode.hpp"
30
#include "opto/graphKit.hpp"
31
#include "opto/idealKit.hpp"
32
#include "opto/macro.hpp"
33
#include "opto/narrowptrnode.hpp"
34
#include "opto/runtime.hpp"
35
#include "utilities/macros.hpp"
36
37
// By default this is a no-op.
38
void BarrierSetC2::resolve_address(C2Access& access) const { }
39
40
void* C2ParseAccess::barrier_set_state() const {
41
return _kit->barrier_set_state();
42
}
43
44
PhaseGVN& C2ParseAccess::gvn() const { return _kit->gvn(); }
45
46
bool C2Access::needs_cpu_membar() const {
47
bool mismatched = (_decorators & C2_MISMATCHED) != 0;
48
bool is_unordered = (_decorators & MO_UNORDERED) != 0;
49
50
bool anonymous = (_decorators & C2_UNSAFE_ACCESS) != 0;
51
bool in_heap = (_decorators & IN_HEAP) != 0;
52
bool in_native = (_decorators & IN_NATIVE) != 0;
53
bool is_mixed = !in_heap && !in_native;
54
55
bool is_write = (_decorators & C2_WRITE_ACCESS) != 0;
56
bool is_read = (_decorators & C2_READ_ACCESS) != 0;
57
bool is_atomic = is_read && is_write;
58
59
if (is_atomic) {
60
// Atomics always need to be wrapped in CPU membars
61
return true;
62
}
63
64
if (anonymous) {
65
// We will need memory barriers unless we can determine a unique
66
// alias category for this reference. (Note: If for some reason
67
// the barriers get omitted and the unsafe reference begins to "pollute"
68
// the alias analysis of the rest of the graph, either Compile::can_alias
69
// or Compile::must_alias will throw a diagnostic assert.)
70
if (is_mixed || !is_unordered || (mismatched && !_addr.type()->isa_aryptr())) {
71
return true;
72
}
73
} else {
74
assert(!is_mixed, "not unsafe");
75
}
76
77
return false;
78
}
79
80
Node* BarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) const {
81
DecoratorSet decorators = access.decorators();
82
83
bool mismatched = (decorators & C2_MISMATCHED) != 0;
84
bool unaligned = (decorators & C2_UNALIGNED) != 0;
85
bool unsafe = (decorators & C2_UNSAFE_ACCESS) != 0;
86
bool requires_atomic_access = (decorators & MO_UNORDERED) == 0;
87
88
bool in_native = (decorators & IN_NATIVE) != 0;
89
assert(!in_native || (unsafe && !access.is_oop()), "not supported yet");
90
91
MemNode::MemOrd mo = access.mem_node_mo();
92
93
Node* store;
94
BasicType bt = access.type();
95
if (access.is_parse_access()) {
96
C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access);
97
98
GraphKit* kit = parse_access.kit();
99
if (bt == T_DOUBLE) {
100
Node* new_val = kit->dstore_rounding(val.node());
101
val.set_node(new_val);
102
}
103
104
store = kit->store_to_memory(kit->control(), access.addr().node(), val.node(), bt,
105
access.addr().type(), mo, requires_atomic_access, unaligned, mismatched, unsafe);
106
} else {
107
assert(access.is_opt_access(), "either parse or opt access");
108
C2OptAccess& opt_access = static_cast<C2OptAccess&>(access);
109
Node* ctl = opt_access.ctl();
110
MergeMemNode* mm = opt_access.mem();
111
PhaseGVN& gvn = opt_access.gvn();
112
const TypePtr* adr_type = access.addr().type();
113
int alias = gvn.C->get_alias_index(adr_type);
114
Node* mem = mm->memory_at(alias);
115
116
StoreNode* st = StoreNode::make(gvn, ctl, mem, access.addr().node(), adr_type, val.node(), bt, mo, requires_atomic_access);
117
if (unaligned) {
118
st->set_unaligned_access();
119
}
120
if (mismatched) {
121
st->set_mismatched_access();
122
}
123
store = gvn.transform(st);
124
if (store == st) {
125
mm->set_memory_at(alias, st);
126
}
127
}
128
access.set_raw_access(store);
129
130
return store;
131
}
132
133
Node* BarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) const {
134
DecoratorSet decorators = access.decorators();
135
136
Node* adr = access.addr().node();
137
const TypePtr* adr_type = access.addr().type();
138
139
bool mismatched = (decorators & C2_MISMATCHED) != 0;
140
bool requires_atomic_access = (decorators & MO_UNORDERED) == 0;
141
bool unaligned = (decorators & C2_UNALIGNED) != 0;
142
bool control_dependent = (decorators & C2_CONTROL_DEPENDENT_LOAD) != 0;
143
bool unknown_control = (decorators & C2_UNKNOWN_CONTROL_LOAD) != 0;
144
bool unsafe = (decorators & C2_UNSAFE_ACCESS) != 0;
145
bool immutable = (decorators & C2_IMMUTABLE_MEMORY) != 0;
146
147
bool in_native = (decorators & IN_NATIVE) != 0;
148
149
MemNode::MemOrd mo = access.mem_node_mo();
150
LoadNode::ControlDependency dep = unknown_control ? LoadNode::UnknownControl : LoadNode::DependsOnlyOnTest;
151
152
Node* load;
153
if (access.is_parse_access()) {
154
C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access);
155
GraphKit* kit = parse_access.kit();
156
Node* control = control_dependent ? kit->control() : NULL;
157
158
if (immutable) {
159
Compile* C = Compile::current();
160
Node* mem = kit->immutable_memory();
161
load = LoadNode::make(kit->gvn(), control, mem, adr,
162
adr_type, val_type, access.type(), mo, dep, requires_atomic_access,
163
unaligned, mismatched, unsafe, access.barrier_data());
164
load = kit->gvn().transform(load);
165
} else {
166
load = kit->make_load(control, adr, val_type, access.type(), adr_type, mo,
167
dep, requires_atomic_access, unaligned, mismatched, unsafe,
168
access.barrier_data());
169
}
170
} else {
171
assert(access.is_opt_access(), "either parse or opt access");
172
C2OptAccess& opt_access = static_cast<C2OptAccess&>(access);
173
Node* control = control_dependent ? opt_access.ctl() : NULL;
174
MergeMemNode* mm = opt_access.mem();
175
PhaseGVN& gvn = opt_access.gvn();
176
Node* mem = mm->memory_at(gvn.C->get_alias_index(adr_type));
177
load = LoadNode::make(gvn, control, mem, adr, adr_type, val_type, access.type(), mo, dep,
178
requires_atomic_access, unaligned, mismatched, unsafe, access.barrier_data());
179
load = gvn.transform(load);
180
}
181
access.set_raw_access(load);
182
183
return load;
184
}
185
186
class C2AccessFence: public StackObj {
187
C2Access& _access;
188
Node* _leading_membar;
189
190
public:
191
C2AccessFence(C2Access& access) :
192
_access(access), _leading_membar(NULL) {
193
GraphKit* kit = NULL;
194
if (access.is_parse_access()) {
195
C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access);
196
kit = parse_access.kit();
197
}
198
DecoratorSet decorators = access.decorators();
199
200
bool is_write = (decorators & C2_WRITE_ACCESS) != 0;
201
bool is_read = (decorators & C2_READ_ACCESS) != 0;
202
bool is_atomic = is_read && is_write;
203
204
bool is_volatile = (decorators & MO_SEQ_CST) != 0;
205
bool is_release = (decorators & MO_RELEASE) != 0;
206
207
if (is_atomic) {
208
assert(kit != NULL, "unsupported at optimization time");
209
// Memory-model-wise, a LoadStore acts like a little synchronized
210
// block, so needs barriers on each side. These don't translate
211
// into actual barriers on most machines, but we still need rest of
212
// compiler to respect ordering.
213
if (is_release) {
214
_leading_membar = kit->insert_mem_bar(Op_MemBarRelease);
215
} else if (is_volatile) {
216
if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
217
_leading_membar = kit->insert_mem_bar(Op_MemBarVolatile);
218
} else {
219
_leading_membar = kit->insert_mem_bar(Op_MemBarRelease);
220
}
221
}
222
} else if (is_write) {
223
// If reference is volatile, prevent following memory ops from
224
// floating down past the volatile write. Also prevents commoning
225
// another volatile read.
226
if (is_volatile || is_release) {
227
assert(kit != NULL, "unsupported at optimization time");
228
_leading_membar = kit->insert_mem_bar(Op_MemBarRelease);
229
}
230
} else {
231
// Memory barrier to prevent normal and 'unsafe' accesses from
232
// bypassing each other. Happens after null checks, so the
233
// exception paths do not take memory state from the memory barrier,
234
// so there's no problems making a strong assert about mixing users
235
// of safe & unsafe memory.
236
if (is_volatile && support_IRIW_for_not_multiple_copy_atomic_cpu) {
237
assert(kit != NULL, "unsupported at optimization time");
238
_leading_membar = kit->insert_mem_bar(Op_MemBarVolatile);
239
}
240
}
241
242
if (access.needs_cpu_membar()) {
243
assert(kit != NULL, "unsupported at optimization time");
244
kit->insert_mem_bar(Op_MemBarCPUOrder);
245
}
246
247
if (is_atomic) {
248
// 4984716: MemBars must be inserted before this
249
// memory node in order to avoid a false
250
// dependency which will confuse the scheduler.
251
access.set_memory();
252
}
253
}
254
255
~C2AccessFence() {
256
GraphKit* kit = NULL;
257
if (_access.is_parse_access()) {
258
C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(_access);
259
kit = parse_access.kit();
260
}
261
DecoratorSet decorators = _access.decorators();
262
263
bool is_write = (decorators & C2_WRITE_ACCESS) != 0;
264
bool is_read = (decorators & C2_READ_ACCESS) != 0;
265
bool is_atomic = is_read && is_write;
266
267
bool is_volatile = (decorators & MO_SEQ_CST) != 0;
268
bool is_acquire = (decorators & MO_ACQUIRE) != 0;
269
270
// If reference is volatile, prevent following volatiles ops from
271
// floating up before the volatile access.
272
if (_access.needs_cpu_membar()) {
273
kit->insert_mem_bar(Op_MemBarCPUOrder);
274
}
275
276
if (is_atomic) {
277
assert(kit != NULL, "unsupported at optimization time");
278
if (is_acquire || is_volatile) {
279
Node* n = _access.raw_access();
280
Node* mb = kit->insert_mem_bar(Op_MemBarAcquire, n);
281
if (_leading_membar != NULL) {
282
MemBarNode::set_load_store_pair(_leading_membar->as_MemBar(), mb->as_MemBar());
283
}
284
}
285
} else if (is_write) {
286
// If not multiple copy atomic, we do the MemBarVolatile before the load.
287
if (is_volatile && !support_IRIW_for_not_multiple_copy_atomic_cpu) {
288
assert(kit != NULL, "unsupported at optimization time");
289
Node* n = _access.raw_access();
290
Node* mb = kit->insert_mem_bar(Op_MemBarVolatile, n); // Use fat membar
291
if (_leading_membar != NULL) {
292
MemBarNode::set_store_pair(_leading_membar->as_MemBar(), mb->as_MemBar());
293
}
294
}
295
} else {
296
if (is_volatile || is_acquire) {
297
assert(kit != NULL, "unsupported at optimization time");
298
Node* n = _access.raw_access();
299
assert(_leading_membar == NULL || support_IRIW_for_not_multiple_copy_atomic_cpu, "no leading membar expected");
300
Node* mb = kit->insert_mem_bar(Op_MemBarAcquire, n);
301
mb->as_MemBar()->set_trailing_load();
302
}
303
}
304
}
305
};
306
307
Node* BarrierSetC2::store_at(C2Access& access, C2AccessValue& val) const {
308
C2AccessFence fence(access);
309
resolve_address(access);
310
return store_at_resolved(access, val);
311
}
312
313
Node* BarrierSetC2::load_at(C2Access& access, const Type* val_type) const {
314
C2AccessFence fence(access);
315
resolve_address(access);
316
return load_at_resolved(access, val_type);
317
}
318
319
MemNode::MemOrd C2Access::mem_node_mo() const {
320
bool is_write = (_decorators & C2_WRITE_ACCESS) != 0;
321
bool is_read = (_decorators & C2_READ_ACCESS) != 0;
322
if ((_decorators & MO_SEQ_CST) != 0) {
323
if (is_write && is_read) {
324
// For atomic operations
325
return MemNode::seqcst;
326
} else if (is_write) {
327
return MemNode::release;
328
} else {
329
assert(is_read, "what else?");
330
return MemNode::acquire;
331
}
332
} else if ((_decorators & MO_RELEASE) != 0) {
333
return MemNode::release;
334
} else if ((_decorators & MO_ACQUIRE) != 0) {
335
return MemNode::acquire;
336
} else if (is_write) {
337
// Volatile fields need releasing stores.
338
// Non-volatile fields also need releasing stores if they hold an
339
// object reference, because the object reference might point to
340
// a freshly created object.
341
// Conservatively release stores of object references.
342
return StoreNode::release_if_reference(_type);
343
} else {
344
return MemNode::unordered;
345
}
346
}
347
348
void C2Access::fixup_decorators() {
349
bool default_mo = (_decorators & MO_DECORATOR_MASK) == 0;
350
bool is_unordered = (_decorators & MO_UNORDERED) != 0 || default_mo;
351
bool anonymous = (_decorators & C2_UNSAFE_ACCESS) != 0;
352
353
bool is_read = (_decorators & C2_READ_ACCESS) != 0;
354
bool is_write = (_decorators & C2_WRITE_ACCESS) != 0;
355
356
if (AlwaysAtomicAccesses && is_unordered) {
357
_decorators &= ~MO_DECORATOR_MASK; // clear the MO bits
358
_decorators |= MO_RELAXED; // Force the MO_RELAXED decorator with AlwaysAtomicAccess
359
}
360
361
_decorators = AccessInternal::decorator_fixup(_decorators);
362
363
if (is_read && !is_write && anonymous) {
364
// To be valid, unsafe loads may depend on other conditions than
365
// the one that guards them: pin the Load node
366
_decorators |= C2_CONTROL_DEPENDENT_LOAD;
367
_decorators |= C2_UNKNOWN_CONTROL_LOAD;
368
const TypePtr* adr_type = _addr.type();
369
Node* adr = _addr.node();
370
if (!needs_cpu_membar() && adr_type->isa_instptr()) {
371
assert(adr_type->meet(TypePtr::NULL_PTR) != adr_type->remove_speculative(), "should be not null");
372
intptr_t offset = Type::OffsetBot;
373
AddPNode::Ideal_base_and_offset(adr, &gvn(), offset);
374
if (offset >= 0) {
375
int s = Klass::layout_helper_size_in_bytes(adr_type->isa_instptr()->klass()->layout_helper());
376
if (offset < s) {
377
// Guaranteed to be a valid access, no need to pin it
378
_decorators ^= C2_CONTROL_DEPENDENT_LOAD;
379
_decorators ^= C2_UNKNOWN_CONTROL_LOAD;
380
}
381
}
382
}
383
}
384
}
385
386
//--------------------------- atomic operations---------------------------------
387
388
void BarrierSetC2::pin_atomic_op(C2AtomicParseAccess& access) const {
389
if (!access.needs_pinning()) {
390
return;
391
}
392
// SCMemProjNodes represent the memory state of a LoadStore. Their
393
// main role is to prevent LoadStore nodes from being optimized away
394
// when their results aren't used.
395
assert(access.is_parse_access(), "entry not supported at optimization time");
396
C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access);
397
GraphKit* kit = parse_access.kit();
398
Node* load_store = access.raw_access();
399
assert(load_store != NULL, "must pin atomic op");
400
Node* proj = kit->gvn().transform(new SCMemProjNode(load_store));
401
kit->set_memory(proj, access.alias_idx());
402
}
403
404
void C2AtomicParseAccess::set_memory() {
405
Node *mem = _kit->memory(_alias_idx);
406
_memory = mem;
407
}
408
409
Node* BarrierSetC2::atomic_cmpxchg_val_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
410
Node* new_val, const Type* value_type) const {
411
GraphKit* kit = access.kit();
412
MemNode::MemOrd mo = access.mem_node_mo();
413
Node* mem = access.memory();
414
415
Node* adr = access.addr().node();
416
const TypePtr* adr_type = access.addr().type();
417
418
Node* load_store = NULL;
419
420
if (access.is_oop()) {
421
#ifdef _LP64
422
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
423
Node *newval_enc = kit->gvn().transform(new EncodePNode(new_val, new_val->bottom_type()->make_narrowoop()));
424
Node *oldval_enc = kit->gvn().transform(new EncodePNode(expected_val, expected_val->bottom_type()->make_narrowoop()));
425
load_store = new CompareAndExchangeNNode(kit->control(), mem, adr, newval_enc, oldval_enc, adr_type, value_type->make_narrowoop(), mo);
426
} else
427
#endif
428
{
429
load_store = new CompareAndExchangePNode(kit->control(), mem, adr, new_val, expected_val, adr_type, value_type->is_oopptr(), mo);
430
}
431
} else {
432
switch (access.type()) {
433
case T_BYTE: {
434
load_store = new CompareAndExchangeBNode(kit->control(), mem, adr, new_val, expected_val, adr_type, mo);
435
break;
436
}
437
case T_SHORT: {
438
load_store = new CompareAndExchangeSNode(kit->control(), mem, adr, new_val, expected_val, adr_type, mo);
439
break;
440
}
441
case T_INT: {
442
load_store = new CompareAndExchangeINode(kit->control(), mem, adr, new_val, expected_val, adr_type, mo);
443
break;
444
}
445
case T_LONG: {
446
load_store = new CompareAndExchangeLNode(kit->control(), mem, adr, new_val, expected_val, adr_type, mo);
447
break;
448
}
449
default:
450
ShouldNotReachHere();
451
}
452
}
453
454
load_store->as_LoadStore()->set_barrier_data(access.barrier_data());
455
load_store = kit->gvn().transform(load_store);
456
457
access.set_raw_access(load_store);
458
pin_atomic_op(access);
459
460
#ifdef _LP64
461
if (access.is_oop() && adr->bottom_type()->is_ptr_to_narrowoop()) {
462
return kit->gvn().transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
463
}
464
#endif
465
466
return load_store;
467
}
468
469
Node* BarrierSetC2::atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
470
Node* new_val, const Type* value_type) const {
471
GraphKit* kit = access.kit();
472
DecoratorSet decorators = access.decorators();
473
MemNode::MemOrd mo = access.mem_node_mo();
474
Node* mem = access.memory();
475
bool is_weak_cas = (decorators & C2_WEAK_CMPXCHG) != 0;
476
Node* load_store = NULL;
477
Node* adr = access.addr().node();
478
479
if (access.is_oop()) {
480
#ifdef _LP64
481
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
482
Node *newval_enc = kit->gvn().transform(new EncodePNode(new_val, new_val->bottom_type()->make_narrowoop()));
483
Node *oldval_enc = kit->gvn().transform(new EncodePNode(expected_val, expected_val->bottom_type()->make_narrowoop()));
484
if (is_weak_cas) {
485
load_store = new WeakCompareAndSwapNNode(kit->control(), mem, adr, newval_enc, oldval_enc, mo);
486
} else {
487
load_store = new CompareAndSwapNNode(kit->control(), mem, adr, newval_enc, oldval_enc, mo);
488
}
489
} else
490
#endif
491
{
492
if (is_weak_cas) {
493
load_store = new WeakCompareAndSwapPNode(kit->control(), mem, adr, new_val, expected_val, mo);
494
} else {
495
load_store = new CompareAndSwapPNode(kit->control(), mem, adr, new_val, expected_val, mo);
496
}
497
}
498
} else {
499
switch(access.type()) {
500
case T_BYTE: {
501
if (is_weak_cas) {
502
load_store = new WeakCompareAndSwapBNode(kit->control(), mem, adr, new_val, expected_val, mo);
503
} else {
504
load_store = new CompareAndSwapBNode(kit->control(), mem, adr, new_val, expected_val, mo);
505
}
506
break;
507
}
508
case T_SHORT: {
509
if (is_weak_cas) {
510
load_store = new WeakCompareAndSwapSNode(kit->control(), mem, adr, new_val, expected_val, mo);
511
} else {
512
load_store = new CompareAndSwapSNode(kit->control(), mem, adr, new_val, expected_val, mo);
513
}
514
break;
515
}
516
case T_INT: {
517
if (is_weak_cas) {
518
load_store = new WeakCompareAndSwapINode(kit->control(), mem, adr, new_val, expected_val, mo);
519
} else {
520
load_store = new CompareAndSwapINode(kit->control(), mem, adr, new_val, expected_val, mo);
521
}
522
break;
523
}
524
case T_LONG: {
525
if (is_weak_cas) {
526
load_store = new WeakCompareAndSwapLNode(kit->control(), mem, adr, new_val, expected_val, mo);
527
} else {
528
load_store = new CompareAndSwapLNode(kit->control(), mem, adr, new_val, expected_val, mo);
529
}
530
break;
531
}
532
default:
533
ShouldNotReachHere();
534
}
535
}
536
537
load_store->as_LoadStore()->set_barrier_data(access.barrier_data());
538
load_store = kit->gvn().transform(load_store);
539
540
access.set_raw_access(load_store);
541
pin_atomic_op(access);
542
543
return load_store;
544
}
545
546
Node* BarrierSetC2::atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node* new_val, const Type* value_type) const {
547
GraphKit* kit = access.kit();
548
Node* mem = access.memory();
549
Node* adr = access.addr().node();
550
const TypePtr* adr_type = access.addr().type();
551
Node* load_store = NULL;
552
553
if (access.is_oop()) {
554
#ifdef _LP64
555
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
556
Node *newval_enc = kit->gvn().transform(new EncodePNode(new_val, new_val->bottom_type()->make_narrowoop()));
557
load_store = kit->gvn().transform(new GetAndSetNNode(kit->control(), mem, adr, newval_enc, adr_type, value_type->make_narrowoop()));
558
} else
559
#endif
560
{
561
load_store = new GetAndSetPNode(kit->control(), mem, adr, new_val, adr_type, value_type->is_oopptr());
562
}
563
} else {
564
switch (access.type()) {
565
case T_BYTE:
566
load_store = new GetAndSetBNode(kit->control(), mem, adr, new_val, adr_type);
567
break;
568
case T_SHORT:
569
load_store = new GetAndSetSNode(kit->control(), mem, adr, new_val, adr_type);
570
break;
571
case T_INT:
572
load_store = new GetAndSetINode(kit->control(), mem, adr, new_val, adr_type);
573
break;
574
case T_LONG:
575
load_store = new GetAndSetLNode(kit->control(), mem, adr, new_val, adr_type);
576
break;
577
default:
578
ShouldNotReachHere();
579
}
580
}
581
582
load_store->as_LoadStore()->set_barrier_data(access.barrier_data());
583
load_store = kit->gvn().transform(load_store);
584
585
access.set_raw_access(load_store);
586
pin_atomic_op(access);
587
588
#ifdef _LP64
589
if (access.is_oop() && adr->bottom_type()->is_ptr_to_narrowoop()) {
590
return kit->gvn().transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
591
}
592
#endif
593
594
return load_store;
595
}
596
597
Node* BarrierSetC2::atomic_add_at_resolved(C2AtomicParseAccess& access, Node* new_val, const Type* value_type) const {
598
Node* load_store = NULL;
599
GraphKit* kit = access.kit();
600
Node* adr = access.addr().node();
601
const TypePtr* adr_type = access.addr().type();
602
Node* mem = access.memory();
603
604
switch(access.type()) {
605
case T_BYTE:
606
load_store = new GetAndAddBNode(kit->control(), mem, adr, new_val, adr_type);
607
break;
608
case T_SHORT:
609
load_store = new GetAndAddSNode(kit->control(), mem, adr, new_val, adr_type);
610
break;
611
case T_INT:
612
load_store = new GetAndAddINode(kit->control(), mem, adr, new_val, adr_type);
613
break;
614
case T_LONG:
615
load_store = new GetAndAddLNode(kit->control(), mem, adr, new_val, adr_type);
616
break;
617
default:
618
ShouldNotReachHere();
619
}
620
621
load_store->as_LoadStore()->set_barrier_data(access.barrier_data());
622
load_store = kit->gvn().transform(load_store);
623
624
access.set_raw_access(load_store);
625
pin_atomic_op(access);
626
627
return load_store;
628
}
629
630
Node* BarrierSetC2::atomic_cmpxchg_val_at(C2AtomicParseAccess& access, Node* expected_val,
631
Node* new_val, const Type* value_type) const {
632
C2AccessFence fence(access);
633
resolve_address(access);
634
return atomic_cmpxchg_val_at_resolved(access, expected_val, new_val, value_type);
635
}
636
637
Node* BarrierSetC2::atomic_cmpxchg_bool_at(C2AtomicParseAccess& access, Node* expected_val,
638
Node* new_val, const Type* value_type) const {
639
C2AccessFence fence(access);
640
resolve_address(access);
641
return atomic_cmpxchg_bool_at_resolved(access, expected_val, new_val, value_type);
642
}
643
644
Node* BarrierSetC2::atomic_xchg_at(C2AtomicParseAccess& access, Node* new_val, const Type* value_type) const {
645
C2AccessFence fence(access);
646
resolve_address(access);
647
return atomic_xchg_at_resolved(access, new_val, value_type);
648
}
649
650
Node* BarrierSetC2::atomic_add_at(C2AtomicParseAccess& access, Node* new_val, const Type* value_type) const {
651
C2AccessFence fence(access);
652
resolve_address(access);
653
return atomic_add_at_resolved(access, new_val, value_type);
654
}
655
656
int BarrierSetC2::arraycopy_payload_base_offset(bool is_array) {
657
// Exclude the header but include array length to copy by 8 bytes words.
658
// Can't use base_offset_in_bytes(bt) since basic type is unknown.
659
int base_off = is_array ? arrayOopDesc::length_offset_in_bytes() :
660
instanceOopDesc::base_offset_in_bytes();
661
// base_off:
662
// 8 - 32-bit VM
663
// 12 - 64-bit VM, compressed klass
664
// 16 - 64-bit VM, normal klass
665
if (base_off % BytesPerLong != 0) {
666
assert(UseCompressedClassPointers, "");
667
if (is_array) {
668
// Exclude length to copy by 8 bytes words.
669
base_off += sizeof(int);
670
} else {
671
// Include klass to copy by 8 bytes words.
672
base_off = instanceOopDesc::klass_offset_in_bytes();
673
}
674
assert(base_off % BytesPerLong == 0, "expect 8 bytes alignment");
675
}
676
return base_off;
677
}
678
679
void BarrierSetC2::clone(GraphKit* kit, Node* src_base, Node* dst_base, Node* size, bool is_array) const {
680
int base_off = arraycopy_payload_base_offset(is_array);
681
Node* payload_size = size;
682
Node* offset = kit->MakeConX(base_off);
683
payload_size = kit->gvn().transform(new SubXNode(payload_size, offset));
684
payload_size = kit->gvn().transform(new URShiftXNode(payload_size, kit->intcon(LogBytesPerLong)));
685
ArrayCopyNode* ac = ArrayCopyNode::make(kit, false, src_base, offset, dst_base, offset, payload_size, true, false);
686
if (is_array) {
687
ac->set_clone_array();
688
} else {
689
ac->set_clone_inst();
690
}
691
Node* n = kit->gvn().transform(ac);
692
if (n == ac) {
693
const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
694
ac->set_adr_type(TypeRawPtr::BOTTOM);
695
kit->set_predefined_output_for_runtime_call(ac, ac->in(TypeFunc::Memory), raw_adr_type);
696
} else {
697
kit->set_all_memory(n);
698
}
699
}
700
701
Node* BarrierSetC2::obj_allocate(PhaseMacroExpand* macro, Node* mem, Node* toobig_false, Node* size_in_bytes,
702
Node*& i_o, Node*& needgc_ctrl,
703
Node*& fast_oop_ctrl, Node*& fast_oop_rawmem,
704
intx prefetch_lines) const {
705
706
Node* eden_top_adr;
707
Node* eden_end_adr;
708
709
macro->set_eden_pointers(eden_top_adr, eden_end_adr);
710
711
// Load Eden::end. Loop invariant and hoisted.
712
//
713
// Note: We set the control input on "eden_end" and "old_eden_top" when using
714
// a TLAB to work around a bug where these values were being moved across
715
// a safepoint. These are not oops, so they cannot be include in the oop
716
// map, but they can be changed by a GC. The proper way to fix this would
717
// be to set the raw memory state when generating a SafepointNode. However
718
// this will require extensive changes to the loop optimization in order to
719
// prevent a degradation of the optimization.
720
// See comment in memnode.hpp, around line 227 in class LoadPNode.
721
Node *eden_end = macro->make_load(toobig_false, mem, eden_end_adr, 0, TypeRawPtr::BOTTOM, T_ADDRESS);
722
723
// We need a Region for the loop-back contended case.
724
enum { fall_in_path = 1, contended_loopback_path = 2 };
725
Node *contended_region;
726
Node *contended_phi_rawmem;
727
if (UseTLAB) {
728
contended_region = toobig_false;
729
contended_phi_rawmem = mem;
730
} else {
731
contended_region = new RegionNode(3);
732
contended_phi_rawmem = new PhiNode(contended_region, Type::MEMORY, TypeRawPtr::BOTTOM);
733
// Now handle the passing-too-big test. We fall into the contended
734
// loop-back merge point.
735
contended_region ->init_req(fall_in_path, toobig_false);
736
contended_phi_rawmem->init_req(fall_in_path, mem);
737
macro->transform_later(contended_region);
738
macro->transform_later(contended_phi_rawmem);
739
}
740
741
// Load(-locked) the heap top.
742
// See note above concerning the control input when using a TLAB
743
Node *old_eden_top = UseTLAB
744
? new LoadPNode (toobig_false, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM, MemNode::unordered)
745
: new LoadPLockedNode(contended_region, contended_phi_rawmem, eden_top_adr, MemNode::acquire);
746
747
macro->transform_later(old_eden_top);
748
// Add to heap top to get a new heap top
749
Node *new_eden_top = new AddPNode(macro->top(), old_eden_top, size_in_bytes);
750
macro->transform_later(new_eden_top);
751
// Check for needing a GC; compare against heap end
752
Node *needgc_cmp = new CmpPNode(new_eden_top, eden_end);
753
macro->transform_later(needgc_cmp);
754
Node *needgc_bol = new BoolNode(needgc_cmp, BoolTest::ge);
755
macro->transform_later(needgc_bol);
756
IfNode *needgc_iff = new IfNode(contended_region, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN);
757
macro->transform_later(needgc_iff);
758
759
// Plug the failing-heap-space-need-gc test into the slow-path region
760
Node *needgc_true = new IfTrueNode(needgc_iff);
761
macro->transform_later(needgc_true);
762
needgc_ctrl = needgc_true;
763
764
// No need for a GC. Setup for the Store-Conditional
765
Node *needgc_false = new IfFalseNode(needgc_iff);
766
macro->transform_later(needgc_false);
767
768
i_o = macro->prefetch_allocation(i_o, needgc_false, contended_phi_rawmem,
769
old_eden_top, new_eden_top, prefetch_lines);
770
771
Node* fast_oop = old_eden_top;
772
773
// Store (-conditional) the modified eden top back down.
774
// StorePConditional produces flags for a test PLUS a modified raw
775
// memory state.
776
if (UseTLAB) {
777
Node* store_eden_top =
778
new StorePNode(needgc_false, contended_phi_rawmem, eden_top_adr,
779
TypeRawPtr::BOTTOM, new_eden_top, MemNode::unordered);
780
macro->transform_later(store_eden_top);
781
fast_oop_ctrl = needgc_false; // No contention, so this is the fast path
782
fast_oop_rawmem = store_eden_top;
783
} else {
784
Node* store_eden_top =
785
new StorePConditionalNode(needgc_false, contended_phi_rawmem, eden_top_adr,
786
new_eden_top, fast_oop/*old_eden_top*/);
787
macro->transform_later(store_eden_top);
788
Node *contention_check = new BoolNode(store_eden_top, BoolTest::ne);
789
macro->transform_later(contention_check);
790
store_eden_top = new SCMemProjNode(store_eden_top);
791
macro->transform_later(store_eden_top);
792
793
// If not using TLABs, check to see if there was contention.
794
IfNode *contention_iff = new IfNode (needgc_false, contention_check, PROB_MIN, COUNT_UNKNOWN);
795
macro->transform_later(contention_iff);
796
Node *contention_true = new IfTrueNode(contention_iff);
797
macro->transform_later(contention_true);
798
// If contention, loopback and try again.
799
contended_region->init_req(contended_loopback_path, contention_true);
800
contended_phi_rawmem->init_req(contended_loopback_path, store_eden_top);
801
802
// Fast-path succeeded with no contention!
803
Node *contention_false = new IfFalseNode(contention_iff);
804
macro->transform_later(contention_false);
805
fast_oop_ctrl = contention_false;
806
807
// Bump total allocated bytes for this thread
808
Node* thread = new ThreadLocalNode();
809
macro->transform_later(thread);
810
Node* alloc_bytes_adr = macro->basic_plus_adr(macro->top()/*not oop*/, thread,
811
in_bytes(JavaThread::allocated_bytes_offset()));
812
Node* alloc_bytes = macro->make_load(fast_oop_ctrl, store_eden_top, alloc_bytes_adr,
813
0, TypeLong::LONG, T_LONG);
814
#ifdef _LP64
815
Node* alloc_size = size_in_bytes;
816
#else
817
Node* alloc_size = new ConvI2LNode(size_in_bytes);
818
macro->transform_later(alloc_size);
819
#endif
820
Node* new_alloc_bytes = new AddLNode(alloc_bytes, alloc_size);
821
macro->transform_later(new_alloc_bytes);
822
fast_oop_rawmem = macro->make_store(fast_oop_ctrl, store_eden_top, alloc_bytes_adr,
823
0, new_alloc_bytes, T_LONG);
824
}
825
return fast_oop;
826
}
827
828
#define XTOP LP64_ONLY(COMMA phase->top())
829
830
void BarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
831
Node* ctrl = ac->in(TypeFunc::Control);
832
Node* mem = ac->in(TypeFunc::Memory);
833
Node* src = ac->in(ArrayCopyNode::Src);
834
Node* src_offset = ac->in(ArrayCopyNode::SrcPos);
835
Node* dest = ac->in(ArrayCopyNode::Dest);
836
Node* dest_offset = ac->in(ArrayCopyNode::DestPos);
837
Node* length = ac->in(ArrayCopyNode::Length);
838
839
Node* payload_src = phase->basic_plus_adr(src, src_offset);
840
Node* payload_dst = phase->basic_plus_adr(dest, dest_offset);
841
842
const char* copyfunc_name = "arraycopy";
843
address copyfunc_addr = phase->basictype2arraycopy(T_LONG, NULL, NULL, true, copyfunc_name, true);
844
845
const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
846
const TypeFunc* call_type = OptoRuntime::fast_arraycopy_Type();
847
848
Node* call = phase->make_leaf_call(ctrl, mem, call_type, copyfunc_addr, copyfunc_name, raw_adr_type, payload_src, payload_dst, length XTOP);
849
phase->transform_later(call);
850
851
phase->igvn().replace_node(ac, call);
852
}
853
854
#undef XTOP
855
856