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