1 /*
   2  * Copyright (c) 2015, 2018, 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  * @bug 8154556
  27  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar
  28  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsChar
  29  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsChar
  30  */
  31 
  32 import org.testng.annotations.DataProvider;
  33 import org.testng.annotations.Test;
  34 
  35 import java.lang.invoke.MethodHandles;
  36 import java.lang.invoke.VarHandle;
  37 import java.nio.ByteBuffer;
  38 import java.nio.ByteOrder;
  39 import java.util.ArrayList;
  40 import java.util.Arrays;
  41 import java.util.EnumSet;
  42 import java.util.List;
  43 
  44 import static org.testng.Assert.*;
  45 
  46 public class VarHandleTestByteArrayAsChar extends VarHandleBaseByteArrayTest {
  47     static final int SIZE = Character.BYTES;
  48 
  49     static final char VALUE_1 = (char)0x0102;
  50 
  51     static final char VALUE_2 = (char)0x1112;
  52 
  53     static final char VALUE_3 = (char)0xFFFE;
  54 
  55 
  56     @Override
  57     public void setupVarHandleSources() {
  58         // Combinations of VarHandle byte[] or ByteBuffer
  59         vhss = new ArrayList<>();
  60         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
  61 
  62             ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
  63                     ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
  64             VarHandleSource aeh = new VarHandleSource(
  65                     MethodHandles.byteArrayViewVarHandle(char[].class, bo),
  66                     endianess, MemoryMode.READ_WRITE);
  67             vhss.add(aeh);
  68 
  69             VarHandleSource bbh = new VarHandleSource(
  70                     MethodHandles.byteBufferViewVarHandle(char[].class, bo),
  71                     endianess, MemoryMode.READ_WRITE);
  72             vhss.add(bbh);
  73         }
  74     }
  75 
  76 
  77     @Test(dataProvider = "varHandlesProvider")
  78     public void testIsAccessModeSupported(VarHandleSource vhs) {
  79         VarHandle vh = vhs.s;
  80 
  81         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET));
  82         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET));
  83 
  84         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_VOLATILE));
  85         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_VOLATILE));
  86         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_ACQUIRE));
  87         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_RELEASE));
  88         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_OPAQUE));
  89         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.SET_OPAQUE));
  90 
  91         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_SET));
  92         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE));
  93         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
  94         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
  95         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_PLAIN));
  96         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
  97         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
  98         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
  99         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 100         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_ACQUIRE));
 101         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET_RELEASE));
 102 
 103         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
 104         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_ACQUIRE));
 105         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD_RELEASE));
 106 
 107         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR));
 108         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_ACQUIRE));
 109         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_OR_RELEASE));
 110         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND));
 111         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_ACQUIRE));
 112         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_AND_RELEASE));
 113         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR));
 114         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_ACQUIRE));
 115         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_BITWISE_XOR_RELEASE));
 116     }
 117 
 118     @Test(dataProvider = "typesProvider")
 119     public void testTypes(VarHandle vh, List<java.lang.Class<?>> pts) {
 120         assertEquals(vh.varType(), char.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                                 "null array", bav, vh, h -> testArrayNPE(bas, h),
 143                                 false));
 144                         cases.add(new VarHandleSourceAccessTestCase(
 145                                 "unsupported", bav, vh, h -> testArrayUnsupported(bas, h),
 146                                 false));
 147                         cases.add(new VarHandleSourceAccessTestCase(
 148                                 "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bas, h),
 149                                 false));
 150                         cases.add(new VarHandleSourceAccessTestCase(
 151                                 "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bas, h),
 152                                 false));
 153                     }
 154                     else {
 155                         ByteBufferSource bbs = (ByteBufferSource) bav;
 156 
 157                         if (MemoryMode.READ_WRITE.isSet(bav.memoryModes)) {
 158                             cases.add(new VarHandleSourceAccessTestCase(
 159                                     "read write", bav, vh, h -> testArrayReadWrite(bbs, h),
 160                                     true));
 161                         }
 162                         else {
 163                             cases.add(new VarHandleSourceAccessTestCase(
 164                                     "read only", bav, vh, h -> testArrayReadOnly(bbs, h),
 165                                     true));
 166                         }
 167 
 168                         cases.add(new VarHandleSourceAccessTestCase(
 169                                 "null buffer", bav, vh, h -> testArrayNPE(bbs, h),
 170                                 false));
 171                         cases.add(new VarHandleSourceAccessTestCase(
 172                                 "unsupported", bav, vh, h -> testArrayUnsupported(bbs, h),
 173                                 false));
 174                         cases.add(new VarHandleSourceAccessTestCase(
 175                                 "index out of bounds", bav, vh, h -> testArrayIndexOutOfBounds(bbs, h),
 176                                 false));
 177                         cases.add(new VarHandleSourceAccessTestCase(
 178                                 "misaligned access", bav, vh, h -> testArrayMisalignedAccess(bbs, h),
 179                                 false));
 180                     }
 181                 }
 182             }
 183         }
 184 
 185         // Work around issue with jtreg summary reporting which truncates
 186         // the String result of Object.toString to 30 characters, hence
 187         // the first dummy argument
 188         return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
 189     }
 190 
 191     @Test(dataProvider = "accessTestCaseProvider")
 192     public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
 193         T t = atc.get();
 194         int iters = atc.requiresLoop() ? ITERS : 1;
 195         for (int c = 0; c < iters; c++) {
 196             atc.testAccess(t);
 197         }
 198     }
 199 
 200 
 201     static void testArrayNPE(ByteArraySource bs, VarHandleSource vhs) {
 202         VarHandle vh = vhs.s;
 203         byte[] array = null;
 204         int ci = 1;
 205 
 206         checkNPE(() -> {
 207             char x = (char) vh.get(array, ci);
 208         });
 209 
 210         checkNPE(() -> {
 211             vh.set(array, ci, VALUE_1);
 212         });
 213 
 214         checkNPE(() -> {
 215             char x = (char) vh.getVolatile(array, ci);
 216         });
 217 
 218         checkNPE(() -> {
 219             char x = (char) vh.getAcquire(array, ci);
 220         });
 221 
 222         checkNPE(() -> {
 223             char x = (char) vh.getOpaque(array, ci);
 224         });
 225 
 226         checkNPE(() -> {
 227             vh.setVolatile(array, ci, VALUE_1);
 228         });
 229 
 230         checkNPE(() -> {
 231             vh.setRelease(array, ci, VALUE_1);
 232         });
 233 
 234         checkNPE(() -> {
 235             vh.setOpaque(array, ci, VALUE_1);
 236         });
 237 
 238 
 239 
 240     }
 241 
 242     static void testArrayNPE(ByteBufferSource bs, VarHandleSource vhs) {
 243         VarHandle vh = vhs.s;
 244         ByteBuffer array = null;
 245         int ci = 1;
 246 
 247         checkNPE(() -> {
 248             char x = (char) vh.get(array, ci);
 249         });
 250 
 251         checkNPE(() -> {
 252             vh.set(array, ci, VALUE_1);
 253         });
 254 
 255         checkNPE(() -> {
 256             char x = (char) vh.getVolatile(array, ci);
 257         });
 258 
 259         checkNPE(() -> {
 260             char x = (char) vh.getAcquire(array, ci);
 261         });
 262 
 263         checkNPE(() -> {
 264             char x = (char) vh.getOpaque(array, ci);
 265         });
 266 
 267         checkNPE(() -> {
 268             vh.setVolatile(array, ci, VALUE_1);
 269         });
 270 
 271         checkNPE(() -> {
 272             vh.setRelease(array, ci, VALUE_1);
 273         });
 274 
 275         checkNPE(() -> {
 276             vh.setOpaque(array, ci, VALUE_1);
 277         });
 278 
 279 
 280 
 281     }
 282 
 283     static void testArrayUnsupported(ByteArraySource bs, VarHandleSource vhs) {
 284         VarHandle vh = vhs.s;
 285         byte[] array = bs.s;
 286         int ci = 1;
 287 
 288         checkUOE(() -> {
 289             boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 290         });
 291 
 292         checkUOE(() -> {
 293             char r = (char) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
 294         });
 295 
 296         checkUOE(() -> {
 297             char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 298         });
 299 
 300         checkUOE(() -> {
 301             char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 302         });
 303 
 304         checkUOE(() -> {
 305             boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
 306         });
 307 
 308         checkUOE(() -> {
 309             boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 310         });
 311 
 312         checkUOE(() -> {
 313             boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 314         });
 315 
 316         checkUOE(() -> {
 317             boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 318         });
 319 
 320         checkUOE(() -> {
 321             char o = (char) vh.getAndSet(array, ci, VALUE_1);
 322         });
 323 
 324         checkUOE(() -> {
 325             char o = (char) vh.getAndSetAcquire(array, ci, VALUE_1);
 326         });
 327 
 328         checkUOE(() -> {
 329             char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
 330         });
 331 
 332         checkUOE(() -> {
 333             char o = (char) vh.getAndAdd(array, ci, VALUE_1);
 334         });
 335 
 336         checkUOE(() -> {
 337             char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
 338         });
 339 
 340         checkUOE(() -> {
 341             char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
 342         });
 343 
 344         checkUOE(() -> {
 345             char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
 346         });
 347 
 348         checkUOE(() -> {
 349             char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
 350         });
 351 
 352         checkUOE(() -> {
 353             char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
 354         });
 355 
 356         checkUOE(() -> {
 357             char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
 358         });
 359 
 360         checkUOE(() -> {
 361             char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
 362         });
 363 
 364         checkUOE(() -> {
 365             char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
 366         });
 367 
 368         checkUOE(() -> {
 369             char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
 370         });
 371 
 372         checkUOE(() -> {
 373             char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
 374         });
 375 
 376         checkUOE(() -> {
 377             char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
 378         });
 379     }
 380 
 381     static void testArrayUnsupported(ByteBufferSource bs, VarHandleSource vhs) {
 382         VarHandle vh = vhs.s;
 383         ByteBuffer array = bs.s;
 384         int ci = 0;
 385         boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
 386 
 387         if (readOnly) {
 388             checkROBE(() -> {
 389                 vh.set(array, ci, VALUE_1);
 390             });
 391         }
 392 
 393         if (readOnly) {
 394             checkROBE(() -> {
 395                 vh.setVolatile(array, ci, VALUE_1);
 396             });
 397 
 398             checkROBE(() -> {
 399                 vh.setRelease(array, ci, VALUE_1);
 400             });
 401 
 402             checkROBE(() -> {
 403                 vh.setOpaque(array, ci, VALUE_1);
 404             });
 405             checkUOE(() -> {
 406                 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 407             });
 408 
 409             checkUOE(() -> {
 410                 char r = (char) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
 411             });
 412 
 413             checkUOE(() -> {
 414                 char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 415             });
 416 
 417             checkUOE(() -> {
 418                 char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 419             });
 420 
 421             checkUOE(() -> {
 422                 boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
 423             });
 424 
 425             checkUOE(() -> {
 426                 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 427             });
 428 
 429             checkUOE(() -> {
 430                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 431             });
 432 
 433             checkUOE(() -> {
 434                 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 435             });
 436 
 437             checkUOE(() -> {
 438                 char o = (char) vh.getAndSet(array, ci, VALUE_1);
 439             });
 440 
 441             checkUOE(() -> {
 442                 char o = (char) vh.getAndSetAcquire(array, ci, VALUE_1);
 443             });
 444 
 445             checkUOE(() -> {
 446                 char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
 447             });
 448 
 449             checkUOE(() -> {
 450                 char o = (char) vh.getAndAdd(array, ci, VALUE_1);
 451             });
 452 
 453             checkUOE(() -> {
 454                 char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
 455             });
 456 
 457             checkUOE(() -> {
 458                 char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
 459             });
 460 
 461             checkUOE(() -> {
 462                 char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
 463             });
 464 
 465             checkUOE(() -> {
 466                 char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
 467             });
 468 
 469             checkUOE(() -> {
 470                 char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
 471             });
 472 
 473             checkUOE(() -> {
 474                 char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
 475             });
 476 
 477             checkUOE(() -> {
 478                 char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
 479             });
 480 
 481             checkUOE(() -> {
 482                 char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
 483             });
 484 
 485             checkUOE(() -> {
 486                 char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
 487             });
 488 
 489             checkUOE(() -> {
 490                 char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
 491             });
 492 
 493             checkUOE(() -> {
 494                 char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
 495             });
 496         }
 497         else {
 498             checkUOE(() -> {
 499                 boolean r = vh.compareAndSet(array, ci, VALUE_1, VALUE_2);
 500             });
 501 
 502             checkUOE(() -> {
 503                 char r = (char) vh.compareAndExchange(array, ci, VALUE_2, VALUE_1);
 504             });
 505 
 506             checkUOE(() -> {
 507                 char r = (char) vh.compareAndExchangeAcquire(array, ci, VALUE_2, VALUE_1);
 508             });
 509 
 510             checkUOE(() -> {
 511                 char r = (char) vh.compareAndExchangeRelease(array, ci, VALUE_2, VALUE_1);
 512             });
 513 
 514             checkUOE(() -> {
 515                 boolean r = vh.weakCompareAndSetPlain(array, ci, VALUE_1, VALUE_2);
 516             });
 517 
 518             checkUOE(() -> {
 519                 boolean r = vh.weakCompareAndSet(array, ci, VALUE_1, VALUE_2);
 520             });
 521 
 522             checkUOE(() -> {
 523                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
 524             });
 525 
 526             checkUOE(() -> {
 527                 boolean r = vh.weakCompareAndSetRelease(array, ci, VALUE_1, VALUE_2);
 528             });
 529 
 530             checkUOE(() -> {
 531                 char o = (char) vh.getAndSet(array, ci, VALUE_1);
 532             });
 533 
 534             checkUOE(() -> {
 535                 char o = (char) vh.getAndSetAcquire(array, ci, VALUE_1);
 536             });
 537 
 538             checkUOE(() -> {
 539                 char o = (char) vh.getAndSetRelease(array, ci, VALUE_1);
 540             });
 541             checkUOE(() -> {
 542                 char o = (char) vh.getAndAdd(array, ci, VALUE_1);
 543             });
 544 
 545             checkUOE(() -> {
 546                 char o = (char) vh.getAndAddAcquire(array, ci, VALUE_1);
 547             });
 548 
 549             checkUOE(() -> {
 550                 char o = (char) vh.getAndAddRelease(array, ci, VALUE_1);
 551             });
 552             checkUOE(() -> {
 553                 char o = (char) vh.getAndBitwiseOr(array, ci, VALUE_1);
 554             });
 555 
 556             checkUOE(() -> {
 557                 char o = (char) vh.getAndBitwiseOrAcquire(array, ci, VALUE_1);
 558             });
 559 
 560             checkUOE(() -> {
 561                 char o = (char) vh.getAndBitwiseOrRelease(array, ci, VALUE_1);
 562             });
 563 
 564             checkUOE(() -> {
 565                 char o = (char) vh.getAndBitwiseAnd(array, ci, VALUE_1);
 566             });
 567 
 568             checkUOE(() -> {
 569                 char o = (char) vh.getAndBitwiseAndAcquire(array, ci, VALUE_1);
 570             });
 571 
 572             checkUOE(() -> {
 573                 char o = (char) vh.getAndBitwiseAndRelease(array, ci, VALUE_1);
 574             });
 575 
 576             checkUOE(() -> {
 577                 char o = (char) vh.getAndBitwiseXor(array, ci, VALUE_1);
 578             });
 579 
 580             checkUOE(() -> {
 581                 char o = (char) vh.getAndBitwiseXorAcquire(array, ci, VALUE_1);
 582             });
 583 
 584             checkUOE(() -> {
 585                 char o = (char) vh.getAndBitwiseXorRelease(array, ci, VALUE_1);
 586             });
 587         }
 588     }
 589 
 590 
 591     static void testArrayIndexOutOfBounds(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
 592         VarHandle vh = vhs.s;
 593         byte[] array = bs.s;
 594 
 595         int length = array.length - SIZE + 1;
 596         for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
 597             final int ci = i;
 598 
 599             checkIOOBE(() -> {
 600                 char x = (char) vh.get(array, ci);
 601             });
 602 
 603             checkIOOBE(() -> {
 604                 vh.set(array, ci, VALUE_1);
 605             });
 606 
 607             checkIOOBE(() -> {
 608                 char x = (char) vh.getVolatile(array, ci);
 609             });
 610 
 611             checkIOOBE(() -> {
 612                 char x = (char) vh.getAcquire(array, ci);
 613             });
 614 
 615             checkIOOBE(() -> {
 616                 char x = (char) vh.getOpaque(array, ci);
 617             });
 618 
 619             checkIOOBE(() -> {
 620                 vh.setVolatile(array, ci, VALUE_1);
 621             });
 622 
 623             checkIOOBE(() -> {
 624                 vh.setRelease(array, ci, VALUE_1);
 625             });
 626 
 627             checkIOOBE(() -> {
 628                 vh.setOpaque(array, ci, VALUE_1);
 629             });
 630 
 631 
 632 
 633         }
 634     }
 635 
 636     static void testArrayIndexOutOfBounds(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
 637         VarHandle vh = vhs.s;
 638         ByteBuffer array = bs.s;
 639 
 640         boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
 641 
 642         int length = array.limit() - SIZE + 1;
 643         for (int i : new int[]{-1, Integer.MIN_VALUE, length, length + 1, Integer.MAX_VALUE}) {
 644             final int ci = i;
 645 
 646             checkIOOBE(() -> {
 647                 char x = (char) vh.get(array, ci);
 648             });
 649 
 650             if (!readOnly) {
 651                 checkIOOBE(() -> {
 652                     vh.set(array, ci, VALUE_1);
 653                 });
 654             }
 655 
 656             checkIOOBE(() -> {
 657                 char x = (char) vh.getVolatile(array, ci);
 658             });
 659 
 660             checkIOOBE(() -> {
 661                 char x = (char) vh.getAcquire(array, ci);
 662             });
 663 
 664             checkIOOBE(() -> {
 665                 char x = (char) vh.getOpaque(array, ci);
 666             });
 667 
 668             if (!readOnly) {
 669                 checkIOOBE(() -> {
 670                     vh.setVolatile(array, ci, VALUE_1);
 671                 });
 672 
 673                 checkIOOBE(() -> {
 674                     vh.setRelease(array, ci, VALUE_1);
 675                 });
 676 
 677                 checkIOOBE(() -> {
 678                     vh.setOpaque(array, ci, VALUE_1);
 679                 });
 680 
 681 
 682 
 683             }
 684         }
 685     }
 686 
 687     static void testArrayMisalignedAccess(ByteArraySource bs, VarHandleSource vhs) throws Throwable {
 688         VarHandle vh = vhs.s;
 689         byte[] array = bs.s;
 690 
 691         int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
 692 
 693         int length = array.length - SIZE + 1;
 694         for (int i = 0; i < length; i++) {
 695             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 696             final int ci = i;
 697 
 698             if (!iAligned) {
 699                 checkISE(() -> {
 700                     char x = (char) vh.getVolatile(array, ci);
 701                 });
 702 
 703                 checkISE(() -> {
 704                     char x = (char) vh.getAcquire(array, ci);
 705                 });
 706 
 707                 checkISE(() -> {
 708                     char x = (char) vh.getOpaque(array, ci);
 709                 });
 710 
 711                 checkISE(() -> {
 712                     vh.setVolatile(array, ci, VALUE_1);
 713                 });
 714 
 715                 checkISE(() -> {
 716                     vh.setRelease(array, ci, VALUE_1);
 717                 });
 718 
 719                 checkISE(() -> {
 720                     vh.setOpaque(array, ci, VALUE_1);
 721                 });
 722 
 723 
 724             }
 725         }
 726     }
 727 
 728     static void testArrayMisalignedAccess(ByteBufferSource bs, VarHandleSource vhs) throws Throwable {
 729         VarHandle vh = vhs.s;
 730         ByteBuffer array = bs.s;
 731 
 732         boolean readOnly = MemoryMode.READ_ONLY.isSet(bs.memoryModes);
 733         int misalignmentAtZero = array.alignmentOffset(0, SIZE);
 734 
 735         int length = array.limit() - SIZE + 1;
 736         for (int i = 0; i < length; i++) {
 737             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 738             final int ci = i;
 739 
 740             if (!iAligned) {
 741                 checkISE(() -> {
 742                     char x = (char) vh.getVolatile(array, ci);
 743                 });
 744 
 745                 checkISE(() -> {
 746                     char x = (char) vh.getAcquire(array, ci);
 747                 });
 748 
 749                 checkISE(() -> {
 750                     char x = (char) vh.getOpaque(array, ci);
 751                 });
 752 
 753                 if (!readOnly) {
 754                     checkISE(() -> {
 755                         vh.setVolatile(array, ci, VALUE_1);
 756                     });
 757 
 758                     checkISE(() -> {
 759                         vh.setRelease(array, ci, VALUE_1);
 760                     });
 761 
 762                     checkISE(() -> {
 763                         vh.setOpaque(array, ci, VALUE_1);
 764                     });
 765 
 766 
 767 
 768                 }
 769             }
 770         }
 771     }
 772 
 773     static void testArrayReadWrite(ByteArraySource bs, VarHandleSource vhs) {
 774         VarHandle vh = vhs.s;
 775         byte[] array = bs.s;
 776 
 777         int misalignmentAtZero = ByteBuffer.wrap(array).alignmentOffset(0, SIZE);
 778 
 779         bs.fill((byte) 0xff);
 780         int length = array.length - SIZE + 1;
 781         for (int i = 0; i < length; i++) {
 782             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 783 
 784             // Plain
 785             {
 786                 vh.set(array, i, VALUE_1);
 787                 char x = (char) vh.get(array, i);
 788                 assertEquals(x, VALUE_1, "get char value");
 789             }
 790 
 791 
 792             if (iAligned) {
 793                 // Volatile
 794                 {
 795                     vh.setVolatile(array, i, VALUE_2);
 796                     char x = (char) vh.getVolatile(array, i);
 797                     assertEquals(x, VALUE_2, "setVolatile char value");
 798                 }
 799 
 800                 // Lazy
 801                 {
 802                     vh.setRelease(array, i, VALUE_1);
 803                     char x = (char) vh.getAcquire(array, i);
 804                     assertEquals(x, VALUE_1, "setRelease char value");
 805                 }
 806 
 807                 // Opaque
 808                 {
 809                     vh.setOpaque(array, i, VALUE_2);
 810                     char x = (char) vh.getOpaque(array, i);
 811                     assertEquals(x, VALUE_2, "setOpaque char value");
 812                 }
 813 
 814 
 815             }
 816         }
 817     }
 818 
 819 
 820     static void testArrayReadWrite(ByteBufferSource bs, VarHandleSource vhs) {
 821         VarHandle vh = vhs.s;
 822         ByteBuffer array = bs.s;
 823 
 824         int misalignmentAtZero = array.alignmentOffset(0, SIZE);
 825 
 826         bs.fill((byte) 0xff);
 827         int length = array.limit() - SIZE + 1;
 828         for (int i = 0; i < length; i++) {
 829             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 830 
 831             // Plain
 832             {
 833                 vh.set(array, i, VALUE_1);
 834                 char x = (char) vh.get(array, i);
 835                 assertEquals(x, VALUE_1, "get char value");
 836             }
 837 
 838             if (iAligned) {
 839                 // Volatile
 840                 {
 841                     vh.setVolatile(array, i, VALUE_2);
 842                     char x = (char) vh.getVolatile(array, i);
 843                     assertEquals(x, VALUE_2, "setVolatile char value");
 844                 }
 845 
 846                 // Lazy
 847                 {
 848                     vh.setRelease(array, i, VALUE_1);
 849                     char x = (char) vh.getAcquire(array, i);
 850                     assertEquals(x, VALUE_1, "setRelease char value");
 851                 }
 852 
 853                 // Opaque
 854                 {
 855                     vh.setOpaque(array, i, VALUE_2);
 856                     char x = (char) vh.getOpaque(array, i);
 857                     assertEquals(x, VALUE_2, "setOpaque char value");
 858                 }
 859 
 860 
 861             }
 862         }
 863     }
 864 
 865     static void testArrayReadOnly(ByteBufferSource bs, VarHandleSource vhs) {
 866         VarHandle vh = vhs.s;
 867         ByteBuffer array = bs.s;
 868 
 869         int misalignmentAtZero = array.alignmentOffset(0, SIZE);
 870 
 871         ByteBuffer bb = ByteBuffer.allocate(SIZE);
 872         bb.order(MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes) ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
 873         bs.fill(bb.putChar(0, VALUE_2).array());
 874 
 875         int length = array.limit() - SIZE + 1;
 876         for (int i = 0; i < length; i++) {
 877             boolean iAligned = ((i + misalignmentAtZero) & (SIZE - 1)) == 0;
 878 
 879             char v = MemoryMode.BIG_ENDIAN.isSet(vhs.memoryModes)
 880                     ? rotateLeft(VALUE_2, (i % SIZE) << 3)
 881                     : rotateRight(VALUE_2, (i % SIZE) << 3);
 882             // Plain
 883             {
 884                 char x = (char) vh.get(array, i);
 885                 assertEquals(x, v, "get char value");
 886             }
 887 
 888             if (iAligned) {
 889                 // Volatile
 890                 {
 891                     char x = (char) vh.getVolatile(array, i);
 892                     assertEquals(x, v, "getVolatile char value");
 893                 }
 894 
 895                 // Lazy
 896                 {
 897                     char x = (char) vh.getAcquire(array, i);
 898                     assertEquals(x, v, "getRelease char value");
 899                 }
 900 
 901                 // Opaque
 902                 {
 903                     char x = (char) vh.getOpaque(array, i);
 904                     assertEquals(x, v, "getOpaque char value");
 905                 }
 906             }
 907         }
 908     }
 909 
 910 }
 911