1 /*
2 * Copyright (c) 2024, 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 package compiler.valhalla.inlinetypes;
25
26 import jdk.internal.vm.annotation.LooselyConsistentValue;
27 import jdk.internal.vm.annotation.NullRestricted;
28
29 import jdk.test.lib.Asserts;
30 import jdk.test.lib.helpers.StrictInit;
31
32 /*
33 * @test id=noFlags
34 * @key randomness
35 * @summary Test support for null markers in flat fields.
36 * @library /test/lib /
37 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
38 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
39 * @enablePreview
40 * @modules java.base/jdk.internal.value
41 * java.base/jdk.internal.vm.annotation
42 * @compile TestFieldNullMarkers.java
43 * @run driver jdk.test.lib.helpers.StrictProcessor
44 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
45 * @run main/timeout=300 compiler.valhalla.inlinetypes.TestFieldNullMarkers
46 */
47
48 /*
49 * @test id=no-flattening
50 * @key randomness
51 * @summary Test support for null markers in flat fields.
52 * @library /test/lib /
53 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
54 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
55 * @enablePreview
56 * @modules java.base/jdk.internal.value
57 * java.base/jdk.internal.vm.annotation
58 * @compile TestFieldNullMarkers.java
59 * @run driver jdk.test.lib.helpers.StrictProcessor
60 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
61 * @run main/othervm/timeout=300 -Xbatch
62 * -XX:+UnlockDiagnosticVMOptions
63 * -XX:+UnlockExperimentalVMOptions
64 * -XX:-UseNullableAtomicValueFlattening -XX:-UseNullFreeAtomicValueFlattening -XX:-UseNullFreeNonAtomicValueFlattening
65 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
66 */
67
68 /*
69 * @test id=nAVF
70 * @key randomness
71 * @summary Test support for null markers in flat fields.
72 * @library /test/lib /
73 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
74 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
75 * @enablePreview
76 * @modules java.base/jdk.internal.value
77 * java.base/jdk.internal.vm.annotation
78 * @compile TestFieldNullMarkers.java
79 * @run driver jdk.test.lib.helpers.StrictProcessor
80 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
81 * @run main/othervm/timeout=300 -Xbatch
82 * -XX:+UnlockDiagnosticVMOptions
83 * -XX:+UnlockExperimentalVMOptions
84 * -XX:-UseNullableAtomicValueFlattening -XX:-UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
85 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
86 */
87
88 /*
89 * @test id=AVF
90 * @key randomness
91 * @summary Test support for null markers in flat fields.
92 * @library /test/lib /
93 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
94 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
95 * @enablePreview
96 * @modules java.base/jdk.internal.value
97 * java.base/jdk.internal.vm.annotation
98 * @compile TestFieldNullMarkers.java
99 * @run driver jdk.test.lib.helpers.StrictProcessor
100 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
101 * @run main/othervm/timeout=300 -Xbatch
102 * -XX:+UnlockDiagnosticVMOptions
103 * -XX:+UnlockExperimentalVMOptions
104 * -XX:-UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:-UseNullFreeNonAtomicValueFlattening
105 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
106 */
107
108 /*
109 * @test id=AVF-nAVF
110 * @key randomness
111 * @summary Test support for null markers in flat fields.
112 * @library /test/lib /
113 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
114 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
115 * @enablePreview
116 * @modules java.base/jdk.internal.value
117 * java.base/jdk.internal.vm.annotation
118 * @compile TestFieldNullMarkers.java
119 * @run driver jdk.test.lib.helpers.StrictProcessor
120 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
121 * @run main/othervm/timeout=300 -Xbatch
122 * -XX:+UnlockDiagnosticVMOptions
123 * -XX:+UnlockExperimentalVMOptions
124 * -XX:-UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
125 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
126 */
127
128 /*
129 * @test id=NVF
130 * @key randomness
131 * @summary Test support for null markers in flat fields.
132 * @library /test/lib /
133 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
134 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
135 * @enablePreview
136 * @modules java.base/jdk.internal.value
137 * java.base/jdk.internal.vm.annotation
138 * @compile TestFieldNullMarkers.java
139 * @run driver jdk.test.lib.helpers.StrictProcessor
140 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
141 * @run main/othervm/timeout=300 -Xbatch
142 * -XX:+UnlockDiagnosticVMOptions
143 * -XX:+UnlockExperimentalVMOptions
144 * -XX:+UseNullableAtomicValueFlattening -XX:-UseNullFreeAtomicValueFlattening -XX:-UseNullFreeNonAtomicValueFlattening
145 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
146 */
147
148 /*
149 * @test id=NVF-nAVF
150 * @key randomness
151 * @summary Test support for null markers in flat fields.
152 * @library /test/lib /
153 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
154 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
155 * @enablePreview
156 * @modules java.base/jdk.internal.value
157 * java.base/jdk.internal.vm.annotation
158 * @compile TestFieldNullMarkers.java
159 * @run driver jdk.test.lib.helpers.StrictProcessor
160 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
161 * @run main/othervm/timeout=300 -Xbatch
162 * -XX:+UnlockDiagnosticVMOptions
163 * -XX:+UnlockExperimentalVMOptions
164 * -XX:+UseNullableAtomicValueFlattening -XX:-UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
165 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
166 */
167
168 /*
169 * @test id=NVF-AVF
170 * @key randomness
171 * @summary Test support for null markers in flat fields.
172 * @library /test/lib /
173 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
174 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
175 * @enablePreview
176 * @modules java.base/jdk.internal.value
177 * java.base/jdk.internal.vm.annotation
178 * @compile TestFieldNullMarkers.java
179 * @run driver jdk.test.lib.helpers.StrictProcessor
180 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
181 * @run main/othervm/timeout=300 -Xbatch
182 * -XX:+UnlockDiagnosticVMOptions
183 * -XX:+UnlockExperimentalVMOptions
184 * -XX:+UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:-UseNullFreeNonAtomicValueFlattening
185 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
186 */
187
188 /*
189 * @test id=all-flattening
190 * @key randomness
191 * @summary Test support for null markers in flat fields.
192 * @library /test/lib /
193 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
194 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
195 * @enablePreview
196 * @modules java.base/jdk.internal.value
197 * java.base/jdk.internal.vm.annotation
198 * @compile TestFieldNullMarkers.java
199 * @run driver jdk.test.lib.helpers.StrictProcessor
200 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
201 * @run main/othervm/timeout=300 -Xbatch
202 * -XX:+UnlockDiagnosticVMOptions
203 * -XX:+UnlockExperimentalVMOptions
204 * -XX:+UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
205 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
206 */
207
208 /*
209 * @test id=all-flattening-di
210 * @key randomness
211 * @summary Test support for null markers in flat fields.
212 * @library /test/lib /
213 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
214 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
215 * @enablePreview
216 * @modules java.base/jdk.internal.value
217 * java.base/jdk.internal.vm.annotation
218 * @compile TestFieldNullMarkers.java
219 * @run driver jdk.test.lib.helpers.StrictProcessor
220 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
221 * @run main/othervm/timeout=300 -Xbatch
222 * -XX:+UnlockDiagnosticVMOptions
223 * -XX:+UnlockExperimentalVMOptions
224 * -XX:+UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
225 * -XX:CompileCommand=dontinline,*::testHelper*
226 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
227 */
228
229 /*
230 * @test id=all-flattening-pass-fields
231 * @key randomness
232 * @summary Test support for null markers in flat fields.
233 * @library /test/lib /
234 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
235 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
236 * @enablePreview
237 * @modules java.base/jdk.internal.value
238 * java.base/jdk.internal.vm.annotation
239 * @compile TestFieldNullMarkers.java
240 * @run driver jdk.test.lib.helpers.StrictProcessor
241 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
242 * @run main/othervm/timeout=300 -Xbatch
243 * -XX:+UnlockDiagnosticVMOptions
244 * -XX:+UnlockExperimentalVMOptions
245 * -XX:+UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
246 * -XX:+InlineTypeReturnedAsFields -XX:+InlineTypePassFieldsAsArgs
247 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
248 */
249
250 /*
251 * @test id=all-flattening-no-pass-fields
252 * @key randomness
253 * @summary Test support for null markers in flat fields.
254 * @library /test/lib /
255 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
256 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
257 * @enablePreview
258 * @modules java.base/jdk.internal.value
259 * java.base/jdk.internal.vm.annotation
260 * @compile TestFieldNullMarkers.java
261 * @run driver jdk.test.lib.helpers.StrictProcessor
262 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
263 * @run main/othervm/timeout=300 -Xbatch
264 * -XX:+UnlockDiagnosticVMOptions
265 * -XX:+UnlockExperimentalVMOptions
266 * -XX:+UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
267 * -XX:-InlineTypeReturnedAsFields -XX:-InlineTypePassFieldsAsArgs
268 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
269 */
270
271 /*
272 * @test id=all-flattening-return-fields
273 * @key randomness
274 * @summary Test support for null markers in flat fields.
275 * @library /test/lib /
276 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
277 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
278 * @enablePreview
279 * @modules java.base/jdk.internal.value
280 * java.base/jdk.internal.vm.annotation
281 * @compile TestFieldNullMarkers.java
282 * @run driver jdk.test.lib.helpers.StrictProcessor
283 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
284 * @run main/othervm/timeout=300 -Xbatch
285 * -XX:+UnlockDiagnosticVMOptions
286 * -XX:+UnlockExperimentalVMOptions
287 * -XX:+UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
288 * -XX:+InlineTypeReturnedAsFields -XX:-InlineTypePassFieldsAsArgs
289 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
290 */
291
292 /*
293 * @test id=all-flattening-pass-args
294 * @key randomness
295 * @summary Test support for null markers in flat fields.
296 * @library /test/lib /
297 * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
298 * @requires (vm.opt.PreloadClasses == null | vm.opt.PreloadClasses == "true")
299 * @enablePreview
300 * @modules java.base/jdk.internal.value
301 * java.base/jdk.internal.vm.annotation
302 * @compile TestFieldNullMarkers.java
303 * @run driver jdk.test.lib.helpers.StrictProcessor
304 * compiler.valhalla.inlinetypes.TestFieldNullMarkers$StrictFieldHolder
305 * @run main/othervm/timeout=300 -Xbatch
306 * -XX:+UnlockDiagnosticVMOptions
307 * -XX:+UnlockExperimentalVMOptions
308 * -XX:+UseNullableAtomicValueFlattening -XX:+UseNullFreeAtomicValueFlattening -XX:+UseNullFreeNonAtomicValueFlattening
309 * -XX:-InlineTypeReturnedAsFields -XX:+InlineTypePassFieldsAsArgs
310 * compiler.valhalla.inlinetypes.TestFieldNullMarkers
311 */
312
313 public class TestFieldNullMarkers {
314
315 public TestFieldNullMarkers() {
316 field12 = new MyValue8((byte)0);
317 field13 = MyValue14.DEFAULT;
318 field16 = MyValue14.DEFAULT;
319 field17 = new MyValue15(null);
320 field19 = new MyValue16(null, null);
321 field20 = new MyValue17(null, (byte)0, (byte)0);
322 emptyField1 = new MyValueEmpty();
323 emptyField2 = new MyValueEmpty();
324 super();
325 }
326
327 // Value class with two nullable flat fields
328 @LooselyConsistentValue
329 static value class MyValue1 {
330 byte x;
331 MyValue2 val1;
332 MyValue2 val2;
333
334 public MyValue1(byte x, MyValue2 val1, MyValue2 val2) {
335 this.x = x;
336 this.val1 = val1;
337 this.val2 = val2;
338 }
339
340 public String toString() {
341 return "x = " + x + ", val1 = [" + val1 + "], val2 = [" + val2 + "]";
342 }
343 }
344
345 @LooselyConsistentValue
346 static abstract value class MyAbstract1 {
347 byte x;
348
349 public MyAbstract1(byte x) {
350 this.x = x;
351 }
352 }
353
354 // Empty value class inheriting single field from abstract super class
355 @LooselyConsistentValue
356 static value class MyValue2 extends MyAbstract1 {
357 public MyValue2(byte x) {
358 super(x);
359 }
360
361 public String toString() {
362 return "x = " + x;
363 }
364 }
365
366 // Value class with a hole in the payload that will be used for the null marker
367 @LooselyConsistentValue
368 static value class MyValue3 {
369 byte x;
370 // Hole that will be used by the null marker
371 int i;
372
373 public MyValue3(byte x) {
374 this.x = x;
375 this.i = x;
376 }
377
378 public String toString() {
379 return "x = " + x + ", i = " + i;
380 }
381 }
382
383 // Value class with two nullable flat fields that have their null markers *not* at the end of the payload
384 @LooselyConsistentValue
385 static value class MyValue4 {
386 MyValue3 val1;
387 MyValue3 val2;
388
389 public MyValue4(MyValue3 val1, MyValue3 val2) {
390 this.val1 = val1;
391 this.val2 = val2;
392 }
393
394 public String toString() {
395 return "val1 = [" + val1 + "], val2 = [" + val2 + "]";
396 }
397 }
398
399 @LooselyConsistentValue
400 static value class MyValue5C {
401 byte x;
402
403 public MyValue5C(byte x) {
404 this.x = x;
405 }
406 }
407
408 @LooselyConsistentValue
409 static value class MyValue5B {
410 byte x;
411 MyValue5C val;
412
413 public MyValue5B(byte x, MyValue5C val) {
414 this.x = x;
415 this.val = val;
416 }
417 }
418
419 @LooselyConsistentValue
420 static value class MyValue5A {
421 byte x;
422 MyValue5B val;
423
424 public MyValue5A(byte x, MyValue5B val) {
425 this.x = x;
426 this.val = val;
427 }
428 }
429
430 // Value class with deep nesting of nullable flat fields
431 @LooselyConsistentValue
432 static value class MyValue5 {
433 byte x;
434 MyValue5A val;
435
436 public MyValue5(byte x, MyValue5A val) {
437 this.x = x;
438 this.val = val;
439 }
440 }
441
442 @LooselyConsistentValue
443 static value class MyValueEmpty {
444
445 }
446
447 // Value class with flat field of empty value class
448 @LooselyConsistentValue
449 static value class MyValue6 {
450 MyValueEmpty val;
451
452 public MyValue6(MyValueEmpty val) {
453 this.val = val;
454 }
455 }
456
457 // Same as MyValue6 but one more level of nested flat fields
458 @LooselyConsistentValue
459 static value class MyValue7 {
460 MyValue6 val;
461
462 public MyValue7(MyValue6 val) {
463 this.val = val;
464 }
465 }
466
467 // Some more field types
468
469 @LooselyConsistentValue
470 static value class MyValue8 {
471 byte b;
472
473 public MyValue8(byte b) {
474 this.b = b;
475 }
476 }
477
478 @LooselyConsistentValue
479 static value class MyValue9 {
480 short s;
481
482 public MyValue9(short s) {
483 this.s = s;
484 }
485 }
486
487 @LooselyConsistentValue
488 static value class MyValue10 {
489 int i;
490
491 public MyValue10(int i) {
492 this.i = i;
493 }
494 }
495
496 @LooselyConsistentValue
497 static value class MyValue11 {
498 float f;
499
500 public MyValue11(float f) {
501 this.f = f;
502 }
503 }
504
505 @LooselyConsistentValue
506 static value class MyValue12 {
507 char c;
508
509 public MyValue12(char c) {
510 this.c = c;
511 }
512 }
513
514 @LooselyConsistentValue
515 static value class MyValue13 {
516 boolean b;
517
518 public MyValue13(boolean b) {
519 this.b = b;
520 }
521 }
522
523 // Test value class with nullable and null-free fields
524 @LooselyConsistentValue
525 static value class MyValue14 {
526 @NullRestricted
527 MyValue8 nullfree;
528 MyValue8 nullable;
529
530 public MyValue14(MyValue8 nullfree, MyValue8 nullable) {
531 this.nullfree = nullfree;
532 this.nullable = nullable;
533 }
534
535 public static final MyValue14 DEFAULT = new MyValue14(new MyValue8((byte)0), null);
536 }
537
538 static class MyClass {
539 int x;
540
541 public MyClass(int x) {
542 this.x = x;
543 }
544 }
545
546 // Value class with oop field
547 @LooselyConsistentValue
548 static value class MyValue15 {
549 MyClass obj;
550
551 public MyValue15(MyClass obj) {
552 this.obj = obj;
553 }
554 }
555
556 // Value class with two oop fields
557 @LooselyConsistentValue
558 static value class MyValue16 {
559 MyClass obj1;
560 MyClass obj2;
561
562 public MyValue16(MyClass obj1, MyClass obj2) {
563 this.obj1 = obj1;
564 this.obj2 = obj2;
565 }
566 }
567
568 // Value class with oop field and primitive fields
569 @LooselyConsistentValue
570 static value class MyValue17 {
571 byte b1;
572 MyClass obj;
573 byte b2;
574
575 public MyValue17(MyClass obj, byte b1, byte b2) {
576 this.obj = obj;
577 this.b1 = b1;
578 this.b2 = b2;
579 }
580 }
581
582 MyValue1 field1; // Not flat
583 MyValue4 field2; // Not flat
584 MyValue5 field3; // Flat
585 MyValue6 field4; // Flat
586 MyValue7 field5; // Flat
587 MyValue8 field6; // Flat
588 MyValue9 field7; // Flat
589 MyValue10 field8; // Flat
590 MyValue11 field9; // Flat
591 MyValue12 field10; // Flat
592 MyValue13 field11; // Flat
593
594 @NullRestricted
595 volatile MyValue8 field12;
596
597 @NullRestricted
598 MyValue14 field13; // Null-free, flat
599 volatile MyValue14 field14; // Nullable, atomic, flat
600 MyValue14 field15; // Nullable, (atomic), flat
601 @NullRestricted
602 volatile MyValue14 field16; // Null-free, atomic, flat
603
604 @NullRestricted
605 volatile MyValue15 field17;
606 MyValue15 field18;
607 @NullRestricted
608 volatile MyValue16 field19;
609 @NullRestricted
610 volatile MyValue17 field20;
611 MyValue17 field21;
612
613 // Combinations of strict fields
614 static class StrictFieldHolder {
615 @StrictInit
616 MyValue8 strictField1;
617 @StrictInit
618 final MyValue8 strictField2;
619 @NullRestricted
620 MyValue8 strictField3;
621 @NullRestricted
622 final MyValue8 strictField4;
623 @StrictInit
624 volatile MyValue8 strictField5;
625 @NullRestricted
626 volatile MyValue8 strictField6;
627
628 @StrictInit
629 TwoBytes strictField7;
630 @StrictInit
631 final TwoBytes strictField8;
632 @NullRestricted
633 TwoBytes strictField9;
634 @NullRestricted
635 final TwoBytes strictField10;
636 @StrictInit
637 volatile TwoBytes strictField11;
638 @NullRestricted
639 volatile TwoBytes strictField12;
640
641 public StrictFieldHolder(MyValue8 val8, MyValue8 val8NullFree, TwoBytes twoBytes, TwoBytes twoBytesNullFree) {
642 strictField1 = val8;
643 strictField2 = val8;
644 strictField3 = val8NullFree;
645 strictField4 = val8NullFree;
646 strictField5 = val8NullFree;
647 strictField6 = val8NullFree;
648
649 strictField7 = twoBytes;
650 strictField8 = twoBytes;
651 strictField9 = twoBytesNullFree;
652 strictField10 = twoBytesNullFree;
653 strictField11 = twoBytesNullFree;
654 strictField12 = twoBytesNullFree;
655 super();
656 }
657 }
658
659 @NullRestricted
660 MyValueEmpty emptyField1;
661 @NullRestricted
662 volatile MyValueEmpty emptyField2;
663 MyValueEmpty emptyField3;
664 volatile MyValueEmpty emptyField4;
665
666 static final MyValue1 VAL1 = new MyValue1((byte)42, new MyValue2((byte)43), null);
667 static final MyValue4 VAL4 = new MyValue4(new MyValue3((byte)42), null);
668 static final MyValue5 VAL5 = new MyValue5((byte)42, new MyValue5A((byte)43, new MyValue5B((byte)44, new MyValue5C((byte)45))));
669 static final MyValue6 VAL6 = new MyValue6(new MyValueEmpty());
670 static final MyValue7 VAL7 = new MyValue7(new MyValue6(new MyValueEmpty()));
671
672 // Using two bytes such that null-free fields will not be naturally atomic
673 @LooselyConsistentValue
674 static value class TwoBytes {
675 byte b1;
676 byte b2;
677
678 public TwoBytes(byte b1, byte b2) {
679 this.b1 = b1;
680 this.b2 = b2;
681 }
682
683 public static final TwoBytes DEFAULT = new TwoBytes((byte)0, (byte)0);
684 }
685
686 static private final MyValue8 CANARY_VALUE = new MyValue8((byte)42);
687
688 public static class Cage1 {
689 MyValue8 canary1 = CANARY_VALUE;
690
691 @NullRestricted
692 volatile TwoBytes field;
693
694 MyValue8 canary2 = CANARY_VALUE;
695
696 public Cage1() {
697 field = TwoBytes.DEFAULT;
698 super();
699 }
700
701 public void verify(TwoBytes val) {
702 Asserts.assertEQ(canary1, CANARY_VALUE);
703 Asserts.assertEQ(field, val);
704 Asserts.assertEQ(canary2, CANARY_VALUE);
705 }
706 }
707
708 public static class Cage2 {
709 @NullRestricted
710 MyValue8 canary1;
711
712 @NullRestricted
713 volatile TwoBytes field;
714
715 @NullRestricted
716 MyValue8 canary2;
717
718 public Cage2() {
719 canary1 = CANARY_VALUE;
720 field = TwoBytes.DEFAULT;
721 canary2 = CANARY_VALUE;
722 super();
723 }
724
725 public void verify(TwoBytes val) {
726 Asserts.assertEQ(canary1, CANARY_VALUE);
727 Asserts.assertEQ(field, val);
728 Asserts.assertEQ(canary2, CANARY_VALUE);
729 }
730 }
731
732 public static class Cage3 {
733 @NullRestricted
734 MyValue8 canary1;
735
736 volatile TwoBytes field;
737
738 @NullRestricted
739 MyValue8 canary2;
740
741 public Cage3() {
742 canary1 = CANARY_VALUE;
743 canary2 = CANARY_VALUE;
744 super();
745 }
746
747 public void verify(TwoBytes val) {
748 Asserts.assertEQ(canary1, CANARY_VALUE);
749 Asserts.assertEQ(field, val);
750 Asserts.assertEQ(canary2, CANARY_VALUE);
751 }
752 }
753
754 public static class Cage4 {
755 MyValue8 canary1 = CANARY_VALUE;
756
757 volatile TwoBytes field;
758
759 MyValue8 canary2 = CANARY_VALUE;
760
761 public void verify(TwoBytes val) {
762 Asserts.assertEQ(canary1, CANARY_VALUE);
763 Asserts.assertEQ(field, val);
764 Asserts.assertEQ(canary2, CANARY_VALUE);
765 }
766 }
767
768 static final Cage1 canaryCage1 = new Cage1();
769 static final Cage2 canaryCage2 = new Cage2();
770 static final Cage3 canaryCage3 = new Cage3();
771 static final Cage4 canaryCage4 = new Cage4();
772
773 // Check that the canary values are not accidentally overwritten
774 public void testOutOfBoundsAccess(int i) {
775 TwoBytes val = new TwoBytes((byte)i, (byte)(i+1));
776 canaryCage1.field = val;
777 canaryCage1.verify(val);
778
779 canaryCage2.field = val;
780 canaryCage2.verify(val);
781
782 canaryCage3.field = val;
783 canaryCage3.verify(val);
784
785 canaryCage3.field = null;
786 canaryCage3.verify(null);
787
788 canaryCage4.field = val;
789 canaryCage4.verify(val);
790
791 canaryCage4.field = null;
792 canaryCage4.verify(null);
793 }
794
795 // Test that the calling convention is keeping track of the null marker
796 public MyValue1 testHelper1(MyValue1 val) {
797 return val;
798 }
799
800 public void testSet1(MyValue1 val) {
801 field1 = testHelper1(val);
802 }
803
804 public MyValue1 testGet1() {
805 return field1;
806 }
807
808 public void testDeopt1(byte x, MyValue1 neverNull, MyValue1 alwaysNull, boolean deopt) {
809 MyValue2 val2 = new MyValue2(x);
810 MyValue1 val1 = new MyValue1(x, val2, val2);
811 if (deopt) {
812 Asserts.assertEQ(val1.x, x);
813 Asserts.assertEQ(val1.val1, val2);
814 Asserts.assertEQ(val1.val2, val2);
815 Asserts.assertEQ(neverNull.x, x);
816 Asserts.assertEQ(neverNull.val1, val2);
817 Asserts.assertEQ(neverNull.val2, val2);
818 Asserts.assertEQ(alwaysNull.x, x);
819 Asserts.assertEQ(alwaysNull.val1, null);
820 Asserts.assertEQ(alwaysNull.val2, null);
821 }
822 }
823
824 public void testOSR() {
825 // Trigger OSR
826 for (int i = 0; i < 100_000; ++i) {
827 field1 = null;
828 Asserts.assertEQ(field1, null);
829 MyValue2 val2 = new MyValue2((byte)i);
830 MyValue1 val = new MyValue1((byte)i, val2, null);
831 field1 = val;
832 Asserts.assertEQ(field1.x, (byte)i);
833 Asserts.assertEQ(field1.val1, val2);
834 Asserts.assertEQ(field1.val2, null);
835 }
836 }
837
838 public boolean testACmp(MyValue2 val2) {
839 return field1.val1 == val2;
840 }
841
842 // Test that the calling convention is keeping track of the null marker
843 public MyValue4 testHelper2(MyValue4 val) {
844 return val;
845 }
846
847 public void testSet2(MyValue4 val) {
848 field2 = testHelper2(val);
849 }
850
851 public MyValue4 testGet2() {
852 return field2;
853 }
854
855 public void testDeopt2(byte x, MyValue4 neverNull, MyValue4 alwaysNull, boolean deopt) {
856 MyValue3 val3 = new MyValue3(x);
857 MyValue4 val4 = new MyValue4(val3, null);
858 if (deopt) {
859 Asserts.assertEQ(val4.val1, val3);
860 Asserts.assertEQ(val4.val2, null);
861 Asserts.assertEQ(neverNull.val1, val3);
862 Asserts.assertEQ(neverNull.val2, val3);
863 Asserts.assertEQ(alwaysNull.val1, null);
864 Asserts.assertEQ(alwaysNull.val2, null);
865 }
866 }
867
868 // Test that the calling convention is keeping track of the null marker
869 public MyValue5 testHelper3(MyValue5 val) {
870 return val;
871 }
872
873 public void testSet3(MyValue5 val) {
874 field3 = testHelper3(val);
875 }
876
877 public MyValue5 testGet3() {
878 return field3;
879 }
880
881 public void testDeopt3(byte x, MyValue5 val6, MyValue5 val7, MyValue5 val8, MyValue5 val9, boolean deopt) {
882 MyValue5 val1 = new MyValue5(x, new MyValue5A(x, new MyValue5B(x, new MyValue5C(x))));
883 MyValue5 val2 = new MyValue5(x, new MyValue5A(x, new MyValue5B(x, null)));
884 MyValue5 val3 = new MyValue5(x, new MyValue5A(x, null));
885 MyValue5 val4 = new MyValue5(x, null);
886 MyValue5 val5 = null;
887 if (deopt) {
888 Asserts.assertEQ(val1.x, x);
889 Asserts.assertEQ(val1.val.x, x);
890 Asserts.assertEQ(val1.val.val.x, x);
891 Asserts.assertEQ(val1.val.val.val.x, x);
892 Asserts.assertEQ(val2.x, x);
893 Asserts.assertEQ(val2.val.x, x);
894 Asserts.assertEQ(val2.val.val.x, x);
895 Asserts.assertEQ(val2.val.val.val, null);
896 Asserts.assertEQ(val3.x, x);
897 Asserts.assertEQ(val3.val.x, x);
898 Asserts.assertEQ(val3.val.val, null);
899 Asserts.assertEQ(val4.x, x);
900 Asserts.assertEQ(val4.val, null);
901 Asserts.assertEQ(val5, null);
902
903 Asserts.assertEQ(val6.x, x);
904 Asserts.assertEQ(val6.val.x, x);
905 Asserts.assertEQ(val6.val.val.x, x);
906 Asserts.assertEQ(val6.val.val.val.x, x);
907 Asserts.assertEQ(val7.x, x);
908 Asserts.assertEQ(val7.val.x, x);
909 Asserts.assertEQ(val7.val.val.x, x);
910 Asserts.assertEQ(val7.val.val.val, null);
911 Asserts.assertEQ(val8.x, x);
912 Asserts.assertEQ(val8.val.x, x);
913 Asserts.assertEQ(val8.val.val, null);
914 Asserts.assertEQ(val9.x, x);
915 Asserts.assertEQ(val9.val, null);
916 }
917 }
918
919 // Test that the calling convention is keeping track of the null marker
920 public MyValue6 testHelper4(MyValue6 val) {
921 return val;
922 }
923
924 public void testSet4(MyValue6 val) {
925 field4 = testHelper4(val);
926 }
927
928 public MyValue6 testGet4() {
929 return field4;
930 }
931
932 public void testDeopt4(MyValue6 val4, MyValue6 val5, MyValue6 val6, boolean deopt) {
933 MyValue6 val1 = new MyValue6(new MyValueEmpty());
934 MyValue6 val2 = new MyValue6(null);
935 MyValue6 val3 = null;
936 if (deopt) {
937 Asserts.assertEQ(val1.val, new MyValueEmpty());
938 Asserts.assertEQ(val2.val, null);
939 Asserts.assertEQ(val3, null);
940
941 Asserts.assertEQ(val4.val, new MyValueEmpty());
942 Asserts.assertEQ(val5.val, null);
943 Asserts.assertEQ(val6, null);
944 }
945 }
946
947 // Test that the calling convention is keeping track of the null marker
948 public MyValue7 testHelper5(MyValue7 val) {
949 return val;
950 }
951
952 public void testSet5(MyValue7 val) {
953 field5 = testHelper5(val);
954 }
955
956 public MyValue7 testGet5() {
957 return field5;
958 }
959
960 public void testDeopt5(MyValue7 val5, MyValue7 val6, MyValue7 val7, MyValue7 val8, boolean deopt) {
961 MyValue7 val1 = new MyValue7(new MyValue6(new MyValueEmpty()));
962 MyValue7 val2 = new MyValue7(new MyValue6(null));
963 MyValue7 val3 = new MyValue7(null);
964 MyValue7 val4 = null;
965 if (deopt) {
966 Asserts.assertEQ(val1.val, new MyValue6(new MyValueEmpty()));
967 Asserts.assertEQ(val2.val, new MyValue6(null));
968 Asserts.assertEQ(val3.val, null);
969 Asserts.assertEQ(val4, null);
970
971 Asserts.assertEQ(val5.val, new MyValue6(new MyValueEmpty()));
972 Asserts.assertEQ(val6.val, new MyValue6(null));
973 Asserts.assertEQ(val7.val, null);
974 Asserts.assertEQ(val8, null);
975 }
976 }
977
978 // Make sure that flat field accesses contain a (implicit) null check
979 public static void testNPE1() {
980 TestFieldNullMarkers t = null;
981 try {
982 MyValue8 v = t.field6;
983 throw new RuntimeException("No NPE thrown!");
984 } catch (NullPointerException e) {
985 // Expected
986 }
987 }
988
989 public static void testNPE2() {
990 TestFieldNullMarkers t = null;
991 try {
992 t.field6 = null;
993 throw new RuntimeException("No NPE thrown!");
994 } catch (NullPointerException e) {
995 // Expected
996 }
997 }
998
999 public void checkFields(int i) {
1000 Asserts.assertEQ(field6.b, (byte)i);
1001 Asserts.assertEQ(field7.s, (short)i);
1002 Asserts.assertEQ(field8.i, i);
1003 Asserts.assertEQ(field9.f, (float)i);
1004 Asserts.assertEQ(field10.c, (char)i);
1005 Asserts.assertEQ(field11.b, (i % 2) == 0);
1006 }
1007
1008 // Test that writing and reading a (signed) byte stays in bounds
1009 public void testBounds(int i) {
1010 MyValue8 val = new MyValue8((byte)i);
1011 field6 = val;
1012 int b = field6.b;
1013 if (b < -128 || b > 127) {
1014 throw new RuntimeException("Byte value out of bounds: " + b);
1015 }
1016 }
1017
1018 static void produceGarbage() {
1019 for (int i = 0; i < 100; ++i) {
1020 Object[] arrays = new Object[1024];
1021 for (int j = 0; j < arrays.length; j++) {
1022 arrays[j] = new int[1024];
1023 }
1024 }
1025 System.gc();
1026 }
1027
1028 // Test that barriers are emitted when writing flat, atomic fields with oops
1029 public void testWriteOopFields1(MyValue15 val) {
1030 field17 = val;
1031 field18 = val;
1032 }
1033
1034 public void testWriteOopFields2(MyValue16 val) {
1035 field19 = val;
1036 }
1037
1038 public void testWriteOopFields3(MyValue17 val) {
1039 field20 = val;
1040 field21 = val;
1041 }
1042
1043 public static class MyHolderClass9 {
1044 @NullRestricted
1045 TwoBytes field1;
1046
1047 TwoBytes field2;
1048
1049 @NullRestricted
1050 volatile TwoBytes field3;
1051
1052 volatile TwoBytes field4;
1053
1054 public MyHolderClass9() {
1055 field1 = TwoBytes.DEFAULT;
1056 field3 = TwoBytes.DEFAULT;
1057 super();
1058 }
1059 }
1060
1061 static final MyHolderClass9 constantHolder = new MyHolderClass9();
1062
1063 // Test loading a flat field from a constant container (should not be constant folded because fields are immutable)
1064 public void testLoadingFromConstantHolder(int i) {
1065 TwoBytes val = new TwoBytes((byte)i, (byte)(i + 1));
1066 constantHolder.field1 = val;
1067 Asserts.assertEQ(constantHolder.field1, val);
1068
1069 constantHolder.field2 = val;
1070 Asserts.assertEQ(constantHolder.field2, val);
1071
1072 constantHolder.field2 = null;
1073 Asserts.assertEQ(constantHolder.field2, null);
1074
1075 constantHolder.field3 = val;
1076 Asserts.assertEQ(constantHolder.field3, val);
1077
1078 constantHolder.field4 = val;
1079 Asserts.assertEQ(constantHolder.field4, val);
1080
1081 constantHolder.field4 = null;
1082 Asserts.assertEQ(constantHolder.field4, null);
1083 }
1084
1085 public void testStrictFields(StrictFieldHolder holder, MyValue8 val8, MyValue8 val8NullFree, TwoBytes twoBytes, TwoBytes twoBytesNullFree) {
1086 Asserts.assertEQ(holder.strictField1, val8);
1087 Asserts.assertEQ(holder.strictField2, val8);
1088 Asserts.assertEQ(holder.strictField3, val8NullFree);
1089 Asserts.assertEQ(holder.strictField4, val8NullFree);
1090 Asserts.assertEQ(holder.strictField5, val8NullFree);
1091 Asserts.assertEQ(holder.strictField6, val8NullFree);
1092
1093 Asserts.assertEQ(holder.strictField7, twoBytes);
1094 Asserts.assertEQ(holder.strictField8, twoBytes);
1095 Asserts.assertEQ(holder.strictField9, twoBytesNullFree);
1096 Asserts.assertEQ(holder.strictField10, twoBytesNullFree);
1097 Asserts.assertEQ(holder.strictField11, twoBytesNullFree);
1098 Asserts.assertEQ(holder.strictField12, twoBytesNullFree);
1099 }
1100
1101 public static void main(String[] args) {
1102 TestFieldNullMarkers t = new TestFieldNullMarkers();
1103 t.testOSR();
1104
1105 final int LIMIT = 50_000;
1106 for (int i = -50_000; i < LIMIT; ++i) {
1107 t.field1 = null;
1108 Asserts.assertEQ(t.testGet1(), null);
1109
1110 boolean useNull = (i % 2) == 0;
1111 MyValue2 val2 = useNull ? null : new MyValue2((byte)i);
1112 MyValue1 val = new MyValue1((byte)i, val2, val2);
1113 t.field1 = val;
1114 Asserts.assertEQ(t.testGet1().x, val.x);
1115 Asserts.assertEQ(t.testGet1().val1, val2);
1116 Asserts.assertEQ(t.testGet1().val2, val2);
1117
1118 Asserts.assertTrue(t.testACmp(val2));
1119
1120 t.testSet1(null);
1121 Asserts.assertEQ(t.field1, null);
1122
1123 t.testSet1(val);
1124 Asserts.assertEQ(t.field1.x, val.x);
1125 Asserts.assertEQ(t.field1.val1, val2);
1126 Asserts.assertEQ(t.field1.val2, val2);
1127
1128 t.testDeopt1((byte)i, null, null, false);
1129
1130 t.field2 = null;
1131 Asserts.assertEQ(t.testGet2(), null);
1132
1133 MyValue3 val3 = useNull ? null : new MyValue3((byte)i);
1134 MyValue4 val4 = new MyValue4(val3, val3);
1135 t.field2 = val4;
1136 Asserts.assertEQ(t.testGet2().val1, val3);
1137 Asserts.assertEQ(t.testGet2().val2, val3);
1138
1139 t.testSet2(null);
1140 Asserts.assertEQ(t.testGet2(), null);
1141
1142 t.testSet2(val4);
1143 Asserts.assertEQ(t.testGet2().val1, val3);
1144 Asserts.assertEQ(t.testGet2().val2, val3);
1145
1146 t.testDeopt2((byte)i, null, null, false);
1147
1148 t.field3 = null;
1149 Asserts.assertEQ(t.testGet3(), null);
1150
1151 boolean useNull_1 = (i % 4) == 0;
1152 boolean useNull_2 = (i % 4) == 1;
1153 boolean useNull_3 = (i % 4) == 2;
1154 MyValue5C val5_3 = useNull_3 ? null : new MyValue5C((byte)i);
1155 MyValue5B val5_2 = useNull_2 ? null : new MyValue5B((byte)i, val5_3);
1156 MyValue5A val5_1 = useNull_1 ? null : new MyValue5A((byte)i, val5_2);
1157 MyValue5 val5 = new MyValue5((byte)i, val5_1);
1158 t.field3 = val5;
1159 Asserts.assertEQ(t.testGet3().x, val5.x);
1160 if (useNull_1) {
1161 Asserts.assertEQ(t.testGet3().val, null);
1162 } else {
1163 Asserts.assertEQ(t.testGet3().val.x, val5_1.x);
1164 if (useNull_2) {
1165 Asserts.assertEQ(t.testGet3().val.val, null);
1166 } else {
1167 Asserts.assertEQ(t.testGet3().val.val.x, val5_2.x);
1168 if (useNull_3) {
1169 Asserts.assertEQ(t.testGet3().val.val.val, null);
1170 } else {
1171 Asserts.assertEQ(t.testGet3().val.val.val.x, val5_3.x);
1172 }
1173 }
1174 }
1175
1176 t.testSet3(null);
1177 Asserts.assertEQ(t.field3, null);
1178
1179 t.testSet3(val5);
1180 Asserts.assertEQ(t.testGet3().x, val5.x);
1181 if (useNull_1) {
1182 Asserts.assertEQ(t.testGet3().val, null);
1183 } else {
1184 Asserts.assertEQ(t.testGet3().val.x, val5_1.x);
1185 if (useNull_2) {
1186 Asserts.assertEQ(t.testGet3().val.val, null);
1187 } else {
1188 Asserts.assertEQ(t.testGet3().val.val.x, val5_2.x);
1189 if (useNull_3) {
1190 Asserts.assertEQ(t.testGet3().val.val.val, null);
1191 } else {
1192 Asserts.assertEQ(t.testGet3().val.val.val.x, val5_3.x);
1193 }
1194 }
1195 }
1196 t.testDeopt3((byte)i, null, null, null, null, false);
1197
1198 t.field4 = null;
1199 Asserts.assertEQ(t.testGet4(), null);
1200
1201 MyValueEmpty empty = useNull ? null : new MyValueEmpty();
1202 MyValue6 val6 = new MyValue6(empty);
1203 t.field4 = val6;
1204 Asserts.assertEQ(t.testGet4().val, empty);
1205
1206 t.testSet4(null);
1207 Asserts.assertEQ(t.testGet4(), null);
1208
1209 t.testSet4(val6);
1210 Asserts.assertEQ(t.testGet4().val, empty);
1211
1212 t.testDeopt4(null, null, null, false);
1213
1214 t.field5 = null;
1215 Asserts.assertEQ(t.testGet5(), null);
1216
1217 empty = ((i % 3) == 0) ? null : new MyValueEmpty();
1218 val6 = ((i % 3) == 1) ? null : new MyValue6(empty);
1219 MyValue7 val7 = new MyValue7(val6);
1220 t.field5 = val7;
1221 Asserts.assertEQ(t.testGet5().val, val6);
1222
1223 t.testSet5(null);
1224 Asserts.assertEQ(t.testGet5(), null);
1225
1226 t.testSet5(val7);
1227 Asserts.assertEQ(t.testGet5().val, val6);
1228
1229 t.testDeopt5(null, null, null, null, false);
1230
1231 // Check accesses with constant value
1232 t.field1 = VAL1;
1233 Asserts.assertEQ(t.field1.x, VAL1.x);
1234 Asserts.assertEQ(t.field1.val1, VAL1.val1);
1235 Asserts.assertEQ(t.field1.val2, VAL1.val2);
1236
1237 t.field2 = VAL4;
1238 Asserts.assertEQ(t.field2.val1, VAL4.val1);
1239 Asserts.assertEQ(t.field2.val2, VAL4.val2);
1240
1241 t.field3 = VAL5;
1242 Asserts.assertEQ(t.field3.x, VAL5.x);
1243 Asserts.assertEQ(t.field3.val.x, VAL5.val.x);
1244 Asserts.assertEQ(t.field3.val.val.x, VAL5.val.val.x);
1245 Asserts.assertEQ(t.field3.val.val.val.x, VAL5.val.val.val.x);
1246
1247 t.field4 = VAL6;
1248 Asserts.assertEQ(t.field4.val, VAL6.val);
1249
1250 t.field5 = VAL7;
1251 Asserts.assertEQ(t.field5.val, VAL7.val);
1252
1253 // Some more value classes with different flavors of primitive fields
1254 t.field6 = null;
1255 Asserts.assertEQ(t.field6, null);
1256 t.field6 = new MyValue8((byte)i);
1257 Asserts.assertEQ(t.field6.b, (byte)i);
1258 t.field7 = null;
1259 Asserts.assertEQ(t.field7, null);
1260 t.field7 = new MyValue9((short)i);
1261 Asserts.assertEQ(t.field7.s, (short)i);
1262 t.field8 = null;
1263 Asserts.assertEQ(t.field8, null);
1264 t.field8 = new MyValue10(i);
1265 Asserts.assertEQ(t.field8.i, i);
1266 t.field9 = null;
1267 Asserts.assertEQ(t.field9, null);
1268 t.field9 = new MyValue11((float)i);
1269 Asserts.assertEQ(t.field9.f, (float)i);
1270 t.field10 = null;
1271 Asserts.assertEQ(t.field10, null);
1272 t.field10 = new MyValue12((char)i);
1273 Asserts.assertEQ(t.field10.c, (char)i);
1274 t.field11 = null;
1275 Asserts.assertEQ(t.field11, null);
1276 t.field11 = new MyValue13((i % 2) == 0);
1277 Asserts.assertEQ(t.field11.b, (i % 2) == 0);
1278
1279 // Write the fields again and check that we don't overwrite other fields
1280 t.checkFields(i);
1281 t.field6 = new MyValue8((byte)i);
1282 t.checkFields(i);
1283 t.field7 = new MyValue9((short)i);
1284 t.checkFields(i);
1285 t.field8 = new MyValue10(i);
1286 t.checkFields(i);
1287 t.field9 = new MyValue11((float)i);
1288 t.checkFields(i);
1289 t.field10 = new MyValue12((char)i);
1290 t.checkFields(i);
1291 t.field11 = new MyValue13((i % 2) == 0);
1292 t.checkFields(i);
1293
1294 testNPE1();
1295 testNPE2();
1296
1297 t.testBounds(i);
1298
1299 // Null-free, flat, atomic
1300 MyValue8 val8 = new MyValue8((byte)i);
1301 t.field12 = val8;
1302 Asserts.assertEQ(t.field12.b, (byte)i);
1303
1304 try {
1305 t.field12 = null;
1306 throw new RuntimeException("No NPE thrown");
1307 } catch (NullPointerException npe) {
1308 // Expected
1309 }
1310
1311 // Null-free, flat with both nullable and null-free fields
1312 t.field13 = new MyValue14(val8, val8);
1313 Asserts.assertEQ(t.field13.nullfree, val8);
1314 Asserts.assertEQ(t.field13.nullable, val8);
1315
1316 t.field13 = new MyValue14(val8, null);
1317 Asserts.assertEQ(t.field13.nullfree, val8);
1318 Asserts.assertEQ(t.field13.nullable, null);
1319
1320 try {
1321 t.field13 = new MyValue14(null, null);
1322 throw new RuntimeException("No NPE thrown");
1323 } catch (NullPointerException npe) {
1324 // Expected
1325 }
1326 try {
1327 t.field13 = null;
1328 throw new RuntimeException("No NPE thrown");
1329 } catch (NullPointerException npe) {
1330 // Expected
1331 }
1332
1333 // Nullable, atomic, flat with both nullable and null-free fields
1334 t.field14 = null;
1335 Asserts.assertEQ(t.field14, null);
1336
1337 t.field14 = new MyValue14(val8, val8);
1338 Asserts.assertEQ(t.field14.nullfree, val8);
1339 Asserts.assertEQ(t.field14.nullable, val8);
1340
1341 t.field14 = new MyValue14(val8, null);
1342 Asserts.assertEQ(t.field14.nullfree, val8);
1343 Asserts.assertEQ(t.field14.nullable, null);
1344
1345 try {
1346 t.field14 = new MyValue14(null, null);
1347 throw new RuntimeException("No NPE thrown");
1348 } catch (NullPointerException npe) {
1349 // Expected
1350 }
1351
1352 // Nullable, (atomic), flat with both nullable and null-free fields
1353 t.field15 = null;
1354 Asserts.assertEQ(t.field15, null);
1355
1356 t.field15 = new MyValue14(val8, val8);
1357 Asserts.assertEQ(t.field15.nullfree, val8);
1358 Asserts.assertEQ(t.field15.nullable, val8);
1359
1360 t.field15 = new MyValue14(val8, null);
1361 Asserts.assertEQ(t.field15.nullfree, val8);
1362 Asserts.assertEQ(t.field15.nullable, null);
1363
1364 try {
1365 t.field15 = new MyValue14(null, null);
1366 throw new RuntimeException("No NPE thrown");
1367 } catch (NullPointerException npe) {
1368 // Expected
1369 }
1370
1371 // Null-free, atomic, flat with both nullable and null-free fields
1372 t.field16 = new MyValue14(val8, val8);
1373 Asserts.assertEQ(t.field16.nullfree, val8);
1374 Asserts.assertEQ(t.field16.nullable, val8);
1375
1376 t.field16 = new MyValue14(val8, null);
1377 Asserts.assertEQ(t.field16.nullfree, val8);
1378 Asserts.assertEQ(t.field16.nullable, null);
1379
1380 try {
1381 t.field16 = new MyValue14(null, null);
1382 throw new RuntimeException("No NPE thrown");
1383 } catch (NullPointerException npe) {
1384 // Expected
1385 }
1386 try {
1387 t.field16 = null;
1388 throw new RuntimeException("No NPE thrown");
1389 } catch (NullPointerException npe) {
1390 // Expected
1391 }
1392
1393 MyValue15 val15 = new MyValue15(new MyClass(i));
1394 t.testWriteOopFields1(val15);
1395 if (i > (LIMIT - 50)) {
1396 // After warmup, produce some garbage to trigger GC
1397 produceGarbage();
1398 }
1399 Asserts.assertEQ(t.field17.obj.x, i);
1400 Asserts.assertEQ(t.field18.obj.x, i);
1401
1402 MyValue16 val16 = new MyValue16(new MyClass(i), new MyClass(i));
1403 t.testWriteOopFields2(val16);
1404 if (i > (LIMIT - 50)) {
1405 // After warmup, produce some garbage to trigger GC
1406 produceGarbage();
1407 }
1408 Asserts.assertEQ(t.field19.obj1.x, i);
1409 Asserts.assertEQ(t.field19.obj2.x, i);
1410
1411 MyValue17 val17 = new MyValue17(new MyClass(i), (byte)i, (byte)i);
1412 t.testWriteOopFields3(val17);
1413 if (i > (LIMIT - 50)) {
1414 // After warmup, produce some garbage to trigger GC
1415 produceGarbage();
1416 }
1417 Asserts.assertEQ(t.field20.obj.x, i);
1418 Asserts.assertEQ(t.field20.b1, (byte)i);
1419 Asserts.assertEQ(t.field20.b2, (byte)i);
1420 Asserts.assertEQ(t.field21.obj.x, i);
1421 Asserts.assertEQ(t.field21.b1, (byte)i);
1422 Asserts.assertEQ(t.field21.b2, (byte)i);
1423
1424 Asserts.assertEQ(t.emptyField1, new MyValueEmpty());
1425 Asserts.assertEQ(t.emptyField2, new MyValueEmpty());
1426
1427 // Test empty fields
1428 t.emptyField3 = new MyValueEmpty();
1429 t.emptyField4 = new MyValueEmpty();
1430 Asserts.assertEQ(t.emptyField3, new MyValueEmpty());
1431 Asserts.assertEQ(t.emptyField4, new MyValueEmpty());
1432 t.emptyField3 = null;
1433 t.emptyField4 = null;
1434 Asserts.assertEQ(t.emptyField3, null);
1435 Asserts.assertEQ(t.emptyField4, null);
1436
1437 t.testLoadingFromConstantHolder(i);
1438
1439 // Verify that no out of bounds accesses happen
1440 t.testOutOfBoundsAccess(i);
1441
1442 // Test strict fields
1443 TwoBytes twoBytes = new TwoBytes((byte)i, (byte)(i + 1));
1444 t.testStrictFields(new StrictFieldHolder(val8, val8, twoBytes, twoBytes), val8, val8, twoBytes, twoBytes);
1445 t.testStrictFields(new StrictFieldHolder(null, val8, null, twoBytes), null, val8, null, twoBytes);
1446 }
1447
1448 // Trigger deoptimization to check that re-materialization takes the null marker into account
1449 byte x = (byte)42;
1450 t.testDeopt1(x, new MyValue1(x, new MyValue2(x), new MyValue2(x)), new MyValue1(x, null, null), true);
1451 t.testDeopt2(x, new MyValue4(new MyValue3(x), new MyValue3(x)), new MyValue4(null, null), true);
1452
1453 MyValue5 val1 = new MyValue5(x, new MyValue5A(x, new MyValue5B(x, new MyValue5C(x))));
1454 MyValue5 val2 = new MyValue5(x, new MyValue5A(x, new MyValue5B(x, null)));
1455 MyValue5 val3 = new MyValue5(x, new MyValue5A(x, null));
1456 MyValue5 val4 = new MyValue5(x, null);
1457 t.testDeopt3(x, val1, val2, val3, val4, true);
1458
1459 MyValue6 val5 = new MyValue6(new MyValueEmpty());
1460 MyValue6 val6 = new MyValue6(null);
1461 MyValue6 val7 = null;
1462 t.testDeopt4(val5, val6, val7, true);
1463
1464 MyValue7 val8 = new MyValue7(new MyValue6(new MyValueEmpty()));
1465 MyValue7 val9 = new MyValue7(new MyValue6(null));
1466 MyValue7 val10 = new MyValue7(null);
1467 MyValue7 val11 = null;
1468 t.testDeopt5(val8, val9, val10, val11, false);
1469 }
1470 }