1 /*
2 * Copyright (c) 2017, 2026, 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 "ci/ciInlineKlass.hpp"
26 #include "gc/shared/barrierSet.hpp"
27 #include "gc/shared/c2/barrierSetC2.hpp"
28 #include "gc/shared/gc_globals.hpp"
29 #include "memory/resourceArea.hpp"
30 #include "oops/accessDecorators.hpp"
31 #include "opto/addnode.hpp"
32 #include "opto/castnode.hpp"
33 #include "opto/cfgnode.hpp"
34 #include "opto/compile.hpp"
35 #include "opto/convertnode.hpp"
36 #include "opto/graphKit.hpp"
37 #include "opto/inlinetypenode.hpp"
38 #include "opto/memnode.hpp"
39 #include "opto/movenode.hpp"
40 #include "opto/multnode.hpp"
41 #include "opto/narrowptrnode.hpp"
42 #include "opto/node.hpp"
43 #include "opto/opcodes.hpp"
44 #include "opto/phaseX.hpp"
45 #include "opto/rootnode.hpp"
46 #include "opto/subnode.hpp"
47 #include "opto/type.hpp"
48 #include "utilities/globalDefinitions.hpp"
49 #include "utilities/growableArray.hpp"
50 #include "utilities/pair.hpp"
51 #include "utilities/tuple.hpp"
52
53 // Clones the inline type to handle control flow merges involving multiple inline types.
54 // The inputs are replaced by PhiNodes to represent the merged values for the given region.
55 // init_with_top: input of phis above the returned InlineTypeNode are initialized to top.
56 InlineTypeNode* InlineTypeNode::clone_with_phis(PhaseGVN* gvn, Node* region, SafePointNode* map, bool is_non_null, bool init_with_top) {
57 InlineTypeNode* vt = clone_if_required(gvn, map);
58 const Type* t = Type::get_const_type(inline_klass());
59 gvn->set_type(vt, t);
60 vt->as_InlineType()->set_type(t);
61
62 Node* const top = gvn->C->top();
63
64 // Create a PhiNode for merging the oop values
65 PhiNode* oop = PhiNode::make(region, init_with_top ? top : vt->get_oop(), t);
66 gvn->set_type(oop, t);
67 gvn->record_for_igvn(oop);
68 vt->set_oop(*gvn, oop);
69
70 // Create a PhiNode for merging the is_buffered values
71 t = Type::get_const_basic_type(T_BOOLEAN);
72 Node* is_buffered_node = PhiNode::make(region, init_with_top ? top : vt->get_is_buffered(), t);
73 gvn->set_type(is_buffered_node, t);
74 gvn->record_for_igvn(is_buffered_node);
75 vt->set_req(IsBuffered, is_buffered_node);
76
77 // Create a PhiNode for merging the null_marker values
78 Node* null_marker_node;
79 if (is_non_null) {
80 null_marker_node = gvn->intcon(1);
81 } else {
82 t = Type::get_const_basic_type(T_BOOLEAN);
83 null_marker_node = PhiNode::make(region, init_with_top ? top : vt->get_null_marker(), t);
84 gvn->set_type(null_marker_node, t);
85 gvn->record_for_igvn(null_marker_node);
86 }
87 vt->set_req(NullMarker, null_marker_node);
88
89 // Create a PhiNode each for merging the field values
90 for (uint i = 0; i < vt->field_count(); ++i) {
91 ciField* field = vt->field(i);
92 ciType* type = field->type();
93 Node* value = vt->field_value(i);
94 if (field->is_flat()) {
95 // Handle flat fields recursively
96 value = value->as_InlineType()->clone_with_phis(gvn, region, map);
97 } else {
98 t = Type::get_const_type(type);
99 value = PhiNode::make(region, init_with_top ? top : value, t);
100 gvn->set_type(value, t);
101 gvn->record_for_igvn(value);
102 }
103 vt->set_field_value(i, value);
104 }
105 gvn->record_for_igvn(vt);
106 return vt;
107 }
108
109 // Checks if the inputs of the InlineTypeNode were replaced by PhiNodes
110 // for the given region (see InlineTypeNode::clone_with_phis).
111 bool InlineTypeNode::has_phi_inputs(Node* region) const {
112 // Check oop input
113 bool result = get_oop()->is_Phi() && get_oop()->as_Phi()->region() == region;
114 #ifdef ASSERT
115 if (result) {
116 // Check all field value inputs for consistency
117 for (uint i = 0; i < field_count(); ++i) {
118 Node* n = field_value(i);
119 if (n->is_InlineType()) {
120 assert(n->as_InlineType()->has_phi_inputs(region), "inconsistent phi inputs");
121 } else {
122 assert(n->is_Phi() && n->as_Phi()->region() == region, "inconsistent phi inputs");
123 }
124 }
125 }
126 #endif
127 return result;
128 }
129
130 // Merges 'this' with 'other' by updating the input PhiNodes added by 'clone_with_phis'
131 InlineTypeNode* InlineTypeNode::merge_with(PhaseGVN* gvn, const InlineTypeNode* other, int phi_index, bool transform) {
132 assert(inline_klass() == other->inline_klass(), "Merging incompatible types");
133
134 // Merge oop inputs
135 PhiNode* phi = get_oop()->as_Phi();
136 phi->set_req(phi_index, other->get_oop());
137 if (transform) {
138 set_oop(*gvn, gvn->transform(phi));
139 }
140
141 // Merge is_buffered inputs
142 phi = get_is_buffered()->as_Phi();
143 phi->set_req(phi_index, other->get_is_buffered());
144 if (transform) {
145 set_req(IsBuffered, gvn->transform(phi));
146 }
147
148 // Merge null_marker inputs
149 Node* null_marker = get_null_marker();
150 if (null_marker->is_Phi()) {
151 phi = null_marker->as_Phi();
152 phi->set_req(phi_index, other->get_null_marker());
153 if (transform) {
154 set_req(NullMarker, gvn->transform(phi));
155 }
156 } else {
157 assert(null_marker->find_int_con(0) == 1, "only with a non null inline type");
158 }
159
160 // Merge field values
161 for (uint i = 0; i < field_count(); ++i) {
162 Node* val1 = field_value(i);
163 Node* val2 = other->field_value(i);
164 if (field(i)->is_flat()) {
165 if (val2->is_top()) {
166 // The path where 'other' is used is dying. Therefore, we do not need to process the merge with 'other' further.
167 // The phi inputs of 'this' at 'phi_index' will eventually be removed.
168 break;
169 } else if (val2->is_Phi()) {
170 val2 = gvn->transform(val2);
171 }
172
173 assert(val1->is_InlineType() && val2->is_InlineType(), "must be InlineTypeNode: %s - %s", val1->Name(), val2->Name());
174 val1->as_InlineType()->merge_with(gvn, val2->as_InlineType(), phi_index, transform);
175 } else {
176 assert(val1->is_Phi(), "must be a phi node %s", val1->Name());
177 val1->set_req(phi_index, val2);
178 }
179 if (transform) {
180 set_field_value(i, gvn->transform(val1));
181 }
182 }
183 return this;
184 }
185
186 // Adds a new merge path to an inline type node with phi inputs
187 void InlineTypeNode::add_new_path(Node* region) const {
188 assert(has_phi_inputs(region), "must have phi inputs");
189
190 PhiNode* phi = get_oop()->as_Phi();
191 phi->add_req(nullptr);
192 assert(phi->req() == region->req(), "must be same size as region");
193
194 phi = get_is_buffered()->as_Phi();
195 phi->add_req(nullptr);
196 assert(phi->req() == region->req(), "must be same size as region");
197
198 phi = get_null_marker()->as_Phi();
199 phi->add_req(nullptr);
200 assert(phi->req() == region->req(), "must be same size as region");
201
202 for (uint i = 0; i < field_count(); ++i) {
203 Node* val = field_value(i);
204 if (val->is_InlineType()) {
205 val->as_InlineType()->add_new_path(region);
206 } else {
207 val->as_Phi()->add_req(nullptr);
208 assert(val->req() == region->req(), "must be same size as region");
209 }
210 }
211 }
212
213 Node* InlineTypeNode::field_value(uint index) const {
214 assert(index < field_count(), "index out of bounds");
215 return in(Values + index);
216 }
217
218 // Get the value of the field at the given offset.
219 // If 'recursive' is true, flat inline type fields will be resolved recursively.
220 Node* InlineTypeNode::field_value_by_offset(int offset, bool recursive) const {
221 // Find the declared field which contains the field we are looking for
222 int index = inline_klass()->field_index_by_offset(offset);
223 Node* value = field_value(index);
224 assert(value != nullptr, "field value not found");
225 ciField* field = this->field(index);
226 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
227
228 if (value->is_top()) {
229 // The graph is dying but a load may still ask for a nested field
230 // inside a flattened field before the dead load itself is folded away.
231 assert(offset == field->offset_in_bytes() || field->is_flat(), "offset mismatch");
232 return value;
233 }
234 if (!recursive || !field->is_flat()) {
235 assert(offset == field->offset_in_bytes(), "offset mismatch");
236 return value;
237 }
238
239 // Flat inline type field
240 InlineTypeNode* vt = value->as_InlineType();
241 assert(field->is_flat(), "must be flat");
242 if (offset == field->null_marker_offset()) {
243 return vt->get_null_marker();
244 } else {
245 int sub_offset = offset - field->offset_in_bytes(); // Offset of the flattened field inside the declared field
246 sub_offset += vt->inline_klass()->payload_offset(); // Add header size
247 return vt->field_value_by_offset(sub_offset, recursive);
248 }
249 }
250
251 void InlineTypeNode::set_field_value(uint index, Node* value) {
252 assert(index < field_count(), "index out of bounds");
253 set_req(Values + index, value);
254 }
255
256 void InlineTypeNode::set_field_value_by_offset(int offset, Node* value) {
257 set_field_value(field_index(offset), value);
258 }
259
260 uint InlineTypeNode::field_index(int offset) const {
261 uint i = 0;
262 for (; i < field_count() && field(i)->offset_in_bytes() != offset; i++) { }
263 assert(i < field_count(), "field not found");
264 return i;
265 }
266
267 ciField* InlineTypeNode::field(uint index) const {
268 assert(index < field_count(), "index out of bounds");
269 return inline_klass()->declared_nonstatic_field_at(index);
270 }
271
272 uint InlineTypeNode::add_fields_to_safepoint(Unique_Node_List& worklist, SafePointNode* sfpt) const {
273 uint cnt = 0;
274 for (uint i = 0; i < field_count(); ++i) {
275 Node* value = field_value(i);
276 ciField* field = this->field(i);
277 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
278 if (field->is_flat()) {
279 InlineTypeNode* vt = value->as_InlineType();
280 cnt += vt->add_fields_to_safepoint(worklist, sfpt);
281 if (!field->is_null_free()) {
282 // The null marker of a flat field is added right after we scalarize that field
283 sfpt->add_req(vt->get_null_marker());
284 cnt++;
285 }
286 continue;
287 }
288 if (value->is_InlineType()) {
289 // Add inline type to the worklist to process later
290 worklist.push(value);
291 }
292 sfpt->add_req(value);
293 cnt++;
294 }
295 return cnt;
296 }
297
298 void InlineTypeNode::make_scalar_in_safepoint(PhaseIterGVN* igvn, Unique_Node_List& worklist, SafePointNode* sfpt) const {
299 JVMState* jvms = sfpt->jvms();
300 assert(jvms != nullptr, "missing JVMS");
301 uint first_ind = (sfpt->req() - jvms->scloff());
302
303 // Iterate over the inline type fields in order of increasing offset and add the
304 // field values to the safepoint. Nullable inline types have a null marker field that
305 // needs to be checked before using the field values.
306 sfpt->add_req(get_null_marker());
307 uint nfields = add_fields_to_safepoint(worklist, sfpt);
308 jvms->set_endoff(sfpt->req());
309 // Replace safepoint edge by SafePointScalarObjectNode
310 SafePointScalarObjectNode* sobj = new SafePointScalarObjectNode(type()->isa_instptr(),
311 nullptr,
312 first_ind,
313 sfpt->jvms()->depth(),
314 nfields);
315 sobj->init_req(0, igvn->C->root());
316 sobj = igvn->transform(sobj)->as_SafePointScalarObject();
317 igvn->rehash_node_delayed(sfpt);
318 for (uint i = jvms->debug_start(); i < jvms->debug_end(); i++) {
319 Node* debug = sfpt->in(i);
320 if (debug != nullptr && debug->uncast() == this) {
321 sfpt->set_req(i, sobj);
322 }
323 }
324 }
325
326 void InlineTypeNode::make_scalar_in_safepoints(PhaseIterGVN* igvn, bool allow_oop) {
327 make_scalar_in_safepoints(igvn, allow_oop, nullptr);
328 }
329
330 void InlineTypeNode::make_scalar_in_safepoints(PhaseIterGVN* igvn, bool allow_oop, SafePointNode* safepoint) {
331 // If the inline type has a constant or loaded oop, use the oop instead of scalarization
332 // in the safepoint to avoid keeping field loads live just for the debug info.
333 Node* oop = get_oop();
334 bool use_oop = false;
335 if (allow_oop && is_allocated(igvn) && oop->is_Phi()) {
336 Unique_Node_List worklist;
337 VectorSet visited;
338 visited.set(oop->_idx);
339 worklist.push(oop);
340 use_oop = true;
341 while (worklist.size() > 0 && use_oop) {
342 Node* n = worklist.pop();
343 for (uint i = 1; i < n->req(); i++) {
344 Node* in = n->in(i);
345 if (in->is_Phi() && !visited.test_set(in->_idx)) {
346 worklist.push(in);
347 } else if (!(in->is_Con() || in->is_Parm())) {
348 use_oop = false;
349 break;
350 }
351 }
352 }
353 } else {
354 use_oop = allow_oop && is_allocated(igvn) &&
355 (oop->is_Con() || oop->is_Parm() || oop->is_Load() || (oop->isa_DecodeN() && oop->in(1)->is_Load()));
356 }
357
358 ResourceMark rm;
359 Unique_Node_List safepoints;
360 if (safepoint == nullptr) {
361 // Gathering all SafePoint users of `this`...
362 Unique_Node_List worklist;
363 worklist.push(this);
364 while (worklist.size() > 0) {
365 Node* n = worklist.pop();
366 for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
367 Node* use = n->fast_out(i);
368 if (use->is_SafePoint() && !use->is_CallLeaf() && (!use->is_Call() || use->as_Call()->has_debug_use(n))) {
369 safepoints.push(use);
370 } else if (use->is_ConstraintCast()) {
371 worklist.push(use);
372 }
373 }
374 }
375 } else {
376 // ...or just the provided one if given.
377 safepoints.push(safepoint);
378 }
379
380 Unique_Node_List vt_worklist;
381 // Process all safepoint uses and scalarize inline type
382 while (safepoints.size() > 0) {
383 SafePointNode* sfpt = safepoints.pop()->as_SafePoint();
384 if (use_oop) {
385 for (uint i = sfpt->jvms()->debug_start(); i < sfpt->jvms()->debug_end(); i++) {
386 Node* debug = sfpt->in(i);
387 if (debug != nullptr && debug->uncast() == this) {
388 sfpt->set_req(i, get_oop());
389 }
390 }
391 igvn->rehash_node_delayed(sfpt);
392 } else {
393 make_scalar_in_safepoint(igvn, vt_worklist, sfpt);
394 }
395 }
396 // Now scalarize non-flat fields
397 for (uint i = 0; i < vt_worklist.size(); ++i) {
398 InlineTypeNode* vt = vt_worklist.at(i)->isa_InlineType();
399 vt->make_scalar_in_safepoints(igvn);
400 }
401 if (outcnt() == 0) {
402 igvn->record_for_igvn(this);
403 }
404 }
405
406 void InlineTypeNode::load(GraphKit* kit, Node* base, Node* ptr, bool immutable_memory, bool trust_null_free_oop, DecoratorSet decorators) {
407 // Initialize the inline type by loading its field values from
408 // memory and adding the values as input edges to the node.
409 ciInlineKlass* vk = inline_klass();
410 for (uint i = 0; i < field_count(); ++i) {
411 ciField* field = this->field(i);
412 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
413 int field_off = field->offset_in_bytes() - vk->payload_offset();
414 Node* field_ptr = kit->basic_plus_adr(base, ptr, field_off);
415 Node* value = nullptr;
416 ciType* ft = field->type();
417 bool field_null_free = field->is_null_free();
418 if (field->is_flat()) {
419 // Recursively load the flat inline type field
420 ciInlineKlass* fvk = ft->as_inline_klass();
421 bool atomic = field->is_atomic();
422 value = make_from_flat_impl(kit, fvk, base, field_ptr, atomic, immutable_memory,
423 field_null_free, trust_null_free_oop && field_null_free, decorators);
424 } else {
425 // Load field value from memory
426 BasicType bt = type2field[ft->basic_type()];
427 assert(is_java_primitive(bt) || field_ptr->bottom_type()->is_ptr_to_narrowoop() == UseCompressedOops, "inconsistent");
428 const Type* val_type = Type::get_const_type(ft);
429 if (trust_null_free_oop && field_null_free) {
430 val_type = val_type->join_speculative(TypePtr::NOTNULL);
431 }
432 const TypePtr* field_ptr_type = (decorators & C2_MISMATCHED) == 0 ? kit->gvn().type(field_ptr)->is_ptr() : TypeRawPtr::BOTTOM;
433 value = kit->access_load_at(base, field_ptr, field_ptr_type, val_type, bt, decorators);
434 }
435 set_field_value(i, value);
436 }
437 }
438
439 void InlineTypeNode::store_flat(GraphKit* kit, Node* base, Node* ptr, bool atomic, bool immutable_memory, bool null_free, DecoratorSet decorators) {
440 ciInlineKlass* vk = inline_klass();
441 bool do_atomic = atomic;
442 // With immutable memory, a non-atomic load and an atomic load are the same
443 if (immutable_memory) {
444 do_atomic = false;
445 }
446 // If there is only one flattened field, a non-atomic load and an atomic load are the same
447 if (vk->is_naturally_atomic(null_free)) {
448 do_atomic = false;
449 }
450
451 if (!do_atomic) {
452 if (!null_free) {
453 int nm_offset = vk->null_marker_offset_in_payload();
454 Node* nm_ptr = kit->basic_plus_adr(base, ptr, nm_offset);
455 const TypePtr* nm_ptr_type = (decorators & C2_MISMATCHED) == 0 ? kit->gvn().type(nm_ptr)->is_ptr() : TypeRawPtr::BOTTOM;
456 kit->access_store_at(base, nm_ptr, nm_ptr_type, get_null_marker(), TypeInt::BOOL, T_BOOLEAN, decorators);
457 }
458 store(kit, base, ptr, immutable_memory, decorators);
459 return;
460 }
461
462 StoreFlatNode::store(kit, base, ptr, this, null_free, decorators);
463 }
464
465 void InlineTypeNode::store_flat_array(GraphKit* kit, Node* base, Node* idx) {
466 PhaseGVN& gvn = kit->gvn();
467 DecoratorSet decorators = IN_HEAP | IS_ARRAY | MO_UNORDERED;
468 kit->C->set_flat_accesses();
469 ciInlineKlass* vk = inline_klass();
470 assert(vk->maybe_flat_in_array(), "element type %s cannot be flat in array", vk->name()->as_utf8());
471
472 RegionNode* region = new RegionNode(4);
473 gvn.set_type(region, Type::CONTROL);
474 kit->record_for_igvn(region);
475
476 Node* input_memory_state = kit->reset_memory();
477 kit->set_all_memory(input_memory_state);
478
479 PhiNode* mem = PhiNode::make(region, input_memory_state, Type::MEMORY, TypePtr::BOTTOM);
480 gvn.set_type(mem, Type::MEMORY);
481 kit->record_for_igvn(mem);
482
483 PhiNode* io = PhiNode::make(region, kit->i_o(), Type::ABIO);
484 gvn.set_type(io, Type::ABIO);
485 kit->record_for_igvn(io);
486
487 Node* bol_null_free = kit->null_free_array_test(base); // Argument evaluation order is undefined in C++ and since this sets control, it needs to come first
488 IfNode* iff_null_free = kit->create_and_map_if(kit->control(), bol_null_free, PROB_FAIR, COUNT_UNKNOWN);
489
490 // Nullable
491 kit->set_control(kit->IfFalse(iff_null_free));
492 if (!kit->stopped()) {
493 assert(vk->has_nullable_atomic_layout(), "element type %s does not have a nullable flat layout", vk->name()->as_utf8());
494 kit->set_all_memory(input_memory_state);
495 Node* cast = kit->cast_to_flat_array_exact(base, vk, false, true);
496 Node* ptr = kit->array_element_address(cast, idx, T_FLAT_ELEMENT);
497 store_flat(kit, cast, ptr, true, false, false, decorators);
498
499 region->init_req(1, kit->control());
500 mem->set_req(1, kit->reset_memory());
501 io->set_req(1, kit->i_o());
502 }
503
504 // Null-free
505 kit->set_control(kit->IfTrue(iff_null_free));
506 if (!kit->stopped()) {
507 kit->set_all_memory(input_memory_state);
508
509 Node* bol_atomic = kit->null_free_atomic_array_test(base, vk);
510 IfNode* iff_atomic = kit->create_and_map_if(kit->control(), bol_atomic, PROB_FAIR, COUNT_UNKNOWN);
511
512 // Atomic
513 kit->set_control(kit->IfTrue(iff_atomic));
514 if (!kit->stopped()) {
515 assert(vk->has_null_free_atomic_layout(), "element type %s does not have a null-free atomic flat layout", vk->name()->as_utf8());
516 kit->set_all_memory(input_memory_state);
517 Node* cast = kit->cast_to_flat_array_exact(base, vk, true, true);
518 Node* ptr = kit->array_element_address(cast, idx, T_FLAT_ELEMENT);
519 store_flat(kit, cast, ptr, true, false, true, decorators);
520
521 region->init_req(2, kit->control());
522 mem->set_req(2, kit->reset_memory());
523 io->set_req(2, kit->i_o());
524 }
525
526 // Non-atomic
527 kit->set_control(kit->IfFalse(iff_atomic));
528 if (!kit->stopped()) {
529 assert(vk->has_null_free_non_atomic_layout(), "element type %s does not have a null-free non-atomic flat layout", vk->name()->as_utf8());
530 kit->set_all_memory(input_memory_state);
531 Node* cast = kit->cast_to_flat_array_exact(base, vk, true, false);
532 Node* ptr = kit->array_element_address(cast, idx, T_FLAT_ELEMENT);
533 store_flat(kit, cast, ptr, false, false, true, decorators);
534
535 region->init_req(3, kit->control());
536 mem->set_req(3, kit->reset_memory());
537 io->set_req(3, kit->i_o());
538 }
539 }
540
541 kit->set_control(gvn.transform(region));
542 kit->set_all_memory(gvn.transform(mem));
543 kit->set_i_o(gvn.transform(io));
544 }
545
546 void InlineTypeNode::store(GraphKit* kit, Node* base, Node* ptr, bool immutable_memory, DecoratorSet decorators) const {
547 // Write field values to memory
548 ciInlineKlass* vk = inline_klass();
549 for (uint i = 0; i < field_count(); ++i) {
550 ciField* field = this->field(i);
551 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
552 int field_off = field->offset_in_bytes() - vk->payload_offset();
553 Node* field_val = field_value(i);
554 bool field_null_free = field->is_null_free();
555 ciType* ft = field->type();
556 Node* field_ptr = kit->basic_plus_adr(base, ptr, field_off);
557 if (field->is_flat()) {
558 // Recursively store the flat inline type field
559 bool atomic = field->is_atomic();
560 field_val->as_InlineType()->store_flat(kit, base, field_ptr, atomic, immutable_memory, field_null_free, decorators);
561 } else {
562 // Store field value to memory
563 BasicType bt = type2field[ft->basic_type()];
564 const TypePtr* field_ptr_type = (decorators & C2_MISMATCHED) == 0 ? kit->gvn().type(field_ptr)->is_ptr() : TypeRawPtr::BOTTOM;
565 const Type* val_type = Type::get_const_type(ft);
566 kit->access_store_at(base, field_ptr, field_ptr_type, field_val, val_type, bt, decorators);
567 }
568 }
569 }
570
571 // If a value class contains cycle, bail out from trying to expand substitutability check involving it
572 static bool check_cycle(ciInlineKlass* vk) {
573 ResourceMark rm;
574 GrowableArray<Pair<ciInlineKlass*, int>> visited;
575 visited.push(Pair(vk, 0));
576 while (visited.is_nonempty()) {
577 ciInlineKlass* current = visited.top().first;
578 bool finish = true;
579 for (int field_idx = visited.top().second; field_idx < current->nof_nonstatic_fields(); field_idx++) {
580 ciField* field = current->nonstatic_field_at(field_idx);
581 ciType* ft = field->type();
582 if (!ft->is_inlinetype()) {
583 continue;
584 } else if (visited.find_if([&](const auto& entry) { return entry.first == ft; }) >= 0) {
585 return true;
586 } else {
587 visited.top().second = field_idx + 1;
588 visited.push(Pair(ft->as_inline_klass(), 0));
589 finish = false;
590 break;
591 }
592 }
593 if (finish) {
594 visited.pop();
595 }
596 }
597 return false;
598 }
599
600 // Check if a substitutability check between 'lhs' and 'rhs' can be implemented in IR
601 bool InlineTypeNode::can_emit_substitutability_check(Node* lhs, Node* rhs) {
602 if (!lhs->bottom_type()->isa_ptr() ||
603 (rhs != nullptr && !rhs->bottom_type()->isa_ptr())) {
604 return false;
605 }
606
607 if (rhs != nullptr && lhs->eqv_uncast(rhs)) {
608 return true;
609 }
610
611 if (!lhs->bottom_type()->is_ptr()->can_be_inline_type() ||
612 (rhs != nullptr && !rhs->bottom_type()->is_ptr()->can_be_inline_type())) {
613 return true;
614 }
615
616 if (!lhs->is_InlineType() && (rhs == nullptr || !rhs->is_InlineType())) {
617 return false;
618 }
619
620 if (!lhs->is_InlineType()) {
621 swap(lhs, rhs);
622 }
623
624 InlineTypeNode* lhs_inline = lhs->as_InlineType();
625 InlineTypeNode* rhs_inline = rhs != nullptr ? rhs->isa_InlineType() : nullptr;
626 if (rhs_inline != nullptr && lhs_inline->type()->inline_klass() != rhs_inline->type()->inline_klass()) {
627 // Dead code, can skip the substitutability check
628 return true;
629 }
630
631 if (check_cycle(lhs_inline->inline_klass())) {
632 return false;
633 }
634
635 for (uint i = 0; i < lhs_inline->field_count(); i++) {
636 ciType* ft = lhs_inline->field(i)->type();
637 if (!ft->can_be_inline_klass()) {
638 continue;
639 }
640
641 Node* lhs_fv = lhs_inline->field_value(i);
642 Node* rhs_fv = rhs_inline != nullptr ? rhs_inline->field_value(i) : nullptr;
643 if (!can_emit_substitutability_check(lhs_fv, rhs_fv)) {
644 return false;
645 }
646 }
647 return true;
648 }
649
650 // Compare lhs and rhs given they are not value objects
651 static void emit_substitutability_check_primitive(GraphKit* kit, PhiNode* result, Node* lhs, Node* rhs, BasicType bt) {
652 PhaseGVN& gvn = kit->gvn();
653 Node* cmp;
654 if (bt == T_INT || is_subword_type(bt)) {
655 cmp = kit->CmpI(lhs, rhs);
656 } else if (bt == T_LONG) {
657 cmp = kit->CmpL(lhs, rhs);
658 } else if (bt == T_FLOAT) {
659 lhs = gvn.transform(new MoveF2INode(lhs));
660 rhs = gvn.transform(new MoveF2INode(rhs));
661 cmp = kit->CmpI(lhs, rhs);
662 } else if (bt == T_DOUBLE) {
663 lhs = gvn.transform(new MoveD2LNode(lhs));
664 rhs = gvn.transform(new MoveD2LNode(rhs));
665 cmp = kit->CmpL(lhs, rhs);
666 } else {
667 assert(is_reference_type(bt), "unexpected bt %s", type2name(bt));
668 cmp = kit->CmpP(lhs, rhs);
669 }
670
671 Node* bol = kit->Bool(cmp, BoolTest::eq);
672 IfNode* iff = kit->create_and_map_if(kit->control(), bol, PROB_FAIR, COUNT_UNKNOWN);
673
674 Node* iff_false = kit->IfFalse(iff);
675 result->add_req(kit->intcon(0));
676 result->region()->add_req(iff_false);
677
678 Node* iff_true = kit->IfTrue(iff);
679 kit->set_control(iff_true);
680 }
681
682 // Try to see what should be done with lhs and rhs. Either we can emit the answer if it is simple,
683 // give up and emit a call to runtime, or start comparing the value objects field-by-field. In the
684 // last case, NodeSentinel is returned.
685 static Node* emit_substitutability_check_pointer(GraphKit* kit, PhiNode* result, Node* lhs, Node* rhs) {
686 PhaseGVN& gvn = kit->gvn();
687 Node* top = kit->C->top();
688 const Type* lhs_type = gvn.type(lhs);
689 const Type* rhs_type = gvn.type(rhs);
690
691 // Dead graph
692 if (lhs_type == Type::TOP || rhs_type == Type::TOP) {
693 kit->set_control(top);
694 return top;
695 }
696
697 Node* cmp = nullptr;
698 if (lhs->eqv_uncast(rhs)) {
699 cmp = kit->intcon(0);
700 } else if (!lhs_type->is_ptr()->can_be_inline_type() || !rhs_type->is_ptr()->can_be_inline_type()) {
701 // If one of the sides is not a value object, can only be substitutable if they are the same
702 cmp = kit->CmpP(lhs, rhs);
703 } else if (lhs_type->is_instptr()->as_klass_type()->join(rhs_type->is_instptr()->as_klass_type())->empty()) {
704 // Both belongs to provably different types, must be different unless both are null. Cannot
705 // rely on the pointer independence alone because different pointers may still be
706 // substitutable.
707 cmp = kit->CmpP(lhs, rhs);
708 }
709 if (cmp != nullptr) {
710 Node* res = kit->Bool(cmp, BoolTest::eq);
711 IfNode* iff = kit->create_and_map_if(kit->control(), res, PROB_FAIR, COUNT_UNKNOWN);
712
713 Node* iff_false = kit->IfFalse(iff);
714 result->region()->add_req(iff_false);
715 result->add_req(gvn.intcon(0));
716
717 Node* iff_true = kit->IfTrue(iff);
718 kit->set_control(iff_true);
719 return iff_true;
720 }
721
722 if (!lhs_type->is_inlinetypeptr() && !rhs_type->is_inlinetypeptr()) {
723 return nullptr;
724 }
725
726 // A cycle, give up
727 ciInlineKlass* vk = lhs_type->is_inlinetypeptr() ? lhs_type->inline_klass() : rhs_type->inline_klass();
728 if (check_cycle(vk)) {
729 return nullptr;
730 }
731
732 return NodeSentinel;
733 }
734
735 Node* InlineTypeNode::emit_substitutability_check(GraphKit* kit, Node* lhs, Node* rhs) {
736 if (!kit->C->allow_macro_nodes()) {
737 // After macro expansion, InlineTypeNodes are also eliminated, creation of new ones then is not
738 // allowed
739 return nullptr;
740 }
741
742 PhaseIterGVN& igvn = *kit->gvn().is_IterGVN();
743 RegionNode* region = new RegionNode(1);
744 PhiNode* result = new PhiNode(region, TypeInt::BOOL);
745 igvn.register_new_node_with_optimizer(region);
746 igvn.register_new_node_with_optimizer(result);
747
748 Node* preprocess = emit_substitutability_check_pointer(kit, result, lhs, rhs);
749 if (preprocess == nullptr) {
750 return nullptr;
751 } else if (preprocess != NodeSentinel) {
752 region->add_req(kit->control());
753 result->add_req(igvn.intcon(1));
754 kit->set_control(region);
755 return result;
756 }
757
758 const Type* lhs_type = igvn.type(lhs);
759 const Type* rhs_type = igvn.type(rhs);
760 assert(!lhs_type->maybe_null() && !rhs_type->maybe_null(), "must check null beforehand");
761 ciInlineKlass* vk = lhs_type->is_inlinetypeptr() ? lhs_type->inline_klass() : rhs_type->inline_klass();
762 const TypeInstPtr* vk_type = TypeOopPtr::make_from_klass(vk)->join(TypePtr::NOTNULL)->is_instptr();
763
764 if (!lhs->is_InlineType()) {
765 if (!lhs_type->higher_equal(vk_type)) {
766 lhs = igvn.transform(new CheckCastPPNode(kit->control(), lhs, vk_type, ConstraintCastNode::DependencyType::NonFloatingNarrowing));
767 }
768 lhs = InlineTypeNode::make_from_oop(kit, lhs, vk);
769 }
770 if (!rhs->is_InlineType()) {
771 if (!rhs_type->higher_equal(vk_type)) {
772 rhs = igvn.transform(new CheckCastPPNode(kit->control(), rhs, vk_type, ConstraintCastNode::DependencyType::NonFloatingNarrowing));
773 }
774 rhs = InlineTypeNode::make_from_oop(kit, rhs, vk);
775 }
776
777 RegionNode* true_region = new RegionNode(3);
778 igvn.register_new_node_with_optimizer(true_region);
779 region->add_req(true_region);
780 result->add_req(igvn.intcon(1));
781
782 // To verify the substitutability of 2 notnull value objects of the same type, we need to check
783 // the substitutability of each field in the objects:
784 //
785 // substitutable(cur_lhs, cur_rhs) {
786 // cur_start_region:
787 //
788 // if (cur_lhs.field1 == null && cur_rhs.field1 == null) {
789 // goto cur_true_field1_region;
790 // } else if ((cur_lhs.field1 == null) != (cur_rhs.field1 == null) {
791 // return false;
792 // } else if (cur_lhs.field1.klass != cur_rhs.field1.klass) {
793 // return false;
794 // }
795 //
796 // cur_start_field1_region:
797 // if (substitutable(cur_lhs.field1, cur_rhs.field1)) {
798 // return false;
799 // }
800 // cur_true_field1_region:
801 //
802 // if (cur_lhs.field2 == null && cur_rhs.field2 == null) {
803 // goto cur_true_field2_region;
804 // } else if ((cur_lhs.field2 == null) != (cur_rhs.field2 == null) {
805 // return false;
806 // } else if (cur_lhs.field2.klass != cur_rhs.field2.klass) {
807 // return false;
808 // }
809 //
810 // cur_start_field2_region:
811 // if (!substitutable(cur_lhs.field1, cur_rhs.field1)) {
812 // return false;
813 // }
814 // cur_true_field2_region:
815 //
816 // ...
817 //
818 // cur_true_fieldn_region:
819 //
820 // cur_true_region:
821 // }
822 //
823 // To avoid recursion, for field values that are value objects, we create the start and end
824 // region for the substitutability check of that field when both sides are notnull, save them on
825 // the worklist to process them later.
826 ResourceMark rm;
827 using WorklistEntry = Tuple<Node*, RegionNode*, InlineTypeNode*, InlineTypeNode*>;
828 GrowableArray<WorklistEntry> worklist;
829 worklist.push(WorklistEntry(kit->control(), true_region, lhs->as_InlineType(), rhs->as_InlineType()));
830 while (worklist.is_nonempty()) {
831 WorklistEntry entry = worklist.pop();
832 Node* cur_start_region = entry.get<0>();
833 RegionNode* cur_true_region = entry.get<1>();
834 InlineTypeNode* cur_lhs = entry.get<2>();
835 InlineTypeNode* cur_rhs = entry.get<3>();
836
837 kit->set_control(cur_start_region);
838 if (kit->stopped()) {
839 break;
840 }
841 ciInlineKlass* vk = cur_lhs->inline_klass();
842 assert(vk == cur_rhs->inline_klass(), "should not reach here otherwise");
843
844 auto is_simple_field = [](ciField* field) {
845 ciType* ft = field->type();
846 return is_java_primitive(ft->basic_type()) || !ft->as_klass()->can_be_inline_klass();
847 };
848
849 // Go through all fields, process the simple ones first
850 for (int field_idx = 0; field_idx < vk->nof_declared_nonstatic_fields(); field_idx++) {
851 ciField* field = vk->declared_nonstatic_field_at(field_idx);
852 if (is_simple_field(field)) {
853 Node* cur_lhs_field = cur_lhs->field_value(field_idx);
854 Node* cur_rhs_field = cur_rhs->field_value(field_idx);
855 emit_substitutability_check_primitive(kit, result, cur_lhs_field, cur_rhs_field, field->type()->basic_type());
856 }
857 }
858
859 for (int field_idx = 0; field_idx < vk->nof_declared_nonstatic_fields(); field_idx++) {
860 ciField* field = vk->declared_nonstatic_field_at(field_idx);
861 if (is_simple_field(field)) {
862 // These fields have already been processed
863 continue;
864 }
865
866 Node* cur_lhs_field = cur_lhs->field_value(field_idx);
867 Node* cur_rhs_field = cur_rhs->field_value(field_idx);
868
869 Node* preprocess = emit_substitutability_check_pointer(kit, result, cur_lhs_field, cur_rhs_field);
870 if (kit->stopped()) {
871 break;
872 } else if (preprocess == nullptr) {
873 // Must emit a substitutability check for this field, give up for now
874 return nullptr;
875 } else if (preprocess != NodeSentinel) {
876 continue;
877 }
878
879 // When field is not null-free, the shape would look like this:
880 //
881 // current_control:
882 // if (cur_lhs_field == null) {
883 // if (cur_rhs_field == null) {
884 // goto field_true_region;
885 // } else {
886 // return false;
887 // }
888 // } else {
889 // if (cur_rhs_field == null) {
890 // return false;
891 // }
892 // }
893 // if (cur_lhs_field.klass != cur_rhs_field.klass) {
894 // return false;
895 // }
896 //
897 // field_start_region:
898 // if (!substitutable(cur_lhs_field, cur_rhs_field)) {
899 // return false;
900 // }
901 // field_true_region:
902 //
903 // The substitutability test between the fields of cur_lhs_field and cur_rhs_field is then
904 // pushed on the worklist to be expanded later.
905 RegionNode* field_true_region = new RegionNode(3);
906 igvn.register_new_node_with_optimizer(field_true_region);
907
908 // Firstly, filter the cases when either is null
909 Node* null_unknown = kit->top();
910 cur_lhs_field = kit->null_check_common(cur_lhs_field, T_OBJECT, false, &null_unknown);
911 if (!null_unknown->is_top()) {
912 PreserveJVMState pjvms(kit);
913 kit->set_control(null_unknown);
914 Node* null_null = kit->top();
915 kit->null_check_common(cur_rhs_field, T_OBJECT, false, &null_null);
916
917 // null - null, skip other checks
918 field_true_region->init_req(1, null_null);
919
920 // null - notnull
921 if (!kit->stopped()) {
922 region->add_req(kit->control());
923 result->add_req(igvn.intcon(0));
924 }
925 }
926 if (kit->stopped()) {
927 // cur_lhs_field is always null
928 kit->set_control(field_true_region);
929 continue;
930 }
931
932 Node* notnull_null = kit->top();
933 cur_rhs_field = kit->null_check_common(cur_rhs_field, T_OBJECT, false, ¬null_null);
934 if (!notnull_null->is_top()) {
935 region->add_req(notnull_null);
936 result->add_req(igvn.intcon(0));
937 }
938
939 if (kit->stopped()) {
940 // cur_rhs_field is always null
941 kit->set_control(field_true_region);
942 continue;
943 }
944 assert(!igvn.type(cur_lhs_field)->maybe_null() && !igvn.type(cur_rhs_field)->maybe_null(), "must be notnull");
945
946 // Can expand this comparison
947 const Type* cur_lhs_field_type = igvn.type(cur_lhs_field);
948 const Type* cur_rhs_field_type = igvn.type(cur_rhs_field);
949 ciInlineKlass* vk = cur_lhs_field_type->is_inlinetypeptr() ? cur_lhs_field_type->inline_klass() : cur_rhs_field_type->inline_klass();
950 const TypeInstKlassPtr* vk_klass_type = TypeInstKlassPtr::make(vk, Type::ignore_interfaces);
951 Node* vk_klass = igvn.makecon(vk_klass_type);
952
953 // Both must be vk
954 Node* not_vk = kit->top();
955 cur_lhs_field = kit->gen_checkcast(cur_lhs_field, vk_klass, ¬_vk);
956 if (!not_vk->is_top()) {
957 region->add_req(not_vk);
958 result->add_req(igvn.intcon(0));
959 }
960 cur_lhs_field = InlineTypeNode::make_from_oop(kit, cur_lhs_field, vk);
961
962 not_vk = kit->top();
963 cur_rhs_field = kit->gen_checkcast(cur_rhs_field, vk_klass, ¬_vk);
964 if (!not_vk->is_top()) {
965 region->add_req(not_vk);
966 result->add_req(igvn.intcon(0));
967 }
968 cur_rhs_field = InlineTypeNode::make_from_oop(kit, cur_rhs_field, vk);
969
970 if (!kit->stopped()) {
971 // Push the expanded InlineTypeNodes for processing later
972 worklist.push(WorklistEntry(kit->control(), field_true_region, cur_lhs_field->as_InlineType(), cur_rhs_field->as_InlineType()));
973 }
974
975 kit->set_control(field_true_region);
976 }
977
978 cur_true_region->init_req(2, kit->control());
979 kit->set_control(cur_true_region);
980 }
981
982 kit->set_control(region);
983 return result;
984 }
985
986 InlineTypeNode* InlineTypeNode::buffer(GraphKit* kit, bool safe_for_replace) {
987 if (is_allocated(&kit->gvn())) {
988 // Already buffered
989 return this;
990 }
991
992 // Check if inline type is already buffered
993 Node* not_buffered_ctl = kit->top();
994 Node* not_null_oop = kit->null_check_oop(get_oop(), ¬_buffered_ctl, /* never_see_null = */ false, safe_for_replace);
995 if (not_buffered_ctl->is_top()) {
996 // Already buffered
997 InlineTypeNode* vt = clone_if_required(&kit->gvn(), kit->map(), safe_for_replace);
998 vt->set_is_buffered(kit->gvn());
999 vt = kit->gvn().transform(vt)->as_InlineType();
1000 if (safe_for_replace) {
1001 kit->replace_in_map(this, vt);
1002 }
1003 return vt;
1004 }
1005 Node* buffered_ctl = kit->control();
1006 kit->set_control(not_buffered_ctl);
1007
1008 // Inline type is not buffered, check if it is null.
1009 Node* null_ctl = kit->top();
1010 kit->null_check_common(get_null_marker(), T_INT, false, &null_ctl);
1011 bool null_free = null_ctl->is_top();
1012
1013 RegionNode* region = new RegionNode(4);
1014 PhiNode* oop = PhiNode::make(region, not_null_oop, type()->join_speculative(null_free ? TypePtr::NOTNULL : TypePtr::BOTTOM));
1015
1016 // InlineType is already buffered
1017 region->init_req(1, buffered_ctl);
1018 oop->init_req(1, not_null_oop);
1019
1020 // InlineType is null
1021 region->init_req(2, null_ctl);
1022 oop->init_req(2, kit->gvn().zerocon(T_OBJECT));
1023
1024 PhiNode* io = PhiNode::make(region, kit->i_o(), Type::ABIO);
1025 PhiNode* mem = PhiNode::make(region, kit->merged_memory(), Type::MEMORY, TypePtr::BOTTOM);
1026
1027 if (!kit->stopped()) {
1028 assert(!is_allocated(&kit->gvn()), "already buffered");
1029 PreserveJVMState pjvms(kit);
1030 ciInlineKlass* vk = inline_klass();
1031 // Allocate and initialize buffer, re-execute on deoptimization.
1032 kit->jvms()->set_bci(kit->bci());
1033 kit->jvms()->set_should_reexecute(true);
1034 kit->kill_dead_locals();
1035 Node* klass_node = kit->makecon(TypeKlassPtr::make(vk));
1036 Node* alloc_oop = kit->new_instance(klass_node, nullptr, nullptr, /* deoptimize_on_exception */ true, this);
1037 Node* payload_alloc_oop = kit->basic_plus_adr(alloc_oop, vk->payload_offset());
1038 store(kit, alloc_oop, payload_alloc_oop, true, IN_HEAP | MO_UNORDERED | C2_TIGHTLY_COUPLED_ALLOC);
1039
1040 // Do not let stores that initialize this buffer be reordered with a subsequent
1041 // store that would make this buffer accessible by other threads.
1042 AllocateNode* alloc = AllocateNode::Ideal_allocation(alloc_oop);
1043 assert(alloc != nullptr, "must have an allocation node");
1044 kit->insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out_or_null(AllocateNode::RawAddress));
1045 oop->init_req(3, alloc_oop);
1046 region->init_req(3, kit->control());
1047 io ->init_req(3, kit->i_o());
1048 mem ->init_req(3, kit->merged_memory());
1049 }
1050
1051 // Update GraphKit
1052 kit->set_control(kit->gvn().transform(region));
1053 kit->set_i_o(kit->gvn().transform(io));
1054 kit->set_all_memory(kit->gvn().transform(mem));
1055 kit->record_for_igvn(region);
1056 kit->record_for_igvn(oop);
1057 kit->record_for_igvn(io);
1058 kit->record_for_igvn(mem);
1059
1060 // Use cloned InlineTypeNode to propagate oop from now on
1061 Node* res_oop = kit->gvn().transform(oop);
1062 InlineTypeNode* vt = clone_if_required(&kit->gvn(), kit->map(), safe_for_replace);
1063 vt->set_oop(kit->gvn(), res_oop);
1064 vt->set_is_buffered(kit->gvn());
1065 vt = kit->gvn().transform(vt)->as_InlineType();
1066 kit->record_for_igvn(vt);
1067 if (safe_for_replace) {
1068 kit->replace_in_map(this, vt);
1069 }
1070 // InlineTypeNode::remove_redundant_allocations piggybacks on split if.
1071 // Make sure it gets a chance to remove this allocation.
1072 kit->C->set_has_split_ifs(true);
1073 return vt;
1074 }
1075
1076 bool InlineTypeNode::is_allocated(PhaseGVN* phase) const {
1077 if (phase->type(get_is_buffered()) == TypeInt::ONE) {
1078 return true;
1079 }
1080 Node* oop = get_oop();
1081 const Type* oop_type = (phase != nullptr) ? phase->type(oop) : oop->bottom_type();
1082 return !oop_type->maybe_null();
1083 }
1084
1085 static void replace_proj(Compile* C, CallNode* call, uint& proj_idx, Node* value, BasicType bt) {
1086 ProjNode* pn = call->proj_out_or_null(proj_idx);
1087 if (pn != nullptr) {
1088 C->gvn_replace_by(pn, value);
1089 C->initial_gvn()->hash_delete(pn);
1090 pn->set_req(0, C->top());
1091 }
1092 proj_idx += type2size[bt];
1093 }
1094
1095 // When a call returns multiple values, it has several result
1096 // projections, one per field. Replacing the result of the call by an
1097 // inline type node (after late inlining) requires that for each result
1098 // projection, we find the corresponding inline type field.
1099 void InlineTypeNode::replace_call_results(GraphKit* kit, CallNode* call, Compile* C) const {
1100 uint proj_idx = TypeFunc::Parms;
1101 // Replace oop projection
1102 replace_proj(C, call, proj_idx, get_oop(), T_OBJECT);
1103 // Replace field projections
1104 replace_field_projs(C, call, proj_idx);
1105 // Replace null_marker projection
1106 replace_proj(C, call, proj_idx, get_null_marker(), T_BOOLEAN);
1107 assert(proj_idx == call->tf()->range_cc()->cnt(), "missed a projection");
1108 }
1109
1110 void InlineTypeNode::replace_field_projs(Compile* C, CallNode* call, uint& proj_idx) const {
1111 for (uint i = 0; i < field_count(); ++i) {
1112 Node* value = field_value(i);
1113 ciField* field = this->field(i);
1114 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
1115 if (field->is_flat()) {
1116 InlineTypeNode* vt = value->as_InlineType();
1117 // Replace field projections for flat field
1118 vt->replace_field_projs(C, call, proj_idx);
1119 if (!field->is_null_free()) {
1120 // Replace null_marker projection for nullable field
1121 replace_proj(C, call, proj_idx, vt->get_null_marker(), T_BOOLEAN);
1122 }
1123 continue;
1124 }
1125 // Replace projection for field value
1126 replace_proj(C, call, proj_idx, value, field->type()->basic_type());
1127 }
1128 }
1129
1130 InlineTypeNode* InlineTypeNode::allocate_fields(GraphKit* kit) {
1131 InlineTypeNode* vt = clone_if_required(&kit->gvn(), kit->map());
1132 for (uint i = 0; i < field_count(); i++) {
1133 Node* value = field_value(i);
1134 ciField* field = this->field(i);
1135 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
1136 if (field->is_flat()) {
1137 // Flat inline type field
1138 vt->set_field_value(i, value->as_InlineType()->allocate_fields(kit));
1139 } else if (value->is_InlineType()) {
1140 // Non-flat inline type field
1141 vt->set_field_value(i, value->as_InlineType()->buffer(kit));
1142 }
1143 }
1144 vt = kit->gvn().transform(vt)->as_InlineType();
1145 kit->replace_in_map(this, vt);
1146 return vt;
1147 }
1148
1149 // Replace a buffer allocation by a dominating allocation
1150 static void replace_allocation(PhaseIterGVN* igvn, Node* res, Node* dom) {
1151 // Remove initializing stores and GC barriers
1152 for (DUIterator_Fast imax, i = res->fast_outs(imax); i < imax; i++) {
1153 Node* use = res->fast_out(i);
1154 if (use->is_AddP()) {
1155 for (DUIterator_Fast jmax, j = use->fast_outs(jmax); j < jmax; j++) {
1156 Node* store = use->fast_out(j)->isa_Store();
1157 if (store != nullptr) {
1158 igvn->rehash_node_delayed(store);
1159 igvn->replace_in_uses(store, store->in(MemNode::Memory));
1160 }
1161 }
1162 } else if (use->Opcode() == Op_CastP2X) {
1163 if (UseG1GC && use->find_out_with(Op_XorX)->in(1) != use) {
1164 // The G1 pre-barrier uses a CastP2X both for the pointer of the object
1165 // we store into, as well as the value we are storing. Skip if this is a
1166 // barrier for storing 'res' into another object.
1167 continue;
1168 }
1169 BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
1170 bs->eliminate_gc_barrier(igvn, use);
1171 --i; --imax;
1172 }
1173 }
1174 igvn->replace_node(res, dom);
1175 }
1176
1177 Node* InlineTypeNode::Ideal(PhaseGVN* phase, bool can_reshape) {
1178 Node* oop = get_oop();
1179 if (oop->isa_InlineType() && !phase->type(oop)->maybe_null()) {
1180 InlineTypeNode* vtptr = oop->as_InlineType();
1181 assert(inline_klass() == vtptr->inline_klass(), "inconsistent types");
1182 set_oop(*phase, vtptr->get_oop());
1183 set_is_buffered(*phase);
1184 set_null_marker(*phase);
1185 for (uint i = Values; i < vtptr->req(); ++i) {
1186 set_req(i, vtptr->in(i));
1187 }
1188 return this;
1189 }
1190
1191 // Use base oop if fields are loaded from memory, don't do so if base is the CheckCastPP of an
1192 // allocation because the only case we load from a naked CheckCastPP is when we exit a
1193 // constructor of an inline type and we want to relinquish the larval oop there. This has a
1194 // couple of benefits:
1195 // - The allocation is likely to be elided earlier if it is not an input of an InlineTypeNode.
1196 // - The InlineTypeNode without an allocation input is more likely to be GVN-ed. This may emerge
1197 // when we try to clone a value object.
1198 // - The buffering, if needed, is delayed until it is required. This new allocation, since it is
1199 // created from an InlineTypeNode, is recognized as not having a unique identity and in the
1200 // future, we can move them around more freely such as hoisting out of loops. This is not true
1201 // for the old allocation since larval value objects do have unique identities.
1202 Node* base = is_loaded(phase);
1203 if (base != nullptr && !base->is_InlineType() && !phase->type(base)->maybe_null() && phase->C->allow_macro_nodes() && AllocateNode::Ideal_allocation(base) == nullptr) {
1204 if (oop != base || !is_allocated(phase)) {
1205 set_oop(*phase, base);
1206 set_is_buffered(*phase);
1207 return this;
1208 }
1209 }
1210
1211 if (can_reshape) {
1212 PhaseIterGVN* igvn = phase->is_IterGVN();
1213 if (is_allocated(phase)) {
1214 // Search for and remove re-allocations of this inline type. Ignore scalar replaceable ones,
1215 // they will be removed anyway and changing the memory chain will confuse other optimizations.
1216 // This can happen with late inlining when we first allocate an inline type argument
1217 // but later decide to inline the call after the callee code also triggered allocation.
1218 for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
1219 AllocateNode* alloc = fast_out(i)->isa_Allocate();
1220 if (alloc != nullptr && alloc->in(AllocateNode::InlineType) == this && !alloc->_is_scalar_replaceable) {
1221 // Found a re-allocation
1222 Node* res = alloc->result_cast();
1223 if (res != nullptr && res->is_CheckCastPP()) {
1224 // Replace allocation by oop and unlink AllocateNode
1225 replace_allocation(igvn, res, oop);
1226 igvn->replace_input_of(alloc, AllocateNode::InlineType, igvn->C->top());
1227 --i; --imax;
1228 }
1229 }
1230 }
1231 }
1232 }
1233
1234 return nullptr;
1235 }
1236
1237 InlineTypeNode* InlineTypeNode::make_uninitialized(PhaseGVN& gvn, ciInlineKlass* vk, bool null_free) {
1238 // Create a new InlineTypeNode with uninitialized values and nullptr oop
1239 InlineTypeNode* vt = new InlineTypeNode(vk, gvn.zerocon(T_OBJECT), null_free);
1240 vt->set_is_buffered(gvn, false);
1241 vt->set_null_marker(gvn);
1242 return vt;
1243 }
1244
1245 InlineTypeNode* InlineTypeNode::make_all_zero(PhaseGVN& gvn, ciInlineKlass* vk) {
1246 return make_all_zero_impl(gvn, vk);
1247 }
1248
1249 InlineTypeNode* InlineTypeNode::make_all_zero_impl(PhaseGVN& gvn, ciInlineKlass* vk) {
1250 // Create a new InlineTypeNode initialized with all zero
1251 InlineTypeNode* vt = new InlineTypeNode(vk, gvn.zerocon(T_OBJECT), /* null_free= */ true);
1252 vt->set_is_buffered(gvn, false);
1253 vt->set_null_marker(gvn);
1254 for (uint i = 0; i < vt->field_count(); ++i) {
1255 ciField* field = vt->field(i);
1256 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
1257 ciType* ft = field->type();
1258 Node* value;
1259 if (field->is_null_free()) {
1260 value = make_all_zero_impl(gvn, ft->as_inline_klass());
1261 } else if (field->is_flat()) {
1262 value = make_null_impl(gvn, ft->as_inline_klass());
1263 } else {
1264 value = gvn.zerocon(ft->basic_type());
1265 }
1266 vt->set_field_value(i, value);
1267 }
1268 vt = gvn.transform(vt)->as_InlineType();
1269 assert(vt->is_all_zero(&gvn), "must be the all-zero inline type");
1270 return vt;
1271 }
1272
1273 bool InlineTypeNode::is_all_zero(PhaseGVN* gvn, bool flat) const {
1274 const TypeInt* tinit = gvn->type(get_null_marker())->isa_int();
1275 if (tinit == nullptr || !tinit->is_con(1)) {
1276 return false; // May be null
1277 }
1278 for (uint i = 0; i < field_count(); ++i) {
1279 Node* value = field_value(i);
1280 ciField* field = this->field(i);
1281 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
1282 if (field->is_null_free()) {
1283 // Null-free value class field must have the all-zero value. If 'flat' is set,
1284 // reject non-flat fields because they need to be initialized with an oop to a buffer.
1285 if (!value->is_InlineType() || !value->as_InlineType()->is_all_zero(gvn) || (flat && !field->is_flat())) {
1286 return false;
1287 }
1288 continue;
1289 } else if (value->is_InlineType()) {
1290 // Nullable value class field must be null
1291 tinit = gvn->type(value->as_InlineType()->get_null_marker())->isa_int();
1292 if (tinit != nullptr && tinit->is_con(0)) {
1293 continue;
1294 }
1295 return false;
1296 } else if (!gvn->type(value)->is_zero_type()) {
1297 return false;
1298 }
1299 }
1300 return true;
1301 }
1302
1303 InlineTypeNode* InlineTypeNode::make_from_oop(GraphKit* kit, Node* oop, ciInlineKlass* vk) {
1304 return make_from_oop_impl(kit, oop, vk);
1305 }
1306
1307 InlineTypeNode* InlineTypeNode::make_from_oop_impl(GraphKit* kit, Node* oop, ciInlineKlass* vk) {
1308 PhaseGVN& gvn = kit->gvn();
1309
1310 // Create and initialize an InlineTypeNode by loading all field
1311 // values from a heap-allocated version and also save the oop.
1312 InlineTypeNode* vt = oop->isa_InlineType();
1313 if (vt != nullptr) {
1314 return vt;
1315 }
1316
1317 if (gvn.type(oop) == TypePtr::NULL_PTR) {
1318 return make_null_impl(gvn, vk);
1319 }
1320
1321 if (gvn.type(oop)->maybe_null()) {
1322 // Add a null check because the oop may be null
1323 Node* null_ctl = kit->top();
1324 Node* not_null_oop = kit->null_check_oop(oop, &null_ctl);
1325 if (kit->stopped()) {
1326 // Constant null
1327 kit->set_control(null_ctl);
1328 vt = make_null_impl(gvn, vk);
1329 kit->record_for_igvn(vt);
1330 return vt;
1331 }
1332 vt = new InlineTypeNode(vk, not_null_oop, /* null_free= */ false);
1333 vt->set_is_buffered(gvn);
1334 vt->set_null_marker(gvn);
1335 Node* payload_ptr = kit->basic_plus_adr(not_null_oop, vk->payload_offset());
1336 vt->load(kit, not_null_oop, payload_ptr, true, true, IN_HEAP | MO_UNORDERED);
1337
1338 if (null_ctl != kit->top()) {
1339 InlineTypeNode* null_vt = make_null_impl(gvn, vk);
1340 Node* region = new RegionNode(3);
1341 region->init_req(1, kit->control());
1342 region->init_req(2, null_ctl);
1343 vt = vt->clone_with_phis(&gvn, region, kit->map());
1344 vt->merge_with(&gvn, null_vt, 2, true);
1345 vt->set_oop(gvn, oop);
1346 vt->set_is_buffered(gvn);
1347 kit->set_control(gvn.transform(region));
1348 }
1349 } else {
1350 // Oop can never be null
1351 vt = new InlineTypeNode(vk, oop, /* null_free= */ true);
1352 vt->set_is_buffered(gvn);
1353 vt->set_null_marker(gvn);
1354 Node* payload_ptr = kit->basic_plus_adr(oop, vk->payload_offset());
1355 vt->load(kit, oop, payload_ptr, true, true, IN_HEAP | MO_UNORDERED);
1356 }
1357 assert(vt->is_allocated(&gvn), "inline type should be allocated");
1358 kit->record_for_igvn(vt);
1359 return gvn.transform(vt)->as_InlineType();
1360 }
1361
1362 InlineTypeNode* InlineTypeNode::make_from_flat(GraphKit* kit, ciInlineKlass* vk, Node* base, Node* ptr,
1363 bool atomic, bool immutable_memory, bool null_free, DecoratorSet decorators) {
1364 return make_from_flat_impl(kit, vk, base, ptr, atomic, immutable_memory, null_free, null_free, decorators);
1365 }
1366
1367 // GraphKit wrapper for the 'make_from_flat' method
1368 InlineTypeNode* InlineTypeNode::make_from_flat_impl(GraphKit* kit, ciInlineKlass* vk, Node* base, Node* ptr, bool atomic, bool immutable_memory,
1369 bool null_free, bool trust_null_free_oop, DecoratorSet decorators) {
1370 assert(null_free || !trust_null_free_oop, "cannot trust null-free oop when the holder object is not null-free");
1371 PhaseGVN& gvn = kit->gvn();
1372 bool do_atomic = atomic;
1373 // With immutable memory, a non-atomic load and an atomic load are the same
1374 if (immutable_memory) {
1375 do_atomic = false;
1376 }
1377 // If there is only one flattened field, a non-atomic load and an atomic load are the same
1378 if (vk->is_naturally_atomic(null_free)) {
1379 do_atomic = false;
1380 }
1381
1382 if (!do_atomic) {
1383 InlineTypeNode* vt = make_uninitialized(kit->gvn(), vk, null_free);
1384 if (!null_free) {
1385 int nm_offset = vk->null_marker_offset_in_payload();
1386 Node* nm_ptr = kit->basic_plus_adr(base, ptr, nm_offset);
1387 const TypePtr* nm_ptr_type = (decorators & C2_MISMATCHED) == 0 ? gvn.type(nm_ptr)->is_ptr() : TypeRawPtr::BOTTOM;
1388 Node* nm_value = kit->access_load_at(base, nm_ptr, nm_ptr_type, TypeInt::BOOL, T_BOOLEAN, decorators);
1389 vt->set_req(NullMarker, nm_value);
1390 }
1391
1392 vt->load(kit, base, ptr, immutable_memory, trust_null_free_oop, decorators);
1393 return gvn.transform(vt)->as_InlineType();
1394 }
1395
1396 assert(!immutable_memory, "immutable memory does not need explicit atomic access");
1397 return LoadFlatNode::load(kit, vk, base, ptr, null_free, trust_null_free_oop, decorators);
1398 }
1399
1400 InlineTypeNode* InlineTypeNode::make_from_flat_array(GraphKit* kit, ciInlineKlass* vk, Node* base, Node* idx) {
1401 assert(vk->maybe_flat_in_array(), "element type %s cannot be flat in array", vk->name()->as_utf8());
1402 PhaseGVN& gvn = kit->gvn();
1403 // The flat field loads are dependent on both the array layout checks as well as the range check.
1404 DecoratorSet decorators = IN_HEAP | IS_ARRAY | MO_UNORDERED | C2_CONTROL_DEPENDENT_LOAD | C2_UNKNOWN_CONTROL_LOAD;
1405 kit->C->set_flat_accesses();
1406 InlineTypeNode* vt_nullable = nullptr;
1407 InlineTypeNode* vt_null_free = nullptr;
1408 InlineTypeNode* vt_non_atomic = nullptr;
1409
1410 RegionNode* region = new RegionNode(4);
1411 gvn.set_type(region, Type::CONTROL);
1412 kit->record_for_igvn(region);
1413
1414 Node* input_memory_state = kit->reset_memory();
1415 kit->set_all_memory(input_memory_state);
1416
1417 PhiNode* mem = PhiNode::make(region, input_memory_state, Type::MEMORY, TypePtr::BOTTOM);
1418 gvn.set_type(mem, Type::MEMORY);
1419 kit->record_for_igvn(mem);
1420
1421 PhiNode* io = PhiNode::make(region, kit->i_o(), Type::ABIO);
1422 gvn.set_type(io, Type::ABIO);
1423 kit->record_for_igvn(io);
1424
1425 Node* bol_null_free = kit->null_free_array_test(base); // Argument evaluation order is undefined in C++ and since this sets control, it needs to come first
1426 IfNode* iff_null_free = kit->create_and_map_if(kit->control(), bol_null_free, PROB_FAIR, COUNT_UNKNOWN);
1427
1428 // Nullable
1429 kit->set_control(kit->IfFalse(iff_null_free));
1430 if (!kit->stopped()) {
1431 assert(vk->has_nullable_atomic_layout(), "element type %s does not have a nullable flat layout", vk->name()->as_utf8());
1432 kit->set_all_memory(input_memory_state);
1433 Node* cast = kit->cast_to_flat_array_exact(base, vk, false, true);
1434 Node* ptr = kit->array_element_address(cast, idx, T_FLAT_ELEMENT);
1435 vt_nullable = InlineTypeNode::make_from_flat(kit, vk, cast, ptr, true, false, false, decorators);
1436
1437 region->init_req(1, kit->control());
1438 mem->set_req(1, kit->reset_memory());
1439 io->set_req(1, kit->i_o());
1440 }
1441
1442 // Null-free
1443 kit->set_control(kit->IfTrue(iff_null_free));
1444 if (!kit->stopped()) {
1445 kit->set_all_memory(input_memory_state);
1446
1447 Node* bol_atomic = kit->null_free_atomic_array_test(base, vk);
1448 IfNode* iff_atomic = kit->create_and_map_if(kit->control(), bol_atomic, PROB_FAIR, COUNT_UNKNOWN);
1449
1450 // Atomic
1451 kit->set_control(kit->IfTrue(iff_atomic));
1452 if (!kit->stopped()) {
1453 assert(vk->has_null_free_atomic_layout(), "element type %s does not have a null-free atomic flat layout", vk->name()->as_utf8());
1454 kit->set_all_memory(input_memory_state);
1455 Node* cast = kit->cast_to_flat_array_exact(base, vk, true, true);
1456 Node* ptr = kit->array_element_address(cast, idx, T_FLAT_ELEMENT);
1457 vt_null_free = InlineTypeNode::make_from_flat(kit, vk, cast, ptr, true, false, true, decorators);
1458
1459 region->init_req(2, kit->control());
1460 mem->set_req(2, kit->reset_memory());
1461 io->set_req(2, kit->i_o());
1462 }
1463
1464 // Non-Atomic
1465 kit->set_control(kit->IfFalse(iff_atomic));
1466 if (!kit->stopped()) {
1467 assert(vk->has_null_free_non_atomic_layout(), "element type %s does not have a null-free non-atomic flat layout", vk->name()->as_utf8());
1468 kit->set_all_memory(input_memory_state);
1469 Node* cast = kit->cast_to_flat_array_exact(base, vk, true, false);
1470 Node* ptr = kit->array_element_address(cast, idx, T_FLAT_ELEMENT);
1471 vt_non_atomic = InlineTypeNode::make_from_flat(kit, vk, cast, ptr, false, false, true, decorators);
1472
1473 region->init_req(3, kit->control());
1474 mem->set_req(3, kit->reset_memory());
1475 io->set_req(3, kit->i_o());
1476 }
1477 }
1478
1479 InlineTypeNode* vt = nullptr;
1480 if (vt_nullable == nullptr && vt_null_free == nullptr && vt_non_atomic == nullptr) {
1481 // All paths are dead
1482 vt = make_null(gvn, vk);
1483 } else if (vt_nullable == nullptr && vt_null_free == nullptr) {
1484 vt = vt_non_atomic;
1485 } else if (vt_nullable == nullptr && vt_non_atomic == nullptr) {
1486 vt = vt_null_free;
1487 } else if (vt_null_free == nullptr && vt_non_atomic == nullptr) {
1488 vt = vt_nullable;
1489 }
1490 if (vt != nullptr) {
1491 kit->set_control(kit->gvn().transform(region));
1492 kit->set_all_memory(kit->gvn().transform(mem));
1493 kit->set_i_o(kit->gvn().transform(io));
1494 return vt;
1495 }
1496
1497 InlineTypeNode* zero = InlineTypeNode::make_null(gvn, vk);
1498 vt = zero->clone_with_phis(&gvn, region);
1499 if (vt_nullable != nullptr) {
1500 vt = vt->merge_with(&gvn, vt_nullable, 1, false);
1501 }
1502 if (vt_null_free != nullptr) {
1503 vt = vt->merge_with(&gvn, vt_null_free, 2, false);
1504 }
1505 if (vt_non_atomic != nullptr) {
1506 vt = vt->merge_with(&gvn, vt_non_atomic, 3, false);
1507 }
1508
1509 kit->set_control(kit->gvn().transform(region));
1510 kit->set_all_memory(kit->gvn().transform(mem));
1511 kit->set_i_o(kit->gvn().transform(io));
1512 return gvn.transform(vt)->as_InlineType();
1513 }
1514
1515 InlineTypeNode* InlineTypeNode::make_from_multi(GraphKit* kit, MultiNode* multi, ciInlineKlass* vk, uint& base_input, bool in, bool null_free) {
1516 InlineTypeNode* vt = make_uninitialized(kit->gvn(), vk, null_free);
1517 if (!in || multi->is_Start()) {
1518 // Keep track of the oop. The inline type might already be buffered.
1519 Node* oop = nullptr;
1520 if (multi->is_Start()) {
1521 oop = kit->gvn().transform(new ParmNode(multi->as_Start(), base_input++));
1522 } else {
1523 oop = kit->gvn().transform(new ProjNode(multi, base_input++));
1524 }
1525 vt->set_oop(kit->gvn(), oop);
1526 } else {
1527 Node* oop = multi->as_Call()->in(base_input++);
1528 vt->set_oop(kit->gvn(), oop);
1529 }
1530 vt->initialize_fields(kit, multi, base_input, in, null_free, nullptr);
1531 return kit->gvn().transform(vt)->as_InlineType();
1532 }
1533
1534 Node* InlineTypeNode::is_loaded(PhaseGVN* phase, ciInlineKlass* vk, Node* base, int holder_offset) const {
1535 if (vk == nullptr) {
1536 vk = inline_klass();
1537 }
1538 for (uint i = 0; i < field_count(); ++i) {
1539 ciField* field = this->field(i);
1540 int offset = holder_offset + field->offset_in_bytes();
1541 Node* value = field_value(i);
1542 if (value->is_InlineType()) {
1543 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
1544 InlineTypeNode* vt = value->as_InlineType();
1545 if (vt->type()->inline_klass()->is_empty()) {
1546 continue;
1547 } else if (field->is_flat() && vt->is_InlineType()) {
1548 // Check inline type field load recursively
1549 base = vt->as_InlineType()->is_loaded(phase, vk, base, offset - vt->type()->inline_klass()->payload_offset());
1550 if (base == nullptr) {
1551 return nullptr;
1552 }
1553 continue;
1554 } else {
1555 value = vt->get_oop();
1556 if (value->Opcode() == Op_CastPP) {
1557 // Skip CastPP
1558 value = value->in(1);
1559 }
1560 }
1561 }
1562 if (value->isa_DecodeN()) {
1563 // Skip DecodeN
1564 value = value->in(1);
1565 }
1566 if (value->isa_Load()) {
1567 // Check if base and offset of field load matches inline type layout
1568 intptr_t loffset = 0;
1569 Node* lbase = AddPNode::Ideal_base_and_offset(value->in(MemNode::Address), phase, loffset);
1570 if (lbase == nullptr || (lbase != base && base != nullptr) || loffset != offset) {
1571 return nullptr;
1572 } else if (base == nullptr) {
1573 // Set base and check if pointer type matches
1574 base = lbase;
1575 const TypeInstPtr* vtptr = phase->type(base)->isa_instptr();
1576 if (vtptr == nullptr || !vtptr->instance_klass()->equals(vk)) {
1577 return nullptr;
1578 }
1579 }
1580 } else {
1581 return nullptr;
1582 }
1583 }
1584 return base;
1585 }
1586
1587 Node* InlineTypeNode::tagged_klass(ciInlineKlass* vk, PhaseGVN& gvn) {
1588 const TypeKlassPtr* tk = TypeKlassPtr::make(vk);
1589 intptr_t bits = tk->get_con();
1590 set_nth_bit(bits, 0);
1591 return gvn.longcon((jlong)bits);
1592 }
1593
1594 void InlineTypeNode::pass_fields(GraphKit* kit, Node* n, uint& base_input, bool in, bool null_free, bool root) {
1595 if (root) {
1596 if (is_allocated(&kit->gvn())) {
1597 // Keep the information that 'this' is buffered
1598 n->init_req(base_input++, this);
1599 } else {
1600 n->init_req(base_input++, get_oop());
1601 }
1602 }
1603 if (!null_free && in) {
1604 n->init_req(base_input++, get_null_marker());
1605 }
1606 for (uint i = 0; i < field_count(); i++) {
1607 Node* arg = field_value(i);
1608 ciField* field = this->field(i);
1609 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
1610 if (field->is_flat()) {
1611 // Flat inline type field
1612 arg->as_InlineType()->pass_fields(kit, n, base_input, in);
1613 if (!field->is_null_free()) {
1614 assert(field->null_marker_offset() != -1, "inconsistency");
1615 n->init_req(base_input++, arg->as_InlineType()->get_null_marker());
1616 }
1617 } else {
1618 if (arg->is_InlineType()) {
1619 // Non-flat inline type field
1620 InlineTypeNode* vt = arg->as_InlineType();
1621 assert(n->Opcode() != Op_Return || vt->is_allocated(&kit->gvn()), "inline type field should be allocated on return");
1622 arg = vt->buffer(kit);
1623 }
1624 // Initialize call/return arguments
1625 n->init_req(base_input++, arg);
1626 if (field->type()->size() == 2) {
1627 n->init_req(base_input++, kit->top());
1628 }
1629 }
1630 }
1631 }
1632
1633 void InlineTypeNode::initialize_fields(GraphKit* kit, MultiNode* multi, uint& base_input, bool in, bool no_null_marker, Node* null_check_region) {
1634 PhaseGVN& gvn = kit->gvn();
1635 Node* null_marker = nullptr;
1636 if (!no_null_marker) {
1637 // Nullable inline type
1638 if (in) {
1639 // Set null marker
1640 if (multi->is_Start()) {
1641 null_marker = gvn.transform(new ParmNode(multi->as_Start(), base_input));
1642 } else {
1643 null_marker = multi->as_Call()->in(base_input);
1644 }
1645 set_req(NullMarker, null_marker);
1646 base_input++;
1647 }
1648 // Add a null check to make subsequent loads dependent on
1649 assert(null_check_region == nullptr, "already set");
1650 if (null_marker == nullptr) {
1651 // Will only be initialized below, use dummy node for now
1652 null_marker = new Node(1);
1653 null_marker->init_req(0, kit->control()); // Add an input to prevent dummy from being dead
1654 gvn.set_type_bottom(null_marker);
1655 }
1656 Node* null_ctrl = kit->top();
1657 kit->null_check_common(null_marker, T_INT, false, &null_ctrl);
1658 Node* non_null_ctrl = kit->control();
1659 null_check_region = new RegionNode(3);
1660 null_check_region->init_req(1, non_null_ctrl);
1661 null_check_region->init_req(2, null_ctrl);
1662 null_check_region = gvn.transform(null_check_region);
1663 kit->set_control(null_check_region);
1664 }
1665
1666 for (uint i = 0; i < field_count(); ++i) {
1667 ciField* field = this->field(i);
1668 ciType* type = field->type();
1669 Node* parm = nullptr;
1670 assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");
1671 if (field->is_flat()) {
1672 // Flat inline type field
1673 InlineTypeNode* vt = make_uninitialized(gvn, type->as_inline_klass(), field->is_null_free());
1674 vt->initialize_fields(kit, multi, base_input, in, true, null_check_region);
1675 if (!field->is_null_free()) {
1676 assert(field->null_marker_offset() != -1, "inconsistency");
1677 Node* null_marker_field_vt = nullptr;
1678 if (multi->is_Start()) {
1679 null_marker_field_vt = gvn.transform(new ParmNode(multi->as_Start(), base_input));
1680 } else if (in) {
1681 null_marker_field_vt = multi->as_Call()->in(base_input);
1682 } else {
1683 null_marker_field_vt = gvn.transform(new ProjNode(multi->as_Call(), base_input));
1684 }
1685 vt->set_req(NullMarker, null_marker_field_vt);
1686 base_input++;
1687 }
1688 parm = gvn.transform(vt);
1689 } else {
1690 if (multi->is_Start()) {
1691 assert(in, "return from start?");
1692 parm = gvn.transform(new ParmNode(multi->as_Start(), base_input));
1693 } else if (in) {
1694 parm = multi->as_Call()->in(base_input);
1695 } else {
1696 parm = gvn.transform(new ProjNode(multi->as_Call(), base_input));
1697 }
1698 base_input += type->size();
1699 }
1700 assert(parm != nullptr, "should never be null");
1701 assert(field_value(i) == nullptr, "already set");
1702 set_field_value(i, parm);
1703 gvn.record_for_igvn(parm);
1704 }
1705 // The last argument is used to pass the null marker to compiled code
1706 if (!no_null_marker && !in) {
1707 Node* cmp = null_marker->raw_out(0);
1708 null_marker = gvn.transform(new ProjNode(multi->as_Call(), base_input));
1709 set_req(NullMarker, null_marker);
1710 gvn.hash_delete(cmp);
1711 cmp->set_req(1, null_marker);
1712 gvn.hash_find_insert(cmp);
1713 gvn.record_for_igvn(cmp);
1714 base_input++;
1715 }
1716 }
1717
1718 // Search for multiple allocations of this inline type and try to replace them by dominating allocations.
1719 // Equivalent InlineTypeNodes are merged by GVN, so we just need to search for AllocateNode users to find redundant allocations.
1720 void InlineTypeNode::remove_redundant_allocations(PhaseIdealLoop* phase) const {
1721 PhaseIterGVN* igvn = &phase->igvn();
1722 // Search for allocations of this inline type. Ignore scalar replaceable ones, they
1723 // will be removed anyway and changing the memory chain will confuse other optimizations.
1724 for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
1725 AllocateNode* alloc = fast_out(i)->isa_Allocate();
1726 if (alloc != nullptr && alloc->in(AllocateNode::InlineType) == this && !alloc->_is_scalar_replaceable) {
1727 Node* res = alloc->result_cast();
1728 if (res == nullptr || !res->is_CheckCastPP()) {
1729 break; // No unique CheckCastPP
1730 }
1731 // Search for a dominating allocation of the same inline type
1732 Node* res_dom = res;
1733 for (DUIterator_Fast jmax, j = fast_outs(jmax); j < jmax; j++) {
1734 AllocateNode* alloc_other = fast_out(j)->isa_Allocate();
1735 if (alloc_other != nullptr && alloc_other->in(AllocateNode::InlineType) == this && !alloc_other->_is_scalar_replaceable) {
1736 Node* res_other = alloc_other->result_cast();
1737 if (res_other != nullptr && res_other->is_CheckCastPP() && res_other != res_dom &&
1738 phase->is_dominator(res_other->in(0), res_dom->in(0))) {
1739 res_dom = res_other;
1740 }
1741 }
1742 }
1743 if (res_dom != res) {
1744 // Replace allocation by dominating one.
1745 replace_allocation(igvn, res, res_dom);
1746 // The result of the dominated allocation is now unused and will be removed
1747 // later in PhaseMacroExpand::eliminate_allocate_node to not confuse loop opts.
1748 igvn->_worklist.push(alloc);
1749 }
1750 }
1751 }
1752 }
1753
1754 InlineTypeNode* InlineTypeNode::make_null(PhaseGVN& gvn, ciInlineKlass* vk, bool transform) {
1755 return make_null_impl(gvn, vk, transform);
1756 }
1757
1758 InlineTypeNode* InlineTypeNode::make_null_impl(PhaseGVN& gvn, ciInlineKlass* vk, bool transform) {
1759 InlineTypeNode* vt = new InlineTypeNode(vk, gvn.zerocon(T_OBJECT), /* null_free= */ false);
1760 vt->set_is_buffered(gvn);
1761 vt->set_null_marker(gvn, gvn.intcon(0));
1762 for (uint i = 0; i < vt->field_count(); i++) {
1763 ciField* field = vt->field(i);
1764 ciType* ft = field->type();
1765 Node* value;
1766 if (field->is_flat()) {
1767 value = make_null_impl(gvn, ft->as_inline_klass());
1768 } else {
1769 value = gvn.zerocon(ft->basic_type());
1770 }
1771 vt->set_field_value(i, value);
1772 }
1773 return transform ? gvn.transform(vt)->as_InlineType() : vt;
1774 }
1775
1776 InlineTypeNode* InlineTypeNode::clone_if_required(PhaseGVN* gvn, SafePointNode* map, bool safe_for_replace) {
1777 if (!safe_for_replace || (map == nullptr && outcnt() != 0)) {
1778 return clone()->as_InlineType();
1779 }
1780 for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
1781 if (fast_out(i) != map) {
1782 return clone()->as_InlineType();
1783 }
1784 }
1785 gvn->hash_delete(this);
1786 return this;
1787 }
1788
1789 const Type* InlineTypeNode::Value(PhaseGVN* phase) const {
1790 Node* oop = get_oop();
1791 const Type* toop = phase->type(oop);
1792 #ifdef ASSERT
1793 if (oop->is_Con() && toop->is_zero_type() && _type->isa_oopptr()->is_known_instance()) {
1794 // We are not allocated (anymore) and should therefore not have an instance id
1795 dump(1);
1796 assert(false, "Unbuffered inline type should not have known instance id");
1797 }
1798 #endif
1799 if (toop == Type::TOP) {
1800 return Type::TOP;
1801 }
1802 const Type* t = toop->filter_speculative(_type);
1803 // Because of contradicting type profiling, we can end up with top as speculative type,
1804 // which would then get removed by cleanup_speculative. In this case we have to run filter_speculative
1805 // again, otherwise we would break the idempotence of Value
1806 if (t->speculative() == nullptr && toop->speculative() != nullptr) {
1807 t = toop->filter_speculative(t);
1808 }
1809 if (t->singleton()) {
1810 // Don't replace InlineType by a constant
1811 t = _type;
1812 }
1813 const Type* tinit = phase->type(in(NullMarker));
1814 if (tinit == Type::TOP) {
1815 return Type::TOP;
1816 }
1817 if (tinit->isa_int() && tinit->is_int()->is_con(1)) {
1818 t = t->join_speculative(TypePtr::NOTNULL);
1819 }
1820 return t;
1821 }
1822
1823 InlineTypeNode* LoadFlatNode::load(GraphKit* kit, ciInlineKlass* vk, Node* base, Node* ptr, bool null_free, bool trust_null_free_oop, DecoratorSet decorators) {
1824 int output_type_size = vk->nof_nonstatic_fields() + (null_free ? 0 : 1);
1825 const Type** output_types = TypeTuple::fields(output_type_size);
1826 collect_field_types(vk, output_types + TypeFunc::Parms, 0, output_type_size, null_free, trust_null_free_oop);
1827 const TypeTuple* type = TypeTuple::make(output_type_size + TypeFunc::Parms, output_types);
1828
1829 LoadFlatNode* load = new LoadFlatNode(vk, type, null_free, decorators);
1830 load->init_req(TypeFunc::Control, kit->control());
1831 load->init_req(TypeFunc::I_O, kit->top());
1832 load->init_req(TypeFunc::Memory, kit->reset_memory());
1833 load->init_req(TypeFunc::FramePtr, kit->frameptr());
1834 load->init_req(TypeFunc::ReturnAdr, kit->top());
1835
1836 load->init_req(TypeFunc::Parms, base);
1837 load->init_req(TypeFunc::Parms + 1, ptr);
1838 kit->kill_dead_locals();
1839 kit->add_safepoint_edges(load);
1840 load = kit->gvn().transform(load)->as_LoadFlat();
1841 kit->record_for_igvn(load);
1842
1843 kit->set_control(kit->gvn().transform(new ProjNode(load, TypeFunc::Control)));
1844 kit->set_all_memory(kit->gvn().transform(new ProjNode(load, TypeFunc::Memory)));
1845 return load->collect_projs(kit, vk, TypeFunc::Parms, null_free);
1846 }
1847
1848 bool LoadFlatNode::expand_constant(PhaseIterGVN& igvn, ciInstance* inst) const {
1849 precond(inst != nullptr);
1850 assert(igvn.delay_transform(), "transformation must be delayed");
1851 if ((_decorators & C2_MISMATCHED) != 0) {
1852 return false;
1853 }
1854
1855 GraphKit kit(this, igvn);
1856 for (int i = 0; i < _vk->nof_nonstatic_fields(); i++) {
1857 ProjNode* proj_out = proj_out_or_null(TypeFunc::Parms + i);
1858 if (proj_out == nullptr) {
1859 continue;
1860 }
1861
1862 ciField* field = _vk->nonstatic_field_at(i);
1863 BasicType bt = field->type()->basic_type();
1864 if (inst == nullptr) {
1865 Node* cst_node = igvn.zerocon(bt);
1866 igvn.replace_node(proj_out, cst_node);
1867 } else {
1868 bool is_unsigned_load = bt == T_BOOLEAN || bt == T_CHAR;
1869 const Type* cst_type = Type::make_constant_from_field(field, inst, bt, is_unsigned_load);
1870 Node* cst_node = igvn.makecon(cst_type);
1871 igvn.replace_node(proj_out, cst_node);
1872 }
1873 }
1874
1875 if (!_null_free) {
1876 ProjNode* proj_out = proj_out_or_null(TypeFunc::Parms + _vk->nof_nonstatic_fields());
1877 if (proj_out != nullptr) {
1878 igvn.replace_node(proj_out, igvn.intcon(1));
1879 }
1880 }
1881
1882 Node* old_ctrl = proj_out_or_null(TypeFunc::Control);
1883 if (old_ctrl != nullptr) {
1884 igvn.replace_node(old_ctrl, kit.control());
1885 }
1886 Node* old_mem = proj_out_or_null(TypeFunc::Memory);
1887 Node* new_mem = kit.reset_memory();
1888 if (old_mem != nullptr) {
1889 igvn.replace_node(old_mem, new_mem);
1890 }
1891 return true;
1892 }
1893
1894 bool LoadFlatNode::expand_non_atomic(PhaseIterGVN& igvn) const {
1895 assert(igvn.delay_transform(), "transformation must be delayed");
1896 if ((_decorators & C2_MISMATCHED) != 0) {
1897 return false;
1898 }
1899
1900 GraphKit kit(this, igvn);
1901 Node* base = this->base();
1902 Node* ptr = this->ptr();
1903
1904 for (int i = 0; i < _vk->nof_nonstatic_fields(); i++) {
1905 ProjNode* proj_out = proj_out_or_null(TypeFunc::Parms + i);
1906 if (proj_out == nullptr) {
1907 continue;
1908 }
1909
1910 ciField* field = _vk->nonstatic_field_at(i);
1911 Node* field_ptr = kit.basic_plus_adr(base, ptr, field->offset_in_bytes() - _vk->payload_offset());
1912 const TypePtr* field_ptr_type = field_ptr->Value(&igvn)->is_ptr();
1913 igvn.set_type(field_ptr, field_ptr_type);
1914
1915 Node* field_value = kit.access_load_at(base, field_ptr, field_ptr_type, igvn.type(proj_out), field->type()->basic_type(), _decorators);
1916 igvn.replace_node(proj_out, field_value);
1917 }
1918
1919 if (!_null_free) {
1920 ProjNode* proj_out = proj_out_or_null(TypeFunc::Parms + _vk->nof_nonstatic_fields());
1921 if (proj_out != nullptr) {
1922 Node* null_marker_ptr = kit.basic_plus_adr(base, ptr, _vk->null_marker_offset_in_payload());
1923 const TypePtr* null_marker_ptr_type = null_marker_ptr->Value(&igvn)->is_ptr();
1924 igvn.set_type(null_marker_ptr, null_marker_ptr_type);
1925 Node* null_marker_value = kit.access_load_at(base, null_marker_ptr, null_marker_ptr_type, TypeInt::BOOL, T_BOOLEAN, _decorators);
1926 igvn.replace_node(proj_out, null_marker_value);
1927 }
1928 }
1929
1930 Node* old_ctrl = proj_out_or_null(TypeFunc::Control);
1931 if (old_ctrl != nullptr) {
1932 igvn.replace_node(old_ctrl, kit.control());
1933 }
1934 Node* old_mem = proj_out_or_null(TypeFunc::Memory);
1935 Node* new_mem = kit.reset_memory();
1936 if (old_mem != nullptr) {
1937 igvn.replace_node(old_mem, new_mem);
1938 }
1939 return true;
1940 }
1941
1942 void LoadFlatNode::expand_atomic(PhaseIterGVN& igvn) const {
1943 assert(igvn.delay_transform(), "transformation must be delayed");
1944 GraphKit kit(this, igvn);
1945 Node* base = this->base();
1946 Node* ptr = this->ptr();
1947
1948 BasicType payload_bt = _vk->atomic_size_to_basic_type(_null_free);
1949 kit.insert_mem_bar(Op_MemBarCPUOrder);
1950 Node* payload = kit.access_load_at(base, ptr, TypeRawPtr::BOTTOM, Type::get_const_basic_type(payload_bt), payload_bt,
1951 _decorators | C2_MISMATCHED | C2_CONTROL_DEPENDENT_LOAD | C2_UNKNOWN_CONTROL_LOAD, kit.control());
1952 kit.insert_mem_bar(Op_MemBarCPUOrder);
1953
1954 Node* old_ctrl = proj_out_or_null(TypeFunc::Control);
1955 if (old_ctrl != nullptr) {
1956 igvn.replace_node(old_ctrl, kit.control());
1957 }
1958 Node* old_mem = proj_out_or_null(TypeFunc::Memory);
1959 Node* new_mem = kit.reset_memory();
1960 if (old_mem != nullptr) {
1961 igvn.replace_node(old_mem, new_mem);
1962 }
1963
1964 expand_projs_atomic(igvn, kit.control(), payload);
1965 }
1966
1967 void LoadFlatNode::collect_field_types(ciInlineKlass* vk, const Type** field_types, int idx, int limit, bool null_free, bool trust_null_free_oop) {
1968 assert(null_free || !trust_null_free_oop, "cannot trust null-free oop when the holder object is not null-free");
1969 for (int i = 0; i < vk->nof_declared_nonstatic_fields(); i++) {
1970 ciField* field = vk->declared_nonstatic_field_at(i);
1971 if (field->is_flat()) {
1972 ciInlineKlass* field_klass = field->type()->as_inline_klass();
1973 collect_field_types(field_klass, field_types, idx, limit, field->is_null_free(), trust_null_free_oop && field->is_null_free());
1974 idx += field_klass->nof_nonstatic_fields() + (field->is_null_free() ? 0 : 1);
1975 continue;
1976 }
1977
1978 const Type* field_type = Type::get_const_type(field->type());
1979 if (trust_null_free_oop && field->is_null_free()) {
1980 field_type = field_type->filter(TypePtr::NOTNULL);
1981 }
1982
1983 assert(idx >= 0 && idx < limit, "field type out of bounds, %d - %d", idx, limit);
1984 field_types[idx] = field_type;
1985 idx++;
1986 }
1987
1988 if (!null_free) {
1989 assert(idx >= 0 && idx < limit, "field type out of bounds, %d - %d", idx, limit);
1990 field_types[idx] = TypeInt::BOOL;
1991 }
1992 }
1993
1994 // Create an InlineTypeNode from a LoadFlatNode with its fields being extracted from the
1995 // LoadFlatNode
1996 InlineTypeNode* LoadFlatNode::collect_projs(GraphKit* kit, ciInlineKlass* vk, int proj_con, bool null_free) {
1997 PhaseGVN& gvn = kit->gvn();
1998 InlineTypeNode* res = InlineTypeNode::make_uninitialized(gvn, vk, null_free);
1999 for (int i = 0; i < vk->nof_declared_nonstatic_fields(); i++) {
2000 ciField* field = vk->declared_nonstatic_field_at(i);
2001 Node* field_value;
2002 if (field->is_flat()) {
2003 ciInlineKlass* field_klass = field->type()->as_inline_klass();
2004 field_value = collect_projs(kit, field_klass, proj_con, field->is_null_free());
2005 proj_con += field_klass->nof_nonstatic_fields() + (field->is_null_free() ? 0 : 1);
2006 } else {
2007 field_value = gvn.transform(new ProjNode(this, proj_con));
2008 proj_con++;
2009 }
2010 res->set_field_value(i, field_value);
2011 }
2012
2013 if (null_free) {
2014 res->set_null_marker(gvn);
2015 } else {
2016 res->set_null_marker(gvn, gvn.transform(new ProjNode(this, proj_con)));
2017 }
2018 return gvn.transform(res)->as_InlineType();
2019 }
2020
2021 // Extract the values of the flattened fields from the loaded payload
2022 void LoadFlatNode::expand_projs_atomic(PhaseIterGVN& igvn, Node* ctrl, Node* payload) const {
2023 BasicType payload_bt = _vk->atomic_size_to_basic_type(_null_free);
2024 for (int i = 0; i < _vk->nof_nonstatic_fields(); i++) {
2025 ProjNode* proj_out = proj_out_or_null(TypeFunc::Parms + i);
2026 if (proj_out == nullptr) {
2027 continue;
2028 }
2029
2030 ciField* field = _vk->nonstatic_field_at(i);
2031 int field_offset = field->offset_in_bytes() - _vk->payload_offset();
2032 const Type* field_type = igvn.type(proj_out);
2033 Node* field_value = get_payload_value(igvn, ctrl, payload_bt, payload, field_type, field->type()->basic_type(), field_offset);
2034 igvn.replace_node(proj_out, field_value);
2035 }
2036
2037 if (!_null_free) {
2038 ProjNode* proj_out = proj_out_or_null(TypeFunc::Parms + _vk->nof_nonstatic_fields());
2039 if (proj_out == nullptr) {
2040 return;
2041 }
2042
2043 int null_marker_offset = _vk->null_marker_offset_in_payload();
2044 Node* null_marker_value = get_payload_value(igvn, ctrl, payload_bt, payload, TypeInt::BOOL, T_BOOLEAN, null_marker_offset);
2045 igvn.replace_node(proj_out, null_marker_value);
2046 }
2047 }
2048
2049 Node* LoadFlatNode::get_payload_value(PhaseIterGVN& igvn, Node* ctrl, BasicType payload_bt, Node* payload, const Type* value_type, BasicType value_bt, int offset) {
2050 assert((offset + type2aelembytes(value_bt)) <= type2aelembytes(payload_bt), "Value does not fit into payload");
2051 Node* value = nullptr;
2052 // Shift to the right position in the long value
2053 Node* shift_val = igvn.intcon(offset << LogBitsPerByte);
2054 if (payload_bt == T_LONG) {
2055 value = igvn.transform(new URShiftLNode(payload, shift_val));
2056 value = igvn.transform(new ConvL2INode(value));
2057 } else {
2058 value = igvn.transform(new URShiftINode(payload, shift_val));
2059 }
2060
2061 if (value_bt == T_INT) {
2062 return value;
2063 } else if (!is_java_primitive(value_bt)) {
2064 assert(UseCompressedOops && payload_bt == T_LONG, "Naturally atomic");
2065 value = igvn.transform(new CastI2NNode(ctrl, value, value_type->make_narrowoop()));
2066 value = igvn.transform(new DecodeNNode(value, value_type));
2067
2068 // Similar to CheckCastPP nodes with raw input, CastI2N nodes require special handling in 'PhaseCFG::schedule_late' to ensure the
2069 // register allocator does not move the CastI2N below a safepoint. This is necessary to avoid having the raw pointer span a safepoint,
2070 // making it opaque to the GC. Unlike CheckCastPPs, which need extra handling in 'Scheduling::ComputeRegisterAntidependencies' due to
2071 // scalarization, CastI2N nodes are always used by a load if scalarization happens which inherently keeps them pinned above the safepoint.
2072 return value;
2073 } else {
2074 // Make sure to zero unused bits in the 32-bit value
2075 return Compile::narrow_value(value_bt, value, nullptr, &igvn, true);
2076 }
2077 }
2078
2079 void StoreFlatNode::store(GraphKit* kit, Node* base, Node* ptr, InlineTypeNode* value, bool null_free, DecoratorSet decorators) {
2080 value = value->allocate_fields(kit);
2081 StoreFlatNode* store = new StoreFlatNode(null_free, decorators);
2082 store->init_req(TypeFunc::Control, kit->control());
2083 store->init_req(TypeFunc::I_O, kit->top());
2084 store->init_req(TypeFunc::Memory, kit->reset_memory());
2085 store->init_req(TypeFunc::FramePtr, kit->frameptr());
2086 store->init_req(TypeFunc::ReturnAdr, kit->top());
2087
2088 store->init_req(TypeFunc::Parms, base);
2089 store->init_req(TypeFunc::Parms + 1, ptr);
2090 store->init_req(TypeFunc::Parms + 2, value);
2091 kit->kill_dead_locals();
2092 kit->add_safepoint_edges(store);
2093 store = kit->gvn().transform(store)->as_StoreFlat();
2094 kit->record_for_igvn(store);
2095
2096 kit->set_control(kit->gvn().transform(new ProjNode(store, TypeFunc::Control)));
2097 kit->set_all_memory(kit->gvn().transform(new ProjNode(store, TypeFunc::Memory)));
2098 }
2099
2100 bool StoreFlatNode::expand_non_atomic(PhaseIterGVN& igvn) const {
2101 assert(igvn.delay_transform(), "transformation must be delayed");
2102 if ((_decorators & C2_MISMATCHED) != 0) {
2103 return false;
2104 }
2105
2106 GraphKit kit(this, igvn);
2107 Node* base = this->base();
2108 Node* ptr = this->ptr();
2109 InlineTypeNode* value = this->value();
2110
2111 ciInlineKlass* vk = igvn.type(value)->inline_klass();
2112 for (int i = 0; i < vk->nof_nonstatic_fields(); i++) {
2113 ciField* field = vk->nonstatic_field_at(i);
2114 Node* field_ptr = kit.basic_plus_adr(base, ptr, field->offset_in_bytes() - vk->payload_offset());
2115 const TypePtr* field_ptr_type = field_ptr->Value(&igvn)->is_ptr();
2116 igvn.set_type(field_ptr, field_ptr_type);
2117 Node* field_value = value->field_value_by_offset(field->offset_in_bytes(), true);
2118 kit.access_store_at(base, field_ptr, field_ptr_type, field_value, igvn.type(field_value), field->type()->basic_type(), _decorators);
2119 }
2120
2121 if (!_null_free) {
2122 Node* null_marker_ptr = kit.basic_plus_adr(base, ptr, vk->null_marker_offset_in_payload());
2123 const TypePtr* null_marker_ptr_type = null_marker_ptr->Value(&igvn)->is_ptr();
2124 igvn.set_type(null_marker_ptr, null_marker_ptr_type);
2125 Node* null_marker_value = value->get_null_marker();
2126 kit.access_store_at(base, null_marker_ptr, null_marker_ptr_type, null_marker_value, TypeInt::BOOL, T_BOOLEAN, _decorators);
2127 }
2128
2129 Node* old_ctrl = proj_out_or_null(TypeFunc::Control);
2130 if (old_ctrl != nullptr) {
2131 igvn.replace_node(old_ctrl, kit.control());
2132 }
2133 Node* old_mem = proj_out_or_null(TypeFunc::Memory);
2134 Node* new_mem = kit.reset_memory();
2135 if (old_mem != nullptr) {
2136 igvn.replace_node(old_mem, new_mem);
2137 }
2138 return true;
2139 }
2140
2141 void StoreFlatNode::expand_atomic(PhaseIterGVN& igvn) const {
2142 // Convert to a payload value <= 64-bit and write atomically.
2143 // The payload might contain at most two oop fields that must be narrow because otherwise they would be 64-bit
2144 // in size and would then be written by a "normal" oop store. If the payload contains oops, its size is always
2145 // 64-bit because the next smaller (power-of-two) size would be 32-bit which could only hold one narrow oop that
2146 // would then be written by a normal narrow oop store. These properties are asserted in 'convert_to_payload'.
2147 assert(igvn.delay_transform(), "transformation must be delayed");
2148 GraphKit kit(this, igvn);
2149 Node* base = this->base();
2150 Node* ptr = this->ptr();
2151 InlineTypeNode* value = this->value();
2152
2153 int oop_off_1 = -1;
2154 int oop_off_2 = -1;
2155 Node* payload = convert_to_payload(igvn, kit.control(), value, _null_free, oop_off_1, oop_off_2);
2156
2157 ciInlineKlass* vk = igvn.type(value)->inline_klass();
2158 assert(oop_off_1 == -1 || oop_off_1 == 0 || oop_off_1 == 4, "invalid layout for %s, first oop at offset %d", vk->name()->as_utf8(), oop_off_1);
2159 assert(oop_off_2 == -1 || oop_off_2 == 4, "invalid layout for %s, second oop at offset %d", vk->name()->as_utf8(), oop_off_2);
2160 BasicType payload_bt = vk->atomic_size_to_basic_type(_null_free);
2161 kit.insert_mem_bar(Op_MemBarCPUOrder);
2162 if (!UseG1GC || oop_off_1 == -1) {
2163 // No oop fields or no late barrier expansion. Emit an atomic store of the payload and add GC barriers if needed.
2164 assert(oop_off_2 == -1 || !UseG1GC, "sanity");
2165 // ZGC does not support compressed oops, so only one oop can be in the payload which is written by a "normal" oop store.
2166 assert((oop_off_1 == -1 && oop_off_2 == -1) || !UseZGC, "ZGC does not support embedded oops in flat fields");
2167 kit.access_store_at(base, ptr, TypeRawPtr::BOTTOM, payload, Type::get_const_basic_type(payload_bt), payload_bt, _decorators | C2_MISMATCHED, true, value);
2168 } else {
2169 // Contains oops and requires late barrier expansion. Emit a special store node that allows to emit GC barriers in the backend.
2170 assert(UseG1GC, "Unexpected GC");
2171 assert(payload_bt == T_LONG, "Unexpected payload type");
2172 // If one oop, set the offset (if no offset is set, two oops are assumed by the backend)
2173 Node* oop_offset = (oop_off_2 == -1) ? igvn.intcon(oop_off_1) : nullptr;
2174 Node* mem = kit.reset_memory();
2175 kit.set_all_memory(mem);
2176 Node* store = igvn.transform(new StoreLSpecialNode(kit.control(), mem, ptr, TypeRawPtr::BOTTOM, payload, oop_offset, MemNode::unordered));
2177 kit.set_memory(store, TypeRawPtr::BOTTOM);
2178 }
2179 kit.insert_mem_bar(Op_MemBarCPUOrder);
2180
2181 Node* old_ctrl = proj_out_or_null(TypeFunc::Control);
2182 if (old_ctrl != nullptr) {
2183 igvn.replace_node(old_ctrl, kit.control());
2184 }
2185 Node* old_mem = proj_out_or_null(TypeFunc::Memory);
2186 Node* new_mem = kit.reset_memory();
2187 if (old_mem != nullptr) {
2188 igvn.replace_node(old_mem, new_mem);
2189 }
2190 }
2191
2192 // Convert the field values to a payload value of type 'bt'
2193 Node* StoreFlatNode::convert_to_payload(PhaseIterGVN& igvn, Node* ctrl, InlineTypeNode* value, bool null_free, int& oop_off_1, int& oop_off_2) {
2194 ciInlineKlass* vk = igvn.type(value)->inline_klass();
2195 BasicType payload_bt = vk->atomic_size_to_basic_type(null_free);
2196 Node* payload = igvn.zerocon(payload_bt);
2197 if (!null_free) {
2198 // Set the null marker
2199 payload = set_payload_value(igvn, payload_bt, payload, T_BOOLEAN, value->get_null_marker(), vk->null_marker_offset_in_payload());
2200 }
2201
2202 // Iterate over the fields and add their values to the payload
2203 for (int i = 0; i < vk->nof_nonstatic_fields(); i++) {
2204 ciField* field = vk->nonstatic_field_at(i);
2205 Node* field_value = value->field_value_by_offset(field->offset_in_bytes(), true);
2206 ciType* field_klass = field->type();
2207 BasicType field_bt = field_klass->basic_type();
2208 int field_offset_in_payload = field->offset_in_bytes() - vk->payload_offset();
2209 if (!field_klass->is_primitive_type()) {
2210 // Narrow oop field
2211 assert(UseCompressedOops && payload_bt == T_LONG, "Naturally atomic");
2212 if (oop_off_1 == -1) {
2213 oop_off_1 = field_offset_in_payload;
2214 } else {
2215 assert(oop_off_2 == -1, "already set");
2216 oop_off_2 = field_offset_in_payload;
2217 }
2218
2219 const Type* val_type = Type::get_const_type(field_klass)->make_narrowoop();
2220 if (field_value->is_InlineType()) {
2221 assert(field_value->as_InlineType()->is_allocated(&igvn), "must be allocated");
2222 }
2223
2224 field_value = igvn.transform(new EncodePNode(field_value, val_type));
2225 field_value = igvn.transform(new CastP2XNode(ctrl, field_value));
2226 field_value = igvn.transform(new ConvL2INode(field_value));
2227 field_bt = T_INT;
2228 }
2229 payload = set_payload_value(igvn, payload_bt, payload, field_bt, field_value, field_offset_in_payload);
2230 }
2231
2232 return payload;
2233 }
2234
2235 Node* StoreFlatNode::set_payload_value(PhaseIterGVN& igvn, BasicType payload_bt, Node* payload, BasicType val_bt, Node* value, int offset) {
2236 assert((offset + type2aelembytes(val_bt)) <= type2aelembytes(payload_bt), "Value does not fit into payload");
2237
2238 // Make sure to zero unused bits in the 32-bit value
2239 if (val_bt == T_BYTE || val_bt == T_BOOLEAN) {
2240 value = igvn.transform(new AndINode(value, igvn.intcon(0xFF)));
2241 } else if (val_bt == T_CHAR || val_bt == T_SHORT) {
2242 value = igvn.transform(new AndINode(value, igvn.intcon(0xFFFF)));
2243 } else if (val_bt == T_FLOAT) {
2244 value = igvn.transform(new MoveF2INode(value));
2245 } else {
2246 assert(val_bt == T_INT, "Unsupported type: %s", type2name(val_bt));
2247 }
2248
2249 Node* shift_val = igvn.intcon(offset << LogBitsPerByte);
2250 if (payload_bt == T_LONG) {
2251 // Convert to long and remove the sign bit (the backend will fold this and emit a zero extend i2l)
2252 value = igvn.transform(new ConvI2LNode(value));
2253 value = igvn.transform(new AndLNode(value, igvn.longcon(0xFFFFFFFF)));
2254
2255 Node* shift_value = igvn.transform(new LShiftLNode(value, shift_val));
2256 payload = new OrLNode(shift_value, payload);
2257 } else {
2258 Node* shift_value = igvn.transform(new LShiftINode(value, shift_val));
2259 payload = new OrINode(shift_value, payload);
2260 }
2261 return igvn.transform(payload);
2262 }
2263
2264 const Type* LoadFlatNode::Value(PhaseGVN* phase) const {
2265 if (phase->type(in(TypeFunc::Control)) == Type::TOP || phase->type(in(TypeFunc::Memory)) == Type::TOP ||
2266 phase->type(base()) == Type::TOP || phase->type(ptr()) == Type::TOP) {
2267 return Type::TOP;
2268 }
2269 return bottom_type();
2270 }
2271
2272 const Type* StoreFlatNode::Value(PhaseGVN* phase) const {
2273 if (phase->type(in(TypeFunc::Control)) == Type::TOP || phase->type(in(TypeFunc::Memory)) == Type::TOP ||
2274 phase->type(base()) == Type::TOP || phase->type(ptr()) == Type::TOP || phase->type(value()) == Type::TOP) {
2275 return Type::TOP;
2276 }
2277 return bottom_type();
2278 }