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