1 /* 2 * Copyright (c) 2023, 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 value class MyValue1 { 25 int x = 42; 26 27 void verify() { 28 if (x != 42) { 29 throw new RuntimeException("Verification failed"); 30 } 31 } 32 } 33 34 value class MyValue2 { 35 int x = 42; 36 37 void verify() { 38 if (x != 42) { 39 throw new RuntimeException("Verification failed"); 40 } 41 } 42 } 43 44 value class MyValue3 { 45 int x = 42; 46 47 void verify() { 48 if (x != 42) { 49 throw new RuntimeException("Verification failed"); 50 } 51 } 52 } 53 54 value class MyValue4 { 55 int x = 42; 56 57 public void verify() { 58 if (x != 42) { 59 throw new RuntimeException("Verification failed"); 60 } 61 } 62 63 static MyValue4 make() { 64 return new MyValue4(); 65 } 66 } 67 68 interface Verifiable { 69 public void verify(); 70 } 71 72 value class MyValue5 implements Verifiable { 73 int x = 42; 74 75 @Override 76 public void verify() { 77 if (x != 42) { 78 throw new RuntimeException("Verification failed"); 79 } 80 } 81 82 static MyValue5 make() { 83 return new MyValue5(); 84 } 85 } 86 87 value class MyValue6 implements Verifiable { 88 int x = 42; 89 90 @Override 91 public void verify() { 92 if (x != 42) { 93 throw new RuntimeException("Verification failed"); 94 } 95 } 96 97 static MyValue6 make() { 98 return new MyValue6(); 99 } 100 } 101 102 value class MyValue7 { 103 int x = 42; 104 105 void verify() { 106 if (x != 42) { 107 throw new RuntimeException("Verification failed"); 108 } 109 } 110 } 111 112 class A { 113 public MyValue1 method(MyValue1 arg) { 114 arg.verify(); 115 return arg; 116 } 117 } 118 119 class B extends A { 120 @Override 121 public MyValue1 method(MyValue1 arg) { 122 arg.verify(); 123 return arg; 124 } 125 } 126 127 class C extends B { 128 @Override 129 public MyValue1 method(MyValue1 arg) { 130 arg.verify(); 131 return arg; 132 } 133 } 134 135 interface I1 { 136 public MyValue2 method(MyValue2 arg); 137 } 138 139 interface I2 extends I1 { 140 public MyValue2 method(MyValue2 arg); 141 } 142 143 interface I3 { 144 public MyValue2 method(MyValue2 arg); 145 } 146 147 interface I4 extends I3 { 148 public MyValue2 method(MyValue2 arg); 149 } 150 151 152 class D implements I2 { 153 @Override 154 public MyValue2 method(MyValue2 arg) { 155 arg.verify(); 156 return arg; 157 } 158 } 159 160 class E implements I4 { 161 @Override 162 public MyValue2 method(MyValue2 arg) { 163 arg.verify(); 164 return arg; 165 } 166 } 167 168 169 class F implements I2, I4 { 170 @Override 171 public MyValue2 method(MyValue2 arg) { 172 arg.verify(); 173 return arg; 174 } 175 } 176 177 class G implements I2, I4 { 178 @Override 179 public MyValue2 method(MyValue2 arg) { 180 arg.verify(); 181 return arg; 182 } 183 } 184 185 interface I5 { 186 public MyValue3 method(MyValue3 arg); 187 } 188 189 class H implements I5 { 190 @Override 191 public MyValue3 method(MyValue3 arg) { 192 arg.verify(); 193 return arg; 194 } 195 } 196 197 class J { 198 public MyValue3 method(MyValue3 arg) { 199 arg.verify(); 200 return arg; 201 } 202 } 203 204 class K extends J { 205 @Override 206 public MyValue3 method(MyValue3 arg) { 207 arg.verify(); 208 return arg; 209 } 210 } 211 212 class L extends K implements I5 { 213 @Override 214 public MyValue3 method(MyValue3 arg) { 215 arg.verify(); 216 return arg; 217 } 218 } 219 220 class M { 221 int val = 0; 222 223 public MyValue4 method(boolean warmup) { 224 if (warmup) { 225 return null; 226 } else { 227 MyValue4 res = MyValue4.make(); 228 // Do something here to "corrupt" registers 229 for (int i = 0; i < 10; ++i) { 230 val++; 231 } 232 return res; 233 } 234 } 235 } 236 237 class N { 238 public MyValue5 method(boolean warmup) { 239 if (warmup) { 240 return null; 241 } else { 242 return MyValue5.make(); 243 } 244 } 245 } 246 247 class O { 248 public MyValue6 method(boolean warmup) { 249 if (warmup) { 250 return null; 251 } else { 252 return MyValue6.make(); 253 } 254 } 255 } 256 257 interface I6 { 258 default MyValue7 method(MyValue7 arg) { 259 return null; 260 } 261 } 262 263 class P implements I6 { 264 @Override 265 public MyValue7 method(MyValue7 arg) { 266 arg.verify(); 267 return arg; 268 } 269 } 270 271 class Q { 272 MyValue7 method(MyValue7 arg) { 273 arg.verify(); 274 return arg; 275 } 276 } 277 278 class R extends Q { 279 @Override 280 MyValue7 method(MyValue7 arg) { 281 arg.verify(); 282 return arg; 283 } 284 } 285 286 class S extends R implements I6 { 287 @Override 288 public MyValue7 method(MyValue7 arg) { 289 arg.verify(); 290 return arg; 291 } 292 } 293 294 class TestMismatchHandlingHelper { 295 // * = has preload attribute for MyValue* 296 297 // With C <: B* <: A 298 public static void test1(A a1, A a2, A a3, A a4, A a5, B b1, B b2, C c) { 299 // Non-scalarized virtual call site, mismatching on B 300 a1.method(new MyValue1()).verify(); 301 a2.method(new MyValue1()).verify(); 302 a3.method(new MyValue1()).verify(); 303 a4.method(new MyValue1()).verify(); 304 a5.method(new MyValue1()).verify(); 305 // Scalarized virtual call sites, mismatching on C 306 b1.method(new MyValue1()).verify(); 307 b2.method(new MyValue1()).verify(); 308 c.method(new MyValue1()).verify(); 309 } 310 311 // D <: I2 <: I1 312 // E* <: I4* <: I3* 313 // Loaded later, combine both hierachies and introduce a mismatch: 314 // F <: I2, I4* 315 // G* <: I2, I4* 316 public static void test2(I1 i11, I1 i12, I1 i13, I1 i14, I1 i15, I1 i16, I2 i21, I2 i22, I2 i23, I2 i24, I2 i25, I2 i26, I3 i31, I3 i32, I3 i33, I3 i34, I3 i35, I3 i36, I4 i41, I4 i42, I4 i43, I4 i44, I4 i45, I4 i46, D d, E e) { 317 // Non-scalarized virtual call sites, mismatching on E 318 i11.method(new MyValue2()).verify(); 319 i12.method(new MyValue2()).verify(); 320 i13.method(new MyValue2()).verify(); 321 i14.method(new MyValue2()).verify(); 322 i15.method(new MyValue2()).verify(); 323 i16.method(new MyValue2()).verify(); 324 i21.method(new MyValue2()).verify(); 325 i22.method(new MyValue2()).verify(); 326 i23.method(new MyValue2()).verify(); 327 i24.method(new MyValue2()).verify(); 328 i25.method(new MyValue2()).verify(); 329 i26.method(new MyValue2()).verify(); 330 d.method(new MyValue2()).verify(); 331 // Scalarized virtual call sites, mismatching on D 332 i31.method(new MyValue2()).verify(); 333 i32.method(new MyValue2()).verify(); 334 i33.method(new MyValue2()).verify(); 335 i34.method(new MyValue2()).verify(); 336 i35.method(new MyValue2()).verify(); 337 i36.method(new MyValue2()).verify(); 338 i41.method(new MyValue2()).verify(); 339 i42.method(new MyValue2()).verify(); 340 i43.method(new MyValue2()).verify(); 341 i44.method(new MyValue2()).verify(); 342 i45.method(new MyValue2()).verify(); 343 i46.method(new MyValue2()).verify(); 344 e.method(new MyValue2()).verify(); 345 } 346 347 // H <: I5 348 // K* <: J* 349 // Loaded later, combines both hierachies and introduces a mismatch: 350 // L* <: K*, I5 351 public static void test3(I5 i51, I5 i52, I5 i53, J j1, J j2, J j3, J j4, J j5, H h, K k) { 352 // Non-scalarized virtual call sites, mismatching on L 353 i51.method(new MyValue3()).verify(); 354 i52.method(new MyValue3()).verify(); 355 i53.method(new MyValue3()).verify(); 356 h.method(new MyValue3()).verify(); 357 // Scalarized virtual call sites 358 j1.method(new MyValue3()).verify(); 359 j2.method(new MyValue3()).verify(); 360 j3.method(new MyValue3()).verify(); 361 j4.method(new MyValue3()).verify(); 362 j5.method(new MyValue3()).verify(); 363 k.method(new MyValue3()).verify(); 364 } 365 366 // Test that a C1 compiled method returns in scalarized form if the method holder class M 367 // is loaded but the value class return type is not due to a missing preload attribute. 368 public static void test4(M m, boolean warmup) { 369 if (warmup) { 370 m.method(warmup); 371 } else { 372 if (m.method(warmup).x != 42) { 373 throw new RuntimeException("Verification failed"); 374 } 375 } 376 } 377 378 // Test that C1 correctly handles scalarized returns at calls if the method holder class N 379 // is loaded but the value class return type is not due to a missing preload attribute. 380 public static void test5(N n, boolean warmup) { 381 Verifiable res = n.method(warmup); 382 if (!warmup) { 383 res.verify(); 384 } 385 } 386 387 // Test direct calls 388 public static void test6(F f, G g, L l) { 389 f.method(new MyValue2()); 390 g.method(new MyValue2()); 391 l.method(new MyValue3()); 392 } 393 394 // Test scalarized return from C2 compiled callee to C2 compiled caller with an unloaded 395 // return type at caller compile time due to a missing preload attribute. 396 public static Verifiable test7(O o, boolean warmup) { 397 return o.method(warmup); 398 } 399 400 public static void test7TriggerCalleeCompilation(O o) { 401 o.method(true); 402 o.method(false).verify(); 403 } 404 405 // Same as test3 but with default method in interface and package private methods 406 // P <: I6 407 // R* <: Q* 408 // Loaded later, combines both hierachies and introduces a mismatch: 409 // S* <: R*, I6 410 public static void test8(I6 i61, I6 i62, I6 i63, Q q1, Q q2, Q q3, Q q4, Q q5, P p, R r) { 411 // Non-scalarized virtual call sites, mismatching on S 412 i61.method(new MyValue7()).verify(); 413 i62.method(new MyValue7()).verify(); 414 i63.method(new MyValue7()).verify(); 415 p.method(new MyValue7()).verify(); 416 // Scalarized virtual call sites 417 q1.method(new MyValue7()).verify(); 418 q2.method(new MyValue7()).verify(); 419 q3.method(new MyValue7()).verify(); 420 q4.method(new MyValue7()).verify(); 421 q5.method(new MyValue7()).verify(); 422 r.method(new MyValue7()).verify(); 423 } 424 }