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