1 /* 2 * Copyright (c) 2015, 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 26 * @run testng/othervm -Diters=10 -Xint VarHandleTestAccessChar 27 * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestAccessChar 28 * @run testng/othervm -Diters=20000 VarHandleTestAccessChar 29 * @run testng/othervm -Diters=20000 -XX:-TieredCompilation VarHandleTestAccessChar 30 */ 31 32 import org.testng.annotations.BeforeClass; 33 import org.testng.annotations.DataProvider; 34 import org.testng.annotations.Test; 35 36 import java.lang.invoke.MethodHandles; 37 import java.lang.invoke.VarHandle; 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.List; 41 42 import static org.testng.Assert.*; 43 44 public class VarHandleTestAccessChar extends VarHandleBaseTest { 45 static final char static_final_v = 'a'; 46 47 static char static_v; 48 49 final char final_v = 'a'; 50 51 char v; 52 53 VarHandle vhFinalField; 54 55 VarHandle vhField; 56 57 VarHandle vhStaticField; 58 59 VarHandle vhStaticFinalField; 60 61 VarHandle vhArray; 62 63 @BeforeClass 64 public void setup() throws Exception { 65 vhFinalField = MethodHandles.lookup().findVarHandle( 66 VarHandleTestAccessChar.class, "final_v", char.class); 67 68 vhField = MethodHandles.lookup().findVarHandle( 69 VarHandleTestAccessChar.class, "v", char.class); 70 71 vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle( 72 VarHandleTestAccessChar.class, "static_final_v", char.class); 73 74 vhStaticField = MethodHandles.lookup().findStaticVarHandle( 75 VarHandleTestAccessChar.class, "static_v", char.class); 76 77 vhArray = MethodHandles.arrayElementVarHandle(char[].class); 78 } 79 80 81 @DataProvider 82 public Object[][] varHandlesProvider() throws Exception { 83 List<VarHandle> vhs = new ArrayList<>(); 84 vhs.add(vhField); 85 vhs.add(vhStaticField); 86 vhs.add(vhArray); 87 88 return vhs.stream().map(tc -> new Object[]{tc}).toArray(Object[][]::new); 89 } 90 91 @Test(dataProvider = "varHandlesProvider") 92 public void testIsAccessModeSupported(VarHandle vh) { 93 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET)); 94 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET)); 95 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE)); 96 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE)); 97 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE)); 98 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE)); 99 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE)); 100 assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE)); 101 102 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET)); 103 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE)); 104 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)); 105 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)); 106 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)); 107 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)); 108 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)); 109 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET)); 110 111 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD)); 112 assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET)); 113 } 114 115 116 @DataProvider 117 public Object[][] typesProvider() throws Exception { 118 List<Object[]> types = new ArrayList<>(); 119 types.add(new Object[] {vhField, Arrays.asList(VarHandleTestAccessChar.class)}); 120 types.add(new Object[] {vhStaticField, Arrays.asList()}); 121 types.add(new Object[] {vhArray, Arrays.asList(char[].class, int.class)}); 122 123 return types.stream().toArray(Object[][]::new); 124 } 125 126 @Test(dataProvider = "typesProvider") 127 public void testTypes(VarHandle vh, List<Class<?>> pts) { 128 assertEquals(vh.varType(), char.class); 129 130 assertEquals(vh.coordinateTypes(), pts); 131 132 testTypes(vh); 133 } 134 135 136 @Test 137 public void testLookupInstanceToStatic() { 138 checkIAE("Lookup of static final field to instance final field", () -> { 139 MethodHandles.lookup().findStaticVarHandle( 140 VarHandleTestAccessChar.class, "final_v", char.class); 141 }); 142 143 checkIAE("Lookup of static field to instance field", () -> { 144 MethodHandles.lookup().findStaticVarHandle( 145 VarHandleTestAccessChar.class, "v", char.class); 146 }); 147 } 148 149 @Test 150 public void testLookupStaticToInstance() { 151 checkIAE("Lookup of instance final field to static final field", () -> { 152 MethodHandles.lookup().findVarHandle( 153 VarHandleTestAccessChar.class, "static_final_v", char.class); 154 }); 155 156 checkIAE("Lookup of instance field to static field", () -> { 157 vhStaticField = MethodHandles.lookup().findVarHandle( 158 VarHandleTestAccessChar.class, "static_v", char.class); 159 }); 160 } 161 162 163 @DataProvider 164 public Object[][] accessTestCaseProvider() throws Exception { 165 List<AccessTestCase<?>> cases = new ArrayList<>(); 166 167 cases.add(new VarHandleAccessTestCase("Instance final field", 168 vhFinalField, vh -> testInstanceFinalField(this, vh))); 169 cases.add(new VarHandleAccessTestCase("Instance final field unsupported", 170 vhFinalField, vh -> testInstanceFinalFieldUnsupported(this, vh), 171 false)); 172 173 cases.add(new VarHandleAccessTestCase("Static final field", 174 vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalField)); 175 cases.add(new VarHandleAccessTestCase("Static final field unsupported", 176 vhStaticFinalField, VarHandleTestAccessChar::testStaticFinalFieldUnsupported, 177 false)); 178 179 cases.add(new VarHandleAccessTestCase("Instance field", 180 vhField, vh -> testInstanceField(this, vh))); 181 cases.add(new VarHandleAccessTestCase("Instance field unsupported", 182 vhField, vh -> testInstanceFieldUnsupported(this, vh), 183 false)); 184 185 cases.add(new VarHandleAccessTestCase("Static field", 186 vhStaticField, VarHandleTestAccessChar::testStaticField)); 187 cases.add(new VarHandleAccessTestCase("Static field unsupported", 188 vhStaticField, VarHandleTestAccessChar::testStaticFieldUnsupported, 189 false)); 190 191 cases.add(new VarHandleAccessTestCase("Array", 192 vhArray, VarHandleTestAccessChar::testArray)); 193 cases.add(new VarHandleAccessTestCase("Array unsupported", 194 vhArray, VarHandleTestAccessChar::testArrayUnsupported, 195 false)); 196 cases.add(new VarHandleAccessTestCase("Array index out of bounds", 197 vhArray, VarHandleTestAccessChar::testArrayIndexOutOfBounds, 198 false)); 199 200 // Work around issue with jtreg summary reporting which truncates 201 // the String result of Object.toString to 30 characters, hence 202 // the first dummy argument 203 return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new); 204 } 205 206 @Test(dataProvider = "accessTestCaseProvider") 207 public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable { 208 T t = atc.get(); 209 int iters = atc.requiresLoop() ? ITERS : 1; 210 for (int c = 0; c < iters; c++) { 211 atc.testAccess(t); 212 } 213 } 214 215 216 217 218 static void testInstanceFinalField(VarHandleTestAccessChar recv, VarHandle vh) { 219 // Plain 220 { 221 char x = (char) vh.get(recv); 222 assertEquals(x, 'a', "get char value"); 223 } 224 225 226 // Volatile 227 { 228 char x = (char) vh.getVolatile(recv); 229 assertEquals(x, 'a', "getVolatile char value"); 230 } 231 232 // Lazy 233 { 234 char x = (char) vh.getAcquire(recv); 235 assertEquals(x, 'a', "getRelease char value"); 236 } 237 238 // Opaque 239 { 240 char x = (char) vh.getOpaque(recv); 241 assertEquals(x, 'a', "getOpaque char value"); 242 } 243 } 244 245 static void testInstanceFinalFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) { 246 checkUOE(() -> { 247 vh.set(recv, 'b'); 248 }); 249 250 checkUOE(() -> { 251 vh.setVolatile(recv, 'b'); 252 }); 253 254 checkUOE(() -> { 255 vh.setRelease(recv, 'b'); 256 }); 257 258 checkUOE(() -> { 259 vh.setOpaque(recv, 'b'); 260 }); 261 262 checkUOE(() -> { 263 boolean r = vh.compareAndSet(recv, 'a', 'b'); 264 }); 265 266 checkUOE(() -> { 267 char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b'); 268 }); 269 270 checkUOE(() -> { 271 char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b'); 272 }); 273 274 checkUOE(() -> { 275 char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b'); 276 }); 277 278 checkUOE(() -> { 279 boolean r = vh.weakCompareAndSet(recv, 'a', 'b'); 280 }); 281 282 checkUOE(() -> { 283 boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b'); 284 }); 285 286 checkUOE(() -> { 287 boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b'); 288 }); 289 290 checkUOE(() -> { 291 char o = (char) vh.getAndAdd(recv, 'a'); 292 }); 293 294 checkUOE(() -> { 295 char o = (char) vh.addAndGet(recv, 'a'); 296 }); 297 } 298 299 300 static void testStaticFinalField(VarHandle vh) { 301 // Plain 302 { 303 char x = (char) vh.get(); 304 assertEquals(x, 'a', "get char value"); 305 } 306 307 308 // Volatile 309 { 310 char x = (char) vh.getVolatile(); 311 assertEquals(x, 'a', "getVolatile char value"); 312 } 313 314 // Lazy 315 { 316 char x = (char) vh.getAcquire(); 317 assertEquals(x, 'a', "getRelease char value"); 318 } 319 320 // Opaque 321 { 322 char x = (char) vh.getOpaque(); 323 assertEquals(x, 'a', "getOpaque char value"); 324 } 325 } 326 327 static void testStaticFinalFieldUnsupported(VarHandle vh) { 328 checkUOE(() -> { 329 vh.set('b'); 330 }); 331 332 checkUOE(() -> { 333 vh.setVolatile('b'); 334 }); 335 336 checkUOE(() -> { 337 vh.setRelease('b'); 338 }); 339 340 checkUOE(() -> { 341 vh.setOpaque('b'); 342 }); 343 344 checkUOE(() -> { 345 boolean r = vh.compareAndSet('a', 'b'); 346 }); 347 348 checkUOE(() -> { 349 char r = (char) vh.compareAndExchangeVolatile('a', 'b'); 350 }); 351 352 checkUOE(() -> { 353 char r = (char) vh.compareAndExchangeAcquire('a', 'b'); 354 }); 355 356 checkUOE(() -> { 357 char r = (char) vh.compareAndExchangeRelease('a', 'b'); 358 }); 359 360 checkUOE(() -> { 361 boolean r = vh.weakCompareAndSet('a', 'b'); 362 }); 363 364 checkUOE(() -> { 365 boolean r = vh.weakCompareAndSetAcquire('a', 'b'); 366 }); 367 368 checkUOE(() -> { 369 boolean r = vh.weakCompareAndSetRelease('a', 'b'); 370 }); 371 372 checkUOE(() -> { 373 char o = (char) vh.getAndAdd('a'); 374 }); 375 376 checkUOE(() -> { 377 char o = (char) vh.addAndGet('a'); 378 }); 379 } 380 381 382 static void testInstanceField(VarHandleTestAccessChar recv, VarHandle vh) { 383 // Plain 384 { 385 vh.set(recv, 'a'); 386 char x = (char) vh.get(recv); 387 assertEquals(x, 'a', "set char value"); 388 } 389 390 391 // Volatile 392 { 393 vh.setVolatile(recv, 'b'); 394 char x = (char) vh.getVolatile(recv); 395 assertEquals(x, 'b', "setVolatile char value"); 396 } 397 398 // Lazy 399 { 400 vh.setRelease(recv, 'a'); 401 char x = (char) vh.getAcquire(recv); 402 assertEquals(x, 'a', "setRelease char value"); 403 } 404 405 // Opaque 406 { 407 vh.setOpaque(recv, 'b'); 408 char x = (char) vh.getOpaque(recv); 409 assertEquals(x, 'b', "setOpaque char value"); 410 } 411 412 413 } 414 415 static void testInstanceFieldUnsupported(VarHandleTestAccessChar recv, VarHandle vh) { 416 checkUOE(() -> { 417 boolean r = vh.compareAndSet(recv, 'a', 'b'); 418 }); 419 420 checkUOE(() -> { 421 char r = (char) vh.compareAndExchangeVolatile(recv, 'a', 'b'); 422 }); 423 424 checkUOE(() -> { 425 char r = (char) vh.compareAndExchangeAcquire(recv, 'a', 'b'); 426 }); 427 428 checkUOE(() -> { 429 char r = (char) vh.compareAndExchangeRelease(recv, 'a', 'b'); 430 }); 431 432 checkUOE(() -> { 433 boolean r = vh.weakCompareAndSet(recv, 'a', 'b'); 434 }); 435 436 checkUOE(() -> { 437 boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b'); 438 }); 439 440 checkUOE(() -> { 441 boolean r = vh.weakCompareAndSetRelease(recv, 'a', 'b'); 442 }); 443 444 checkUOE(() -> { 445 char o = (char) vh.getAndAdd(recv, 'a'); 446 }); 447 448 checkUOE(() -> { 449 char o = (char) vh.addAndGet(recv, 'a'); 450 }); 451 } 452 453 454 static void testStaticField(VarHandle vh) { 455 // Plain 456 { 457 vh.set('a'); 458 char x = (char) vh.get(); 459 assertEquals(x, 'a', "set char value"); 460 } 461 462 463 // Volatile 464 { 465 vh.setVolatile('b'); 466 char x = (char) vh.getVolatile(); 467 assertEquals(x, 'b', "setVolatile char value"); 468 } 469 470 // Lazy 471 { 472 vh.setRelease('a'); 473 char x = (char) vh.getAcquire(); 474 assertEquals(x, 'a', "setRelease char value"); 475 } 476 477 // Opaque 478 { 479 vh.setOpaque('b'); 480 char x = (char) vh.getOpaque(); 481 assertEquals(x, 'b', "setOpaque char value"); 482 } 483 484 485 } 486 487 static void testStaticFieldUnsupported(VarHandle vh) { 488 checkUOE(() -> { 489 boolean r = vh.compareAndSet('a', 'b'); 490 }); 491 492 checkUOE(() -> { 493 char r = (char) vh.compareAndExchangeVolatile('a', 'b'); 494 }); 495 496 checkUOE(() -> { 497 char r = (char) vh.compareAndExchangeAcquire('a', 'b'); 498 }); 499 500 checkUOE(() -> { 501 char r = (char) vh.compareAndExchangeRelease('a', 'b'); 502 }); 503 504 checkUOE(() -> { 505 boolean r = vh.weakCompareAndSet('a', 'b'); 506 }); 507 508 checkUOE(() -> { 509 boolean r = vh.weakCompareAndSetAcquire('a', 'b'); 510 }); 511 512 checkUOE(() -> { 513 boolean r = vh.weakCompareAndSetRelease('a', 'b'); 514 }); 515 516 checkUOE(() -> { 517 char o = (char) vh.getAndAdd('a'); 518 }); 519 520 checkUOE(() -> { 521 char o = (char) vh.addAndGet('a'); 522 }); 523 } 524 525 526 static void testArray(VarHandle vh) { 527 char[] array = new char[10]; 528 529 for (int i = 0; i < array.length; i++) { 530 // Plain 531 { 532 vh.set(array, i, 'a'); 533 char x = (char) vh.get(array, i); 534 assertEquals(x, 'a', "get char value"); 535 } 536 537 538 // Volatile 539 { 540 vh.setVolatile(array, i, 'b'); 541 char x = (char) vh.getVolatile(array, i); 542 assertEquals(x, 'b', "setVolatile char value"); 543 } 544 545 // Lazy 546 { 547 vh.setRelease(array, i, 'a'); 548 char x = (char) vh.getAcquire(array, i); 549 assertEquals(x, 'a', "setRelease char value"); 550 } 551 552 // Opaque 553 { 554 vh.setOpaque(array, i, 'b'); 555 char x = (char) vh.getOpaque(array, i); 556 assertEquals(x, 'b', "setOpaque char value"); 557 } 558 559 560 } 561 } 562 563 static void testArrayUnsupported(VarHandle vh) { 564 char[] array = new char[10]; 565 566 int i = 0; 567 checkUOE(() -> { 568 boolean r = vh.compareAndSet(array, i, 'a', 'b'); 569 }); 570 571 checkUOE(() -> { 572 char r = (char) vh.compareAndExchangeVolatile(array, i, 'a', 'b'); 573 }); 574 575 checkUOE(() -> { 576 char r = (char) vh.compareAndExchangeAcquire(array, i, 'a', 'b'); 577 }); 578 579 checkUOE(() -> { 580 char r = (char) vh.compareAndExchangeRelease(array, i, 'a', 'b'); 581 }); 582 583 checkUOE(() -> { 584 boolean r = vh.weakCompareAndSet(array, i, 'a', 'b'); 585 }); 586 587 checkUOE(() -> { 588 boolean r = vh.weakCompareAndSetAcquire(array, i, 'a', 'b'); 589 }); 590 591 checkUOE(() -> { 592 boolean r = vh.weakCompareAndSetRelease(array, i, 'a', 'b'); 593 }); 594 595 checkUOE(() -> { 596 char o = (char) vh.getAndAdd(array, i, 'a'); 597 }); 598 599 checkUOE(() -> { 600 char o = (char) vh.addAndGet(array, i, 'a'); 601 }); 602 } 603 604 static void testArrayIndexOutOfBounds(VarHandle vh) throws Throwable { 605 char[] array = new char[10]; 606 607 for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) { 608 final int ci = i; 609 610 checkIOOBE(() -> { 611 char x = (char) vh.get(array, ci); 612 }); 613 614 checkIOOBE(() -> { 615 vh.set(array, ci, 'a'); 616 }); 617 618 checkIOOBE(() -> { 619 char x = (char) vh.getVolatile(array, ci); 620 }); 621 622 checkIOOBE(() -> { 623 vh.setVolatile(array, ci, 'a'); 624 }); 625 626 checkIOOBE(() -> { 627 char x = (char) vh.getAcquire(array, ci); 628 }); 629 630 checkIOOBE(() -> { 631 vh.setRelease(array, ci, 'a'); 632 }); 633 634 checkIOOBE(() -> { 635 char x = (char) vh.getOpaque(array, ci); 636 }); 637 638 checkIOOBE(() -> { 639 vh.setOpaque(array, ci, 'a'); 640 }); 641 642 643 } 644 } 645 } 646