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