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 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAs$Type$
  27  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAs$Type$
  28  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAs$Type$
  29  */
  30 
  31 import org.testng.annotations.DataProvider;
  32 import org.testng.annotations.Test;
  33 
  34 import java.lang.invoke.MethodHandles;
  35 import java.lang.invoke.VarHandle;
  36 import java.nio.ByteBuffer;
  37 import java.nio.ByteOrder;
  38 import java.util.ArrayList;
  39 import java.util.Arrays;
  40 import java.util.EnumSet;
  41 import java.util.List;
  42 
  43 import static org.testng.Assert.*;
  44 
  45 public class VarHandleTestByteArrayAs$Type$ extends VarHandleBaseByteArrayTest {
  46     static final int SIZE = $BoxType$.BYTES;
  47 
  48     static final $type$ VALUE_1 = $value1$;
  49 
  50     static final $type$ VALUE_2 = $value2$;
  51 
  52     static final $type$ VALUE_3 = $value3$;
  53 
  54 
  55     @Override
  56     public void setupVarHandleSources() {
  57         // Combinations of VarHandle byte[] or ByteBuffer
  58         vhss = new ArrayList<>();
  59         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
  60             VarHandleSource aeh = new VarHandleSource(
  61                     MethodHandles.byteArrayViewVarHandle($type$[].class,
  62                                                          endianess == MemoryMode.BIG_ENDIAN),
  63                     endianess, MemoryMode.READ_WRITE);
  64             vhss.add(aeh);
  65 
  66             VarHandleSource bbh = new VarHandleSource(
  67                     MethodHandles.byteBufferViewVarHandle($type$[].class,
  68                                                           endianess == MemoryMode.BIG_ENDIAN),
  69                     endianess, MemoryMode.READ_WRITE);
  70             vhss.add(bbh);
  71         }
  72     }
  73 
  74 
  75     @Test(dataProvider = "varHandlesProvider")
  76     public void testIsAccessModeSupported(VarHandleSource vhs) {
  77         VarHandle vh = vhs.s;
  78 
  79         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
  80         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
  81 
  82         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
  83         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
  84         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
  85         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
  86         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
  87         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
  88 
  89 #if[CAS]
  90         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
  91         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE));
  92         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
  93         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
  94         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
  95         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
  96         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
  97         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
  98 #else[CAS]
  99         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
 100         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE));
 101         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
 102         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
 103         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
 104         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
 105         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
 106         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 107 #end[CAS]
 108 
 109 #if[AtomicAdd]
 110         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
 111         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
 112 #else[AtomicAdd]
 113         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
 114         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.ADD_AND_GET));
 115 #end[AtomicAdd]
 116     }
 117 
 118     @Test(dataProvider = "typesProvider")
 119     public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
 120         assertEquals(vh.varType(), $type$.class);
 121 
 122         assertEquals(vh.coordinateTypes(), pts);
 123 
 124         testTypes(vh);
 125     }
 126 
 127 
 128     @DataProvider
 129     public Object[][] accessTestCaseProvider() throws Exception {
 130         List<AccessTestCase<?>> cases = new ArrayList<>();
 131 
 132         for (ByteArrayViewSource<?> bav : bavss) {
 133             for (VarHandleSource vh : vhss) {
 134                 if (vh.matches(bav)) {
 135                     if (bav instanceof ByteArraySource) {
 136                         ByteArraySource bas = (ByteArraySource) bav;
 137 
 138                         cases.add(new VarHandleSourceAccessTestCase(
 139                                 "read write", bav, vh, h -> testArrayReadWrite(bas, h),
 140                                 true));
 141                         cases.add(new VarHandleSourceAccessTestCase(
 142                                 "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
 143                                 false));
 144                         cases.add(new VarHandleSourceAccessTestCase(
 145                                 "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
 146                                 false));
 147                         cases.add(new VarHandleSourceAccessTestCase(
 148                                 "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
 149                                 false));
 150                     }
 151                     else {
 152                         ByteBufferSource bbs = (ByteBufferSource) bav;
 153 
 154                         if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
 155                             cases.add(new VarHandleSourceAccessTestCase(
 156                                     "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
 157                                     true));
 158                         }
 159                         else {
 160                             cases.add(new VarHandleSourceAccessTestCase(
 161                                     "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
 162                                     true));
 163                         }
 164 
 165                         cases.add(new VarHandleSourceAccessTestCase(
 166                                 "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
 167                                 false));
 168                         cases.add(new VarHandleSourceAccessTestCase(
 169                                 "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
 170                                 false));
 171                         cases.add(new VarHandleSourceAccessTestCase(
 172                                 "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
 173                                 false));
 174                     }
 175                 }
 176             }
 177         }
 178 
 179         // Work around issue with jtreg summary reporting which truncates
 180         // the String result of Object.toString to 30 characters, hence
 181         // the first dummy argument
 182         return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
 183     }
 184 
 185     @Test(dataProvider = "accessTestCaseProvider")
 186     public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
 187         T t = atc.get();
 188         int iters = atc.requiresLoop() ? ITERS : 1;
 189         for (int c = 0; c < iters; c++) {
 190             atc.testAccess(t);
 191         }
 192     }
 193 
 194 
 195     static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
 196         VarHandle vh = vhs.s;
 197         byte[] array = bs.s;
 198         int ci = 1;
 199 
 200 #if[!CAS]
 201         checkUOE(() -> {
 202             boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 203         });
 204 
 205         checkUOE(() -> {
 206             $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
 207         });
 208 
 209         checkUOE(() -> {
 210             $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 211         });
 212 
 213         checkUOE(() -> {
 214             $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 215         });
 216 
 217         checkUOE(() -> {
 218             boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 219         });
 220 
 221         checkUOE(() -> {
 222             boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 223         });
 224 
 225         checkUOE(() -> {
 226             boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 227         });
 228 
 229         checkUOE(() -> {
 230             $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
 231         });
 232 #end[CAS]
 233 
 234 #if[!AtomicAdd]
 235         checkUOE(() -> {
 236             $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
 237         });
 238 
 239         checkUOE(() -> {
 240             $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
 241         });
 242 #end[AtomicAdd]
 243     }
 244 
 245     static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
 246         VarHandle vh = vhs.s;
 247         ByteBuffer array = bs.s;
 248         int ci = 0;
 249         boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
 250 
 251         if (readOnly) {
 252             checkROBE(() -> {
 253                 vh.set(array, ci, VALUE_1);
 254             });
 255         }
 256 
 257         if (readOnly) {
 258             checkROBE(() -> {
 259                 vh.setVolatile(array, ci, VALUE_1);
 260             });
 261 
 262             checkROBE(() -> {
 263                 vh.setRelease(array, ci, VALUE_1);
 264             });
 265 
 266             checkROBE(() -> {
 267                 vh.setOpaque(array, ci, VALUE_1);
 268             });
 269 #if[CAS]
 270 
 271             checkROBE(() -> {
 272                 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 273             });
 274 
 275             checkROBE(() -> {
 276                 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
 277             });
 278 
 279             checkROBE(() -> {
 280                 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 281             });
 282 
 283             checkROBE(() -> {
 284                 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 285             });
 286 
 287             checkROBE(() -> {
 288                 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 289             });
 290 
 291             checkROBE(() -> {
 292                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 293             });
 294 
 295             checkROBE(() -> {
 296                 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 297             });
 298 
 299             checkROBE(() -> {
 300                 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
 301             });
 302             checkUOE(() -> {
 303                 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 304             });
 305 #else[CAS]
 306             checkUOE(() -> {
 307                 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
 308             });
 309 
 310             checkUOE(() -> {
 311                 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 312             });
 313 
 314             checkUOE(() -> {
 315                 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 316             });
 317 
 318             checkUOE(() -> {
 319                 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 320             });
 321 
 322             checkUOE(() -> {
 323                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 324             });
 325 
 326             checkUOE(() -> {
 327                 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 328             });
 329 
 330             checkUOE(() -> {
 331                 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
 332             });
 333 #end[CAS]
 334 
 335 #if[AtomicAdd]
 336             checkROBE(() -> {
 337                 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
 338             });
 339 
 340             checkROBE(() -> {
 341                 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
 342             });
 343 #else[AtomicAdd]
 344             checkUOE(() -> {
 345                 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
 346             });
 347 
 348             checkUOE(() -> {
 349                 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
 350             });
 351 #end[AtomicAdd]
 352         }
 353         else {
 354 #if[!CAS]
 355             checkUOE(() -> {
 356                 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 357             });
 358 
 359             checkUOE(() -> {
 360                 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
 361             });
 362 
 363             checkUOE(() -> {
 364                 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 365             });
 366 
 367             checkUOE(() -> {
 368                 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 369             });
 370 
 371             checkUOE(() -> {
 372                 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 373             });
 374 
 375             checkUOE(() -> {
 376                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 377             });
 378 
 379             checkUOE(() -> {
 380                 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 381             });
 382 
 383             checkUOE(() -> {
 384                 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
 385             });
 386 #end[CAS]
 387 #if[!AtomicAdd]
 388             checkUOE(() -> {
 389                 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
 390             });
 391 
 392             checkUOE(() -> {
 393                 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
 394             });
 395 #end[AtomicAdd]
 396         }
 397     }
 398 
 399 
 400     static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
 401         VarHandle vh = vhs.s;
 402         byte[] array = bs.s;
 403 
 404         int length = array.length - SIZE + 1;
 405         for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
 406             final int ci = i;
 407 
 408             checkIOOBE(() -> {
 409                 $type$ x = ($type$) vh.get(array, ci);
 410             });
 411 
 412             checkIOOBE(() -> {
 413                 vh.set(array, ci, VALUE_1);
 414             });
 415 
 416             checkIOOBE(() -> {
 417                 $type$ x = ($type$) vh.getVolatile(array, ci);
 418             });
 419 
 420             checkIOOBE(() -> {
 421                 $type$ x = ($type$) vh.getAcquire(array, ci);
 422             });
 423 
 424             checkIOOBE(() -> {
 425                 $type$ x = ($type$) vh.getOpaque(array, ci);
 426             });
 427 
 428             checkIOOBE(() -> {
 429                 vh.setVolatile(array, ci, VALUE_1);
 430             });
 431 
 432             checkIOOBE(() -> {
 433                 vh.setRelease(array, ci, VALUE_1);
 434             });
 435 
 436             checkIOOBE(() -> {
 437                 vh.setOpaque(array, ci, VALUE_1);
 438             });
 439 #if[CAS]
 440 
 441             checkIOOBE(() -> {
 442                 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 443             });
 444 
 445             checkIOOBE(() -> {
 446                 $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
 447             });
 448 
 449             checkIOOBE(() -> {
 450                 $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 451             });
 452 
 453             checkIOOBE(() -> {
 454                 $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 455             });
 456 
 457             checkIOOBE(() -> {
 458                 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 459             });
 460 
 461             checkIOOBE(() -> {
 462                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 463             });
 464 
 465             checkIOOBE(() -> {
 466                 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 467             });
 468 
 469             checkIOOBE(() -> {
 470                 $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
 471             });
 472 #end[CAS]
 473 
 474 #if[AtomicAdd]
 475             checkIOOBE(() -> {
 476                 $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
 477             });
 478 
 479             checkIOOBE(() -> {
 480                 $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
 481             });
 482 #end[AtomicAdd]
 483 
 484         }
 485     }
 486 
 487     static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
 488         VarHandle vh = vhs.s;
 489         ByteBuffer array = bs.s;
 490 
 491         boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
 492 
 493         int length = array.limit() - SIZE + 1;
 494         for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
 495             final int ci = i;
 496 
 497             checkIOOBE(() -> {
 498                 $type$ x = ($type$) vh.get(array, ci);
 499             });
 500 
 501             if (!readOnly) {
 502                 checkIOOBE(() -> {
 503                     vh.set(array, ci, VALUE_1);
 504                 });
 505             }
 506 
 507             checkIOOBE(() -> {
 508                 $type$ x = ($type$) vh.getVolatile(array, ci);
 509             });
 510 
 511             checkIOOBE(() -> {
 512                 $type$ x = ($type$) vh.getAcquire(array, ci);
 513             });
 514 
 515             checkIOOBE(() -> {
 516                 $type$ x = ($type$) vh.getOpaque(array, ci);
 517             });
 518 
 519             if (!readOnly) {
 520                 checkIOOBE(() -> {
 521                     vh.setVolatile(array, ci, VALUE_1);
 522                 });
 523 
 524                 checkIOOBE(() -> {
 525                     vh.setRelease(array, ci, VALUE_1);
 526                 });
 527 
 528                 checkIOOBE(() -> {
 529                     vh.setOpaque(array, ci, VALUE_1);
 530                 });
 531 
 532 #if[CAS]
 533                 checkIOOBE(() -> {
 534                     boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 535                 });
 536 
 537                 checkIOOBE(() -> {
 538                     $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
 539                 });
 540 
 541                 checkIOOBE(() -> {
 542                     $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 543                 });
 544 
 545                 checkIOOBE(() -> {
 546                     $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 547                 });
 548 
 549                 checkIOOBE(() -> {
 550                     boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 551                 });
 552 
 553                 checkIOOBE(() -> {
 554                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 555                 });
 556 
 557                 checkIOOBE(() -> {
 558                     boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 559                 });
 560 
 561                 checkIOOBE(() -> {
 562                     $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
 563                 });
 564 #end[CAS]
 565 
 566 #if[AtomicAdd]
 567                 checkIOOBE(() -> {
 568                     $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
 569                 });
 570 
 571                 checkIOOBE(() -> {
 572                     $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
 573                 });
 574 #end[AtomicAdd]
 575             }
 576         }
 577     }
 578 
 579     static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
 580         VarHandle vh = vhs.s;
 581         byte[] array = bs.s;
 582 
 583         int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
 584 
 585         int length = array.length - SIZE + 1;
 586         for (int i = 0; i < length; i++) {
 587             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 588             final int ci = i;
 589 
 590             if (!iAligned) {
 591                 checkISE(() -> {
 592                     $type$ x = ($type$) vh.getVolatile(array, ci);
 593                 });
 594 
 595                 checkISE(() -> {
 596                     $type$ x = ($type$) vh.getAcquire(array, ci);
 597                 });
 598 
 599                 checkISE(() -> {
 600                     $type$ x = ($type$) vh.getOpaque(array, ci);
 601                 });
 602 
 603                 checkISE(() -> {
 604                     vh.setVolatile(array, ci, VALUE_1);
 605                 });
 606 
 607                 checkISE(() -> {
 608                     vh.setRelease(array, ci, VALUE_1);
 609                 });
 610 
 611                 checkISE(() -> {
 612                     vh.setOpaque(array, ci, VALUE_1);
 613                 });
 614 #if[CAS]
 615 
 616                 checkISE(() -> {
 617                     boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 618                 });
 619 
 620                 checkISE(() -> {
 621                     $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
 622                 });
 623 
 624                 checkISE(() -> {
 625                     $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 626                 });
 627 
 628                 checkISE(() -> {
 629                     $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 630                 });
 631 
 632                 checkISE(() -> {
 633                     boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 634                 });
 635 
 636                 checkISE(() -> {
 637                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 638                 });
 639 
 640                 checkISE(() -> {
 641                     boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 642                 });
 643 
 644                 checkISE(() -> {
 645                     $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
 646                 });
 647 #end[CAS]
 648 
 649 #if[AtomicAdd]
 650                 checkISE(() -> {
 651                     $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
 652                 });
 653 
 654                 checkISE(() -> {
 655                     $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
 656                 });
 657 #end[AtomicAdd]
 658 
 659             }
 660         }
 661     }
 662 
 663     static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
 664         VarHandle vh = vhs.s;
 665         ByteBuffer array = bs.s;
 666 
 667         boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
 668         int misalignmentAtZero = array.alignmentOffset(0, SIZE);
 669 
 670         int length = array.limit() - SIZE + 1;
 671         for (int i = 0; i < length; i++) {
 672             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 673             final int ci = i;
 674 
 675             if (!iAligned) {
 676                 checkISE(() -> {
 677                     $type$ x = ($type$) vh.getVolatile(array, ci);
 678                 });
 679 
 680                 checkISE(() -> {
 681                     $type$ x = ($type$) vh.getAcquire(array, ci);
 682                 });
 683 
 684                 checkISE(() -> {
 685                     $type$ x = ($type$) vh.getOpaque(array, ci);
 686                 });
 687 
 688                 if (!readOnly) {
 689                     checkISE(() -> {
 690                         vh.setVolatile(array, ci, VALUE_1);
 691                     });
 692 
 693                     checkISE(() -> {
 694                         vh.setRelease(array, ci, VALUE_1);
 695                     });
 696 
 697                     checkISE(() -> {
 698                         vh.setOpaque(array, ci, VALUE_1);
 699                     });
 700 
 701 #if[CAS]
 702                     checkISE(() -> {
 703                         boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 704                     });
 705 
 706                     checkISE(() -> {
 707                         $type$ r = ($type$) vh.compareAndExchangeVolatile(array, ci, VALUE_2, VALUE_1);
 708                     });
 709 
 710                     checkISE(() -> {
 711                         $type$ r = ($type$) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 712                     });
 713 
 714                     checkISE(() -> {
 715                         $type$ r = ($type$) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 716                     });
 717 
 718                     checkISE(() -> {
 719                         boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 720                     });
 721 
 722                     checkISE(() -> {
 723                         boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 724                     });
 725 
 726                     checkISE(() -> {
 727                         boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 728                     });
 729 
 730                     checkISE(() -> {
 731                         $type$ o = ($type$) vh.getAndSet(array, ci, VALUE_1);
 732                     });
 733 #end[CAS]
 734 
 735 #if[AtomicAdd]
 736                     checkISE(() -> {
 737                         $type$ o = ($type$) vh.getAndAdd(array, ci, VALUE_1);
 738                     });
 739 
 740                     checkISE(() -> {
 741                         $type$ o = ($type$) vh.addAndGet(array, ci, VALUE_1);
 742                     });
 743 #end[AtomicAdd]
 744                 }
 745             }
 746         }
 747     }
 748 
 749     static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
 750         VarHandle vh = vhs.s;
 751         byte[] array = bs.s;
 752 
 753         int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
 754 
 755         bs.fill((byte) 0xff);
 756         int length = array.length - SIZE + 1;
 757         for (int i = 0; i < length; i++) {
 758             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 759 
 760             // Plain
 761             {
 762                 vh.set(array, i, VALUE_1);
 763                 $type$ x = ($type$) vh.get(array, i);
 764                 assertEquals(x, VALUE_1, "get $type$ value");
 765             }
 766 
 767 
 768             if (iAligned) {
 769                 // Volatile
 770                 {
 771                     vh.setVolatile(array, i, VALUE_2);
 772                     $type$ x = ($type$) vh.getVolatile(array, i);
 773                     assertEquals(x, VALUE_2, "setVolatile $type$ value");
 774                 }
 775 
 776                 // Lazy
 777                 {
 778                     vh.setRelease(array, i, VALUE_1);
 779                     $type$ x = ($type$) vh.getAcquire(array, i);
 780                     assertEquals(x, VALUE_1, "setRelease $type$ value");
 781                 }
 782 
 783                 // Opaque
 784                 {
 785                     vh.setOpaque(array, i, VALUE_2);
 786                     $type$ x = ($type$) vh.getOpaque(array, i);
 787                     assertEquals(x, VALUE_2, "setOpaque $type$ value");
 788                 }
 789 #if[CAS]
 790 
 791                 vh.set(array, i, VALUE_1);
 792 
 793                 // Compare
 794                 {
 795                     boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
 796                     assertEquals(r, true, "success compareAndSet $type$");
 797                     $type$ x = ($type$) vh.get(array, i);
 798                     assertEquals(x, VALUE_2, "success compareAndSet $type$ value");
 799                 }
 800 
 801                 {
 802                     boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
 803                     assertEquals(r, false, "failing compareAndSet $type$");
 804                     $type$ x = ($type$) vh.get(array, i);
 805                     assertEquals(x, VALUE_2, "failing compareAndSet $type$ value");
 806                 }
 807 
 808                 {
 809                     $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
 810                     assertEquals(r, VALUE_2, "success compareAndExchangeVolatile $type$");
 811                     $type$ x = ($type$) vh.get(array, i);
 812                     assertEquals(x, VALUE_1, "success compareAndExchangeVolatile $type$ value");
 813                 }
 814 
 815                 {
 816                     $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
 817                     assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile $type$");
 818                     $type$ x = ($type$) vh.get(array, i);
 819                     assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile $type$ value");
 820                 }
 821 
 822                 {
 823                     $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
 824                     assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$");
 825                     $type$ x = ($type$) vh.get(array, i);
 826                     assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value");
 827                 }
 828 
 829                 {
 830                     $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
 831                     assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$");
 832                     $type$ x = ($type$) vh.get(array, i);
 833                     assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value");
 834                 }
 835 
 836                 {
 837                     $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
 838                     assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$");
 839                     $type$ x = ($type$) vh.get(array, i);
 840                     assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value");
 841                 }
 842 
 843                 {
 844                     $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
 845                     assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$");
 846                     $type$ x = ($type$) vh.get(array, i);
 847                     assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value");
 848                 }
 849 
 850                 {
 851                     boolean success = false;
 852                     for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 853                         success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
 854                     }
 855                     assertEquals(success, true, "weakCompareAndSet $type$");
 856                     $type$ x = ($type$) vh.get(array, i);
 857                     assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value");
 858                 }
 859 
 860                 {
 861                     boolean success = false;
 862                     for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 863                         success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
 864                     }
 865                     assertEquals(success, true, "weakCompareAndSetAcquire $type$");
 866                     $type$ x = ($type$) vh.get(array, i);
 867                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$");
 868                 }
 869 
 870                 {
 871                     boolean success = false;
 872                     for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
 873                         success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
 874                     }
 875                     assertEquals(success, true, "weakCompareAndSetRelease $type$");
 876                     $type$ x = ($type$) vh.get(array, i);
 877                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
 878                 }
 879 
 880                 // Compare set and get
 881                 {
 882                     $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1);
 883                     assertEquals(o, VALUE_2, "getAndSet $type$");
 884                     $type$ x = ($type$) vh.get(array, i);
 885                     assertEquals(x, VALUE_1, "getAndSet $type$ value");
 886                 }
 887 #end[CAS]
 888 
 889 #if[AtomicAdd]
 890                 vh.set(array, i, VALUE_1);
 891 
 892                 // get and add, add and get
 893                 {
 894                     $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_3);
 895                     assertEquals(o, VALUE_1, "getAndAdd $type$");
 896                     $type$ c = ($type$) vh.addAndGet(array, i, VALUE_3);
 897                     assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd $type$ value");
 898                 }
 899 #end[AtomicAdd]
 900             }
 901         }
 902     }
 903 
 904 
 905     static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
 906         VarHandle vh = vhs.s;
 907         ByteBuffer array = bs.s;
 908 
 909         int misalignmentAtZero = array.alignmentOffset(0, SIZE);
 910 
 911         bs.fill((byte) 0xff);
 912         int length = array.limit() - SIZE + 1;
 913         for (int i = 0; i < length; i++) {
 914             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 915 
 916             // Plain
 917             {
 918                 vh.set(array, i, VALUE_1);
 919                 $type$ x = ($type$) vh.get(array, i);
 920                 assertEquals(x, VALUE_1, "get $type$ value");
 921             }
 922 
 923             if (iAligned) {
 924                 // Volatile
 925                 {
 926                     vh.setVolatile(array, i, VALUE_2);
 927                     $type$ x = ($type$) vh.getVolatile(array, i);
 928                     assertEquals(x, VALUE_2, "setVolatile $type$ value");
 929                 }
 930 
 931                 // Lazy
 932                 {
 933                     vh.setRelease(array, i, VALUE_1);
 934                     $type$ x = ($type$) vh.getAcquire(array, i);
 935                     assertEquals(x, VALUE_1, "setRelease $type$ value");
 936                 }
 937 
 938                 // Opaque
 939                 {
 940                     vh.setOpaque(array, i, VALUE_2);
 941                     $type$ x = ($type$) vh.getOpaque(array, i);
 942                     assertEquals(x, VALUE_2, "setOpaque $type$ value");
 943                 }
 944 #if[CAS]
 945 
 946                 vh.set(array, i, VALUE_1);
 947 
 948                 // Compare
 949                 {
 950                     boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_2);
 951                     assertEquals(r, true, "success compareAndSet $type$");
 952                     $type$ x = ($type$) vh.get(array, i);
 953                     assertEquals(x, VALUE_2, "success compareAndSet $type$ value");
 954                 }
 955 
 956                 {
 957                     boolean r = vh.compareAndSet(array, i, VALUE_1, VALUE_3);
 958                     assertEquals(r, false, "failing compareAndSet $type$");
 959                     $type$ x = ($type$) vh.get(array, i);
 960                     assertEquals(x, VALUE_2, "failing compareAndSet $type$ value");
 961                 }
 962 
 963                 {
 964                     $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_1);
 965                     assertEquals(r, VALUE_2, "success compareAndExchangeVolatile $type$");
 966                     $type$ x = ($type$) vh.get(array, i);
 967                     assertEquals(x, VALUE_1, "success compareAndExchangeVolatile $type$ value");
 968                 }
 969 
 970                 {
 971                     $type$ r = ($type$) vh.compareAndExchangeVolatile(array, i, VALUE_2, VALUE_3);
 972                     assertEquals(r, VALUE_1, "failing compareAndExchangeVolatile $type$");
 973                     $type$ x = ($type$) vh.get(array, i);
 974                     assertEquals(x, VALUE_1, "failing compareAndExchangeVolatile $type$ value");
 975                 }
 976 
 977                 {
 978                     $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_2);
 979                     assertEquals(r, VALUE_1, "success compareAndExchangeAcquire $type$");
 980                     $type$ x = ($type$) vh.get(array, i);
 981                     assertEquals(x, VALUE_2, "success compareAndExchangeAcquire $type$ value");
 982                 }
 983 
 984                 {
 985                     $type$ r = ($type$) vh.compareAndExchangeAcquire(array, i, VALUE_1, VALUE_3);
 986                     assertEquals(r, VALUE_2, "failing compareAndExchangeAcquire $type$");
 987                     $type$ x = ($type$) vh.get(array, i);
 988                     assertEquals(x, VALUE_2, "failing compareAndExchangeAcquire $type$ value");
 989                 }
 990 
 991                 {
 992                     $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_1);
 993                     assertEquals(r, VALUE_2, "success compareAndExchangeRelease $type$");
 994                     $type$ x = ($type$) vh.get(array, i);
 995                     assertEquals(x, VALUE_1, "success compareAndExchangeRelease $type$ value");
 996                 }
 997 
 998                 {
 999                     $type$ r = ($type$) vh.compareAndExchangeRelease(array, i, VALUE_2, VALUE_3);
1000                     assertEquals(r, VALUE_1, "failing compareAndExchangeRelease $type$");
1001                     $type$ x = ($type$) vh.get(array, i);
1002                     assertEquals(x, VALUE_1, "failing compareAndExchangeRelease $type$ value");
1003                 }
1004 
1005                 {
1006                     boolean success = false;
1007                     for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
1008                         success = vh.weakCompareAndSet(array, i, VALUE_1, VALUE_2);
1009                     }
1010                     assertEquals(success, true, "weakCompareAndSet $type$");
1011                     $type$ x = ($type$) vh.get(array, i);
1012                     assertEquals(x, VALUE_2, "weakCompareAndSet $type$ value");
1013                 }
1014 
1015                 {
1016                     boolean success = false;
1017                     for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
1018                         success = vh.weakCompareAndSetAcquire(array, i, VALUE_2, VALUE_1);
1019                     }
1020                     assertEquals(success, true, "weakCompareAndSetAcquire $type$");
1021                     $type$ x = ($type$) vh.get(array, i);
1022                     assertEquals(x, VALUE_1, "weakCompareAndSetAcquire $type$");
1023                 }
1024 
1025                 {
1026                     boolean success = false;
1027                     for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
1028                         success = vh.weakCompareAndSetRelease(array, i, VALUE_1, VALUE_2);
1029                     }
1030                     assertEquals(success, true, "weakCompareAndSetRelease $type$");
1031                     $type$ x = ($type$) vh.get(array, i);
1032                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
1033                 }
1034 
1035                 // Compare set and get
1036                 {
1037                     $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1);
1038                     assertEquals(o, VALUE_2, "getAndSet $type$");
1039                     $type$ x = ($type$) vh.get(array, i);
1040                     assertEquals(x, VALUE_1, "getAndSet $type$ value");
1041                 }
1042 #end[CAS]
1043 
1044 #if[AtomicAdd]
1045                 vh.set(array, i, VALUE_1);
1046 
1047                 // get and add, add and get
1048                 {
1049                     $type$ o = ($type$) vh.getAndAdd(array, i, VALUE_3);
1050                     assertEquals(o, VALUE_1, "getAndAdd $type$");
1051                     $type$ c = ($type$) vh.addAndGet(array, i, VALUE_3);
1052                     assertEquals(c, VALUE_1 + VALUE_3 + VALUE_3, "getAndAdd $type$ value");
1053                 }
1054 #end[AtomicAdd]
1055             }
1056         }
1057     }
1058 
1059     static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
1060         VarHandle vh = vhs.s;
1061         ByteBuffer array = bs.s;
1062 
1063         int misalignmentAtZero = array.alignmentOffset(0, SIZE);
1064 
1065         ByteBuffer bb = ByteBuffer.allocate(SIZE);
1066         bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
1067         bs.fill(bb.put$Type$(0, VALUE_2).array());
1068 
1069         int length = array.limit() - SIZE + 1;
1070         for (int i = 0; i < length; i++) {
1071             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
1072 
1073             $type$ v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
1074                     ? rotateLeft(VALUE_2, (i % SIZE) << 3)
1075                     : rotateRight(VALUE_2, (i % SIZE) << 3);
1076             // Plain
1077             {
1078                 $type$ x = ($type$) vh.get(array, i);
1079                 assertEquals(x, v, "get $type$ value");
1080             }
1081 
1082             if (iAligned) {
1083                 // Volatile
1084                 {
1085                     $type$ x = ($type$) vh.getVolatile(array, i);
1086                     assertEquals(x, v, "getVolatile $type$ value");
1087                 }
1088 
1089                 // Lazy
1090                 {
1091                     $type$ x = ($type$) vh.getAcquire(array, i);
1092                     assertEquals(x, v, "getRelease $type$ value");
1093                 }
1094 
1095                 // Opaque
1096                 {
1097                     $type$ x = ($type$) vh.getOpaque(array, i);
1098                     assertEquals(x, v, "getOpaque $type$ value");
1099                 }
1100             }
1101         }
1102     }
1103 
1104 }
1105