VarHandleTestByteArrayAsChar.java revision 14475:909f38c3d339
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
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 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
644