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