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