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