1 /* 2 * Copyright (c) 2014, 2018, 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 TestStableChar 26 * @summary tests on stable fields and arrays 27 * @library /test/lib / 28 * @modules java.base/jdk.internal.misc 29 * @modules java.base/jdk.internal.vm.annotation 30 * @build sun.hotspot.WhiteBox 31 * 32 * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 33 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 34 * -XX:-TieredCompilation 35 * -XX:+FoldStableValues 36 * compiler.stable.TestStableChar 37 * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 38 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 39 * -XX:-TieredCompilation 40 * -XX:-FoldStableValues 41 * compiler.stable.TestStableChar 42 * 43 * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 44 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 45 * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 46 * -XX:+FoldStableValues 47 * compiler.stable.TestStableChar 48 * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xcomp 49 * -XX:CompileOnly=::get,::get1,::get2,::get3,::get4 50 * -XX:+TieredCompilation -XX:TieredStopAtLevel=1 51 * -XX:-FoldStableValues 52 * compiler.stable.TestStableChar 53 */ 54 55 package compiler.stable; 56 57 import jdk.internal.vm.annotation.Stable; 58 59 import java.lang.reflect.InvocationTargetException; 60 61 public class TestStableChar { 62 static final boolean isStableEnabled = StableConfiguration.isStableEnabled; 63 64 public static void main(String[] args) throws Exception { 65 run(DefaultValue.class); 66 run(CharStable.class); 67 run(DefaultStaticValue.class); 68 run(StaticCharStable.class); 69 run(VolatileCharStable.class); 70 71 // @Stable arrays: Dim 1-4 72 run(CharArrayDim1.class); 73 run(CharArrayDim2.class); 74 run(CharArrayDim3.class); 75 run(CharArrayDim4.class); 76 77 // @Stable Object field: dynamic arrays 78 run(ObjectArrayLowerDim0.class); 79 run(ObjectArrayLowerDim1.class); 80 run(ObjectArrayLowerDim2.class); 81 82 // Nested @Stable fields 83 run(NestedStableField.class); 84 run(NestedStableField1.class); 85 run(NestedStableField2.class); 86 run(NestedStableField3.class); 87 88 if (failed) { 89 throw new Error("TEST FAILED"); 90 } 91 } 92 93 /* ==================================================== */ 94 95 static class DefaultValue { 96 public @Stable char v; 97 98 public static final DefaultValue c = new DefaultValue(); 99 public static char get() { return c.v; } 100 public static void test() throws Exception { 101 char val1 = get(); 102 c.v = 'a'; char val2 = get(); 103 assertEquals(val1, 0); 104 assertEquals(val2, 'a'); 105 } 106 } 107 108 /* ==================================================== */ 109 110 static class CharStable { 111 public @Stable char v; 112 113 public static final CharStable c = new CharStable(); 114 public static char get() { return c.v; } 115 public static void test() throws Exception { 116 c.v = 'a'; char val1 = get(); 117 c.v = 'b'; char val2 = get(); 118 assertEquals(val1, 'a'); 119 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 120 } 121 } 122 123 /* ==================================================== */ 124 125 static class DefaultStaticValue { 126 public static @Stable char v; 127 128 public static final DefaultStaticValue c = new DefaultStaticValue(); 129 public static char get() { return c.v; } 130 public static void test() throws Exception { 131 char val1 = get(); 132 c.v = 'a'; char val2 = get(); 133 assertEquals(val1, 0); 134 assertEquals(val2, 'a'); 135 } 136 } 137 138 /* ==================================================== */ 139 140 static class StaticCharStable { 141 public @Stable char v; 142 143 public static final StaticCharStable c = new StaticCharStable(); 144 public static char get() { return c.v; } 145 public static void test() throws Exception { 146 c.v = 'a'; char val1 = get(); 147 c.v = 'b'; char val2 = get(); 148 assertEquals(val1, 'a'); 149 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 150 } 151 } 152 153 /* ==================================================== */ 154 155 static class VolatileCharStable { 156 public @Stable volatile char v; 157 158 public static final VolatileCharStable c = new VolatileCharStable(); 159 public static char get() { return c.v; } 160 public static void test() throws Exception { 161 c.v = 'a'; char val1 = get(); 162 c.v = 'b'; char val2 = get(); 163 assertEquals(val1, 'a'); 164 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 165 } 166 } 167 168 /* ==================================================== */ 169 // @Stable array == field && all components are stable 170 171 static class CharArrayDim1 { 172 public @Stable char[] v; 173 174 public static final CharArrayDim1 c = new CharArrayDim1(); 175 public static char get() { return c.v[0]; } 176 public static char get1() { return c.v[10]; } 177 public static char[] get2() { return c.v; } 178 public static void test() throws Exception { 179 { 180 c.v = new char[1]; c.v[0] = 'a'; char val1 = get(); 181 c.v[0] = 'b'; char val2 = get(); 182 assertEquals(val1, 'a'); 183 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 184 185 c.v = new char[1]; c.v[0] = 'c'; char val3 = get(); 186 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 187 : 'c')); 188 } 189 190 { 191 c.v = new char[20]; c.v[10] = 'a'; char val1 = get1(); 192 c.v[10] = 'b'; char val2 = get1(); 193 assertEquals(val1, 'a'); 194 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 195 196 c.v = new char[20]; c.v[10] = 'c'; char val3 = get1(); 197 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 198 : 'c')); 199 } 200 201 { 202 c.v = new char[1]; char[] val1 = get2(); 203 c.v = new char[1]; char[] val2 = get2(); 204 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 205 } 206 } 207 } 208 209 /* ==================================================== */ 210 211 static class CharArrayDim2 { 212 public @Stable char[][] v; 213 214 public static final CharArrayDim2 c = new CharArrayDim2(); 215 public static char get() { return c.v[0][0]; } 216 public static char[] get1() { return c.v[0]; } 217 public static char[][] get2() { return c.v; } 218 public static void test() throws Exception { 219 { 220 c.v = new char[1][1]; c.v[0][0] = 'a'; char val1 = get(); 221 c.v[0][0] = 'b'; char val2 = get(); 222 assertEquals(val1, 'a'); 223 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 224 225 c.v = new char[1][1]; c.v[0][0] = 'c'; char val3 = get(); 226 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 227 : 'c')); 228 229 c.v[0] = new char[1]; c.v[0][0] = 'd'; char val4 = get(); 230 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 231 : 'd')); 232 } 233 234 { 235 c.v = new char[1][1]; char[] val1 = get1(); 236 c.v[0] = new char[1]; char[] val2 = get1(); 237 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 238 } 239 240 { 241 c.v = new char[1][1]; char[][] val1 = get2(); 242 c.v = new char[1][1]; char[][] val2 = get2(); 243 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 244 } 245 } 246 } 247 248 /* ==================================================== */ 249 250 static class CharArrayDim3 { 251 public @Stable char[][][] v; 252 253 public static final CharArrayDim3 c = new CharArrayDim3(); 254 public static char get() { return c.v[0][0][0]; } 255 public static char[] get1() { return c.v[0][0]; } 256 public static char[][] get2() { return c.v[0]; } 257 public static char[][][] get3() { return c.v; } 258 public static void test() throws Exception { 259 { 260 c.v = new char[1][1][1]; c.v[0][0][0] = 'a'; char val1 = get(); 261 c.v[0][0][0] = 'b'; char val2 = get(); 262 assertEquals(val1, 'a'); 263 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 264 265 c.v = new char[1][1][1]; c.v[0][0][0] = 'c'; char val3 = get(); 266 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 267 : 'c')); 268 269 c.v[0] = new char[1][1]; c.v[0][0][0] = 'd'; char val4 = get(); 270 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 271 : 'd')); 272 273 c.v[0][0] = new char[1]; c.v[0][0][0] = 'e'; char val5 = get(); 274 assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 275 : 'e')); 276 } 277 278 { 279 c.v = new char[1][1][1]; char[] val1 = get1(); 280 c.v[0][0] = new char[1]; char[] val2 = get1(); 281 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 282 } 283 284 { 285 c.v = new char[1][1][1]; char[][] val1 = get2(); 286 c.v[0] = new char[1][1]; char[][] val2 = get2(); 287 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 288 } 289 290 { 291 c.v = new char[1][1][1]; char[][][] val1 = get3(); 292 c.v = new char[1][1][1]; char[][][] val2 = get3(); 293 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 294 } 295 } 296 } 297 298 /* ==================================================== */ 299 300 static class CharArrayDim4 { 301 public @Stable char[][][][] v; 302 303 public static final CharArrayDim4 c = new CharArrayDim4(); 304 public static char get() { return c.v[0][0][0][0]; } 305 public static char[] get1() { return c.v[0][0][0]; } 306 public static char[][] get2() { return c.v[0][0]; } 307 public static char[][][] get3() { return c.v[0]; } 308 public static char[][][][] get4() { return c.v; } 309 public static void test() throws Exception { 310 { 311 c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'a'; char val1 = get(); 312 c.v[0][0][0][0] = 'b'; char val2 = get(); 313 assertEquals(val1, 'a'); 314 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 315 316 c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'c'; char val3 = get(); 317 assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 318 : 'c')); 319 320 c.v[0] = new char[1][1][1]; c.v[0][0][0][0] = 'd'; char val4 = get(); 321 assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 322 : 'd')); 323 324 c.v[0][0] = new char[1][1]; c.v[0][0][0][0] = 'e'; char val5 = get(); 325 assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 326 : 'e')); 327 328 c.v[0][0][0] = new char[1]; c.v[0][0][0][0] = 'f'; char val6 = get(); 329 assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') 330 : 'f')); 331 } 332 333 { 334 c.v = new char[1][1][1][1]; char[] val1 = get1(); 335 c.v[0][0][0] = new char[1]; char[] val2 = get1(); 336 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 337 } 338 339 { 340 c.v = new char[1][1][1][1]; char[][] val1 = get2(); 341 c.v[0][0] = new char[1][1]; char[][] val2 = get2(); 342 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 343 } 344 345 { 346 c.v = new char[1][1][1][1]; char[][][] val1 = get3(); 347 c.v[0] = new char[1][1][1]; char[][][] val2 = get3(); 348 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 349 } 350 351 { 352 c.v = new char[1][1][1][1]; char[][][][] val1 = get4(); 353 c.v = new char[1][1][1][1]; char[][][][] val2 = get4(); 354 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 355 } 356 } 357 } 358 359 /* ==================================================== */ 360 // Dynamic Dim is higher than static 361 static class ObjectArrayLowerDim0 { 362 public @Stable Object v; 363 364 public static final ObjectArrayLowerDim0 c = new ObjectArrayLowerDim0(); 365 public static char get() { return ((char[])c.v)[0]; } 366 public static char[] get1() { return (char[])c.v; } 367 368 public static void test() throws Exception { 369 { 370 c.v = new char[1]; ((char[])c.v)[0] = 'a'; char val1 = get(); 371 ((char[])c.v)[0] = 'b'; char val2 = get(); 372 373 assertEquals(val1, 'a'); 374 assertEquals(val2, 'b'); 375 } 376 377 { 378 c.v = new char[1]; char[] val1 = get1(); 379 c.v = new char[1]; char[] val2 = get1(); 380 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 381 } 382 } 383 } 384 385 /* ==================================================== */ 386 387 static class ObjectArrayLowerDim1 { 388 public @Stable Object[] v; 389 390 public static final ObjectArrayLowerDim1 c = new ObjectArrayLowerDim1(); 391 public static char get() { return ((char[][])c.v)[0][0]; } 392 public static char[] get1() { return (char[])(c.v[0]); } 393 public static Object[] get2() { return c.v; } 394 395 public static void test() throws Exception { 396 { 397 c.v = new char[1][1]; ((char[][])c.v)[0][0] = 'a'; char val1 = get(); 398 ((char[][])c.v)[0][0] = 'b'; char val2 = get(); 399 400 assertEquals(val1, 'a'); 401 assertEquals(val2, 'b'); 402 } 403 404 { 405 c.v = new char[1][1]; c.v[0] = new char[0]; char[] val1 = get1(); 406 c.v[0] = new char[0]; char[] val2 = get1(); 407 408 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 409 } 410 411 { 412 c.v = new char[0][0]; Object[] val1 = get2(); 413 c.v = new char[0][0]; Object[] val2 = get2(); 414 415 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 416 } 417 } 418 } 419 420 /* ==================================================== */ 421 422 static class ObjectArrayLowerDim2 { 423 public @Stable Object[][] v; 424 425 public static final ObjectArrayLowerDim2 c = new ObjectArrayLowerDim2(); 426 public static char get() { return ((char[][][])c.v)[0][0][0]; } 427 public static char[] get1() { return (char[])(c.v[0][0]); } 428 public static char[][] get2() { return (char[][])(c.v[0]); } 429 public static Object[][] get3() { return c.v; } 430 431 public static void test() throws Exception { 432 { 433 c.v = new char[1][1][1]; ((char[][][])c.v)[0][0][0] = 'a'; char val1 = get(); 434 ((char[][][])c.v)[0][0][0] = 'b'; char val2 = get(); 435 436 assertEquals(val1, 'a'); 437 assertEquals(val2, 'b'); 438 } 439 440 { 441 c.v = new char[1][1][1]; c.v[0][0] = new char[0]; char[] val1 = get1(); 442 c.v[0][0] = new char[0]; char[] val2 = get1(); 443 444 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 445 } 446 447 { 448 c.v = new char[1][1][1]; c.v[0] = new char[0][0]; char[][] val1 = get2(); 449 c.v[0] = new char[0][0]; char[][] val2 = get2(); 450 451 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 452 } 453 454 { 455 c.v = new char[0][0][0]; Object[][] val1 = get3(); 456 c.v = new char[0][0][0]; Object[][] val2 = get3(); 457 458 assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); 459 } 460 } 461 } 462 463 /* ==================================================== */ 464 465 static class NestedStableField { 466 static class A { 467 public @Stable char a; 468 469 } 470 public @Stable A v; 471 472 public static final NestedStableField c = new NestedStableField(); 473 public static A get() { return c.v; } 474 public static char get1() { return get().a; } 475 476 public static void test() throws Exception { 477 { 478 c.v = new A(); c.v.a = 'a'; A val1 = get(); 479 c.v.a = 'b'; A val2 = get(); 480 481 assertEquals(val1.a, 'b'); 482 assertEquals(val2.a, 'b'); 483 } 484 485 { 486 c.v = new A(); c.v.a = 'a'; char val1 = get1(); 487 c.v.a = 'b'; char val2 = get1(); 488 c.v = new A(); c.v.a = 'c'; char val3 = get1(); 489 490 assertEquals(val1, 'a'); 491 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 492 assertEquals(val3, (isStableEnabled ? 'a' : 'c')); 493 } 494 } 495 } 496 497 /* ==================================================== */ 498 499 static class NestedStableField1 { 500 static class A { 501 public @Stable char a; 502 public @Stable A next; 503 } 504 public @Stable A v; 505 506 public static final NestedStableField1 c = new NestedStableField1(); 507 public static A get() { return c.v.next.next.next.next.next.next.next; } 508 public static char get1() { return get().a; } 509 510 public static void test() throws Exception { 511 { 512 c.v = new A(); c.v.next = new A(); c.v.next.next = c.v; 513 c.v.a = 'a'; c.v.next.a = 'a'; A val1 = get(); 514 c.v.a = 'b'; c.v.next.a = 'b'; A val2 = get(); 515 516 assertEquals(val1.a, 'b'); 517 assertEquals(val2.a, 'b'); 518 } 519 520 { 521 c.v = new A(); c.v.next = c.v; 522 c.v.a = 'a'; char val1 = get1(); 523 c.v.a = 'b'; char val2 = get1(); 524 c.v = new A(); c.v.next = c.v; 525 c.v.a = 'c'; char val3 = get1(); 526 527 assertEquals(val1, 'a'); 528 assertEquals(val2, (isStableEnabled ? 'a' : 'b')); 529 assertEquals(val3, (isStableEnabled ? 'a' : 'c')); 530 } 531 } 532 } 533 /* ==================================================== */ 534 535 static class NestedStableField2 { 536 static class A { 537 public @Stable char a; 538 public @Stable A left; 539 public A right; 540 } 541 542 public @Stable A v; 543 544 public static final NestedStableField2 c = new NestedStableField2(); 545 public static char get() { return c.v.left.left.left.a; } 546 public static char get1() { return c.v.left.left.right.left.a; } 547 548 public static void test() throws Exception { 549 { 550 c.v = new A(); c.v.left = c.v.right = c.v; 551 c.v.a = 'a'; char val1 = get(); char val2 = get1(); 552 c.v.a = 'b'; char val3 = get(); char val4 = get1(); 553 554 assertEquals(val1, 'a'); 555 assertEquals(val3, (isStableEnabled ? 'a' : 'b')); 556 557 assertEquals(val2, 'a'); 558 assertEquals(val4, 'b'); 559 } 560 } 561 } 562 563 /* ==================================================== */ 564 565 static class NestedStableField3 { 566 static class A { 567 public @Stable char a; 568 public @Stable A[] left; 569 public A[] right; 570 } 571 572 public @Stable A[] v; 573 574 public static final NestedStableField3 c = new NestedStableField3(); 575 public static char get() { return c.v[0].left[1].left[0].left[1].a; } 576 public static char get1() { return c.v[1].left[0].left[1].right[0].left[1].a; } 577 578 public static void test() throws Exception { 579 { 580 A elem = new A(); 581 c.v = new A[] { elem, elem }; c.v[0].left = c.v[0].right = c.v; 582 elem.a = 'a'; char val1 = get(); char val2 = get1(); 583 elem.a = 'b'; char val3 = get(); char val4 = get1(); 584 585 assertEquals(val1, 'a'); 586 assertEquals(val3, (isStableEnabled ? 'a' : 'b')); 587 588 assertEquals(val2, 'a'); 589 assertEquals(val4, 'b'); 590 } 591 } 592 } 593 594 /* ==================================================== */ 595 // Auxiliary methods 596 static void assertEquals(int i, int j) { if (i != j) throw new AssertionError(i + " != " + j); } 597 static void assertTrue(boolean b) { if (!b) throw new AssertionError(); } 598 599 static boolean failed = false; 600 601 public static void run(Class<?> test) { 602 Throwable ex = null; 603 System.out.print(test.getName()+": "); 604 try { 605 test.getMethod("test").invoke(null); 606 } catch (InvocationTargetException e) { 607 ex = e.getCause(); 608 } catch (Throwable e) { 609 ex = e; 610 } finally { 611 if (ex == null) { 612 System.out.println("PASSED"); 613 } else { 614 failed = true; 615 System.out.println("FAILED"); 616 ex.printStackTrace(System.out); 617 } 618 } 619 } 620 }