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