1 /* 2 * Copyright (c) 2020, 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 package compiler.valhalla.inlinetypes; 25 26 import jdk.test.lib.Asserts; 27 28 import jdk.internal.value.ValueClass; 29 import jdk.internal.vm.annotation.ImplicitlyConstructible; 30 import jdk.internal.vm.annotation.LooselyConsistentValue; 31 import jdk.internal.vm.annotation.NullRestricted; 32 33 34 /** 35 * @test 36 * @bug 8253416 37 * @summary Test nestmate access to flattened field if nest-host is not loaded. 38 * @library /test/lib 39 * @enablePreview 40 * @modules java.base/jdk.internal.value 41 * java.base/jdk.internal.vm.annotation 42 * @run main/othervm -Xcomp 43 * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.Test*::<init> 44 * compiler.valhalla.inlinetypes.TestNestmateAccess 45 * @run main/othervm -Xcomp -XX:TieredStopAtLevel=1 46 * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.Test*::<init> 47 * compiler.valhalla.inlinetypes.TestNestmateAccess 48 * @run main/othervm compiler.valhalla.inlinetypes.TestNestmateAccess 49 */ 50 51 interface MyInterface { 52 int hash(); 53 } 54 55 @ImplicitlyConstructible 56 @LooselyConsistentValue 57 value class MyValue implements MyInterface { 58 int x = 42; 59 int y = 43; 60 61 @Override 62 public int hash() { return x + y; } 63 } 64 65 // Test load from flattened field in nestmate when nest-host is not loaded. 66 class Test1 { 67 @NullRestricted 68 private MyValue vt; 69 70 public Test1(final MyValue vt) { 71 this.vt = vt; 72 } 73 74 public MyInterface test() { 75 return new MyInterface() { 76 // The vt field load does not link. 77 private int x = (Test1.this).vt.hash(); 78 79 @Override 80 public int hash() { return x; } 81 }; 82 } 83 } 84 85 // Same as Test1 but outer class is a value class 86 @ImplicitlyConstructible 87 @LooselyConsistentValue 88 value class Test2 { 89 @NullRestricted 90 private MyValue vt; 91 92 public Test2(final MyValue vt) { 93 this.vt = vt; 94 } 95 96 public MyInterface test() { 97 return new MyInterface() { 98 // Delayed flattened load of Test2.this. 99 // The vt field load does not link. 100 private int x = (Test2.this).vt.hash(); 101 102 @Override 103 public int hash() { return x; } 104 }; 105 } 106 } 107 108 // Test store to flattened field in nestmate when nest-host is not loaded. 109 class Test3 { 110 @NullRestricted 111 private MyValue vt; 112 113 public MyInterface test(MyValue init) { 114 return new MyInterface() { 115 // Store to the vt field does not link. 116 private MyValue tmp = (vt = init); 117 118 @Override 119 public int hash() { return tmp.hash() + vt.hash(); } 120 }; 121 } 122 } 123 124 // Same as Test1 but with static field 125 class Test4 { 126 @NullRestricted 127 private static MyValue vt; 128 129 public Test4(final MyValue vt) { 130 this.vt = vt; 131 } 132 133 public MyInterface test() { 134 return new MyInterface() { 135 // The vt field load does not link. 136 private int x = (Test4.this).vt.hash(); 137 138 @Override 139 public int hash() { return x; } 140 }; 141 } 142 } 143 144 // Same as Test2 but with static field 145 @ImplicitlyConstructible 146 @LooselyConsistentValue 147 value class Test5 { 148 @NullRestricted 149 private static MyValue vt; 150 151 public Test5(final MyValue vt) { 152 this.vt = vt; 153 } 154 155 public MyInterface test() { 156 return new MyInterface() { 157 // Delayed flattened load of Test5.this. 158 // The vt field load does not link. 159 private int x = (Test5.this).vt.hash(); 160 161 @Override 162 public int hash() { return x; } 163 }; 164 } 165 } 166 167 // Same as Test3 but with static field 168 class Test6 { 169 @NullRestricted 170 private static MyValue vt; 171 172 public MyInterface test(MyValue init) { 173 return new MyInterface() { 174 // Store to the vt field does not link. 175 private MyValue tmp = (vt = init); 176 177 @Override 178 public int hash() { return tmp.hash() + vt.hash(); } 179 }; 180 } 181 } 182 183 // Same as Test6 but outer class is a value class 184 @ImplicitlyConstructible 185 @LooselyConsistentValue 186 value class Test7 { 187 @NullRestricted 188 private static MyValue vt; 189 190 public MyInterface test(MyValue init) { 191 return new MyInterface() { 192 // Store to the vt field does not link. 193 private MyValue tmp = (vt = init); 194 195 @Override 196 public int hash() { return tmp.hash() + vt.hash(); } 197 }; 198 } 199 } 200 201 public class TestNestmateAccess { 202 203 public static void main(String[] args) { 204 Test1 t1 = new Test1(new MyValue()); 205 int res = t1.test().hash(); 206 Asserts.assertEQ(res, 85); 207 208 Test2 t2 = new Test2(new MyValue()); 209 res = t2.test().hash(); 210 Asserts.assertEQ(res, 85); 211 212 Test3 t3 = new Test3(); 213 res = t3.test(new MyValue()).hash(); 214 Asserts.assertEQ(res, 170); 215 216 Test4 t4 = new Test4(new MyValue()); 217 res = t4.test().hash(); 218 Asserts.assertEQ(res, 85); 219 220 Test5 t5 = new Test5(new MyValue()); 221 res = t5.test().hash(); 222 Asserts.assertEQ(res, 85); 223 224 Test6 t6 = new Test6(); 225 res = t6.test(new MyValue()).hash(); 226 Asserts.assertEQ(res, 170); 227 228 Test7 t7 = new Test7(); 229 res = t7.test(new MyValue()).hash(); 230 Asserts.assertEQ(res, 170); 231 } 232 }