1 /* 2 * Copyright (c) 2024, 2024, 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 * @test NullableFlatFieldTest 26 * @requires vm.debug == true 27 * @library /test/lib 28 * @modules java.base/jdk.internal.vm.annotation 29 * @enablePreview 30 * @run main/othervm -Xint -XX:+EnableNullableFieldFlattening -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlineLayout NullableFlatFieldTest 31 */ 32 33 import jdk.internal.vm.annotation.ImplicitlyConstructible; 34 import jdk.internal.vm.annotation.LooselyConsistentValue; 35 import jdk.internal.vm.annotation.NullRestricted; 36 37 import jdk.test.lib.Asserts; 38 39 public class NullableFlatFieldTest { 40 41 @ImplicitlyConstructible 42 @LooselyConsistentValue 43 static value class Value0 { 44 long l; 45 int i; 46 short s; 47 byte b; 48 49 Value0() { 50 l = 0; 51 i = 0; 52 s = 0; 53 b = 0; 54 } 55 56 Value0(long l0, int i0, short s0, byte b0) { 57 l = l0; 58 i = i0; 59 s = s0; 60 b = b0; 61 } 62 } 63 64 static class Container0 { 65 Value0 val; 66 long l; 67 int i; 68 } 69 70 // Container0 had a external null marker located just between two Java fields, 71 // and test0 checks that updating the null marker doesn't corrupt 72 // the surrounding fields and vice-versa. 73 static void test0() { 74 Container0 c = new Container0(); 75 Asserts.assertNull(c.val); 76 Asserts.assertEquals(c.l, 0L); 77 Asserts.assertEquals(c.i, 0); 78 c.l = -1L; 79 c.i = -1; 80 Asserts.assertNull(c.val); 81 Value0 v = new Value0(-1L, -1, (short)-1, (byte)-1); 82 c.val = v; 83 Asserts.assertEquals(c.l, -1L); 84 Asserts.assertEquals(c.i, -1); 85 Value0 vr = c.val; 86 Asserts.assertEquals(vr.l, -1L); 87 Asserts.assertEquals(vr.i, -1); 88 Asserts.assertEquals(vr.s, (short)-1); 89 Asserts.assertEquals(vr.b, (byte)-1); 90 c.val = null; 91 Asserts.assertEquals(c.l, -1L); 92 Asserts.assertEquals(c.i, -1); 93 } 94 95 @ImplicitlyConstructible 96 @LooselyConsistentValue 97 static value class Value1a { 98 long l; 99 short s; 100 byte b; 101 102 Value1a() { 103 l = 0; 104 s = 0; 105 b = 0; 106 } 107 108 Value1a(long l0, short s0, byte b0) { 109 l = l0; 110 s = s0; 111 b = b0; 112 } 113 } 114 115 @ImplicitlyConstructible 116 @LooselyConsistentValue 117 static value class Value1b { 118 @NullRestricted 119 Value1a vala; 120 long l; 121 int i; 122 123 Value1b() { 124 vala = new Value1a(); 125 l = 1L; 126 i = 1; 127 } 128 129 Value1b(Value1a v0, long l0, int i0) { 130 vala = v0; 131 l = l0; 132 i = i0; 133 } 134 } 135 136 static class Container1 { 137 Value1b valb; 138 } 139 140 // Container1 has a nullable flat field with an internal null marker, 141 // test1 checks that updating the null marker doesn't corrupt the 142 // flat field's values 143 static void test1() { 144 Container1 c = new Container1(); 145 Asserts.assertNull(c.valb); 146 Value1a va = new Value1a(-1L, (short)-1, (byte)-1); 147 Asserts.assertEquals(va.l, -1L); 148 Asserts.assertEquals(va.s, (short)-1); 149 Asserts.assertEquals(va.b, (byte)-1); 150 Value1b vb = new Value1b(va, -1L, -1); 151 Asserts.assertNotNull(vb.vala); 152 Asserts.assertEquals(vb.vala.l, -1L); 153 Asserts.assertEquals(vb.vala.s, (short)-1); 154 Asserts.assertEquals(vb.vala.b, (byte)-1); 155 c.valb = vb; 156 Asserts.assertNotNull(c.valb); 157 Asserts.assertEquals(c.valb, vb); 158 Asserts.assertEquals(c.valb.vala, va); 159 Asserts.assertEquals(c.valb.l, -1L); 160 Asserts.assertEquals(c.valb.i, -1); 161 c.valb = null; 162 Asserts.assertNull(c.valb); 163 } 164 165 @ImplicitlyConstructible 166 @LooselyConsistentValue 167 static value class Value2a { 168 long l; 169 int i; 170 byte b; 171 Value2a() { 172 l = 0; 173 i = 0; 174 b = 0; 175 } 176 Value2a(long l0, int i0, byte b0) { 177 l = l0; 178 i = i0; 179 b = b0; 180 } 181 } 182 183 @ImplicitlyConstructible 184 @LooselyConsistentValue 185 static value class Value2b { 186 long l; 187 Value2b() { 188 l = 0; 189 } 190 Value2b(long l0) { 191 l = l0; 192 } 193 } 194 195 static class Container2 { 196 Value2a vala; 197 Value2b valb0; 198 Value2b valb1; 199 int i; 200 } 201 202 // Container2 has 3 contiguous null markers, 203 // test2 checks that updating a null marker doesn't affect the other markers 204 public static void test2() { 205 Container2 c = new Container2(); 206 Asserts.assertNull(c.vala); 207 Asserts.assertNull(c.valb0); 208 Asserts.assertNull(c.valb1); 209 Value2a va = new Value2a(-1L, -1, (byte)-1); 210 c.vala = va; 211 Asserts.assertNotNull(c.vala); 212 Asserts.assertNull(c.valb0); 213 Asserts.assertNull(c.valb1); 214 c.vala = null; 215 Asserts.assertNull(c.vala); 216 Asserts.assertNull(c.valb0); 217 Asserts.assertNull(c.valb1); 218 Value2b vb = new Value2b(-1L); 219 c.valb0 = vb; 220 Asserts.assertNull(c.vala); 221 Asserts.assertNotNull(c.valb0); 222 Asserts.assertNull(c.valb1); 223 c.valb0 = null; 224 Asserts.assertNull(c.vala); 225 Asserts.assertNull(c.valb0); 226 Asserts.assertNull(c.valb1); 227 c.valb1 = vb; 228 Asserts.assertNull(c.vala); 229 Asserts.assertNull(c.valb0); 230 Asserts.assertNotNull(c.valb1); 231 c.valb1 = null; 232 Asserts.assertNull(c.vala); 233 Asserts.assertNull(c.valb0); 234 Asserts.assertNull(c.valb1); 235 c.vala = va; 236 c.valb0 = vb; 237 c.valb1 = vb; 238 Asserts.assertNotNull(c.vala); 239 Asserts.assertNotNull(c.valb0); 240 Asserts.assertNotNull(c.valb1); 241 c.vala = null; 242 Asserts.assertNull(c.vala); 243 Asserts.assertNotNull(c.valb0); 244 Asserts.assertNotNull(c.valb1); 245 c.vala = va; 246 Asserts.assertNotNull(c.vala); 247 Asserts.assertNotNull(c.valb0); 248 Asserts.assertNotNull(c.valb1); 249 c.valb0 = null; 250 Asserts.assertNotNull(c.vala); 251 Asserts.assertNull(c.valb0); 252 Asserts.assertNotNull(c.valb1); 253 c.valb0 = vb; 254 Asserts.assertNotNull(c.vala); 255 Asserts.assertNotNull(c.valb0); 256 Asserts.assertNotNull(c.valb1); 257 c.valb1 = null; 258 Asserts.assertNotNull(c.vala); 259 Asserts.assertNotNull(c.valb0); 260 Asserts.assertNull(c.valb1); 261 c.valb1 = vb; 262 Asserts.assertNotNull(c.vala); 263 Asserts.assertNotNull(c.valb0); 264 Asserts.assertNotNull(c.valb1); 265 } 266 267 @ImplicitlyConstructible 268 @LooselyConsistentValue 269 static value class Value3 { 270 int i = 0; 271 } 272 273 static class Container3 { 274 Value3 val; 275 } 276 277 static Container3 getNullContainer3() { 278 return null; 279 } 280 281 public static void test3() { 282 NullPointerException npe = null; 283 Container3 c = getNullContainer3(); 284 try { 285 Value3 v = c.val; 286 } catch(NullPointerException e) { 287 npe = e; 288 } 289 Asserts.assertNotNull(npe); 290 } 291 292 public static void main(String[] args) { 293 // All tests are run twice to exercise both the unresolved bytecodes and the rewritten ones 294 for (int i = 0; i < 2; i++) { 295 System.out.println("Pass " + i); 296 test0(); 297 test1(); 298 test2(); 299 test3(); 300 } 301 } 302 } 303