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