1 /*
  2  * Copyright (c) 2015, 2025, 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  * @comment Set CompileThresholdScaling to 0.1 so that the warmup loop sets to 2000 iterations
 27  *          to hit compilation thresholds
 28  * @run junit/othervm -Diters=2000 -XX:CompileThresholdScaling=0.1 VarHandleTestMethodHandleAccessString
 29  */
 30 
 31 import java.lang.invoke.MethodHandle;
 32 import java.lang.invoke.MethodHandles;
 33 import java.lang.invoke.VarHandle;
 34 import java.util.ArrayList;
 35 import java.util.List;
 36 
 37 import static org.junit.jupiter.api.Assertions.*;
 38 import org.junit.jupiter.api.BeforeAll;
 39 import org.junit.jupiter.api.TestInstance;
 40 import org.junit.jupiter.params.ParameterizedTest;
 41 import org.junit.jupiter.params.provider.MethodSource;
 42 
 43 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 44 public class VarHandleTestMethodHandleAccessString extends VarHandleBaseTest {
 45     static final String static_final_v = "foo";
 46 
 47     static String static_v;
 48 
 49     final String final_v = "foo";
 50 
 51     String v;
 52 
 53     VarHandle vhFinalField;
 54 
 55     VarHandle vhField;
 56 
 57     VarHandle vhStaticField;
 58 
 59     VarHandle vhStaticFinalField;
 60 
 61     VarHandle vhArray;
 62 
 63     @BeforeAll
 64     public void setup() throws Exception {
 65         vhFinalField = MethodHandles.lookup().findVarHandle(
 66                 VarHandleTestMethodHandleAccessString.class, "final_v", String.class);
 67 
 68         vhField = MethodHandles.lookup().findVarHandle(
 69                 VarHandleTestMethodHandleAccessString.class, "v", String.class);
 70 
 71         vhStaticFinalField = MethodHandles.lookup().findStaticVarHandle(
 72             VarHandleTestMethodHandleAccessString.class, "static_final_v", String.class);
 73 
 74         vhStaticField = MethodHandles.lookup().findStaticVarHandle(
 75             VarHandleTestMethodHandleAccessString.class, "static_v", String.class);
 76 
 77         vhArray = MethodHandles.arrayElementVarHandle(String[].class);
 78     }
 79 
 80     public Object[][] accessTestCaseProvider() throws Exception {
 81         List<AccessTestCase<?>> cases = new ArrayList<>();
 82 
 83         for (VarHandleToMethodHandle f : VarHandleToMethodHandle.values()) {
 84             cases.add(new MethodHandleAccessTestCase("Instance field",
 85                                                      vhField, f, hs -> testInstanceField(this, hs)));
 86             cases.add(new MethodHandleAccessTestCase("Instance field unsupported",
 87                                                      vhField, f, hs -> testInstanceFieldUnsupported(this, hs),
 88                                                      false));
 89 
 90             cases.add(new MethodHandleAccessTestCase("Static field",
 91                                                      vhStaticField, f, VarHandleTestMethodHandleAccessString::testStaticField));
 92             cases.add(new MethodHandleAccessTestCase("Static field unsupported",
 93                                                      vhStaticField, f, VarHandleTestMethodHandleAccessString::testStaticFieldUnsupported,
 94                                                      false));
 95 
 96             cases.add(new MethodHandleAccessTestCase("Array",
 97                                                      vhArray, f, VarHandleTestMethodHandleAccessString::testArray));
 98             cases.add(new MethodHandleAccessTestCase("Array unsupported",
 99                                                      vhArray, f, VarHandleTestMethodHandleAccessString::testArrayUnsupported,
100                                                      false));
101             cases.add(new MethodHandleAccessTestCase("Array index out of bounds",
102                                                      vhArray, f, VarHandleTestMethodHandleAccessString::testArrayIndexOutOfBounds,
103                                                      false));
104         }
105 
106         // Work around issue with jtreg summary reporting which truncates
107         // the String result of Object.toString to 30 characters, hence
108         // the first dummy argument
109         return cases.stream().map(tc -> new Object[]{tc.toString(), tc}).toArray(Object[][]::new);
110     }
111 
112     @ParameterizedTest
113     @MethodSource("accessTestCaseProvider")
114     public <T> void testAccess(String desc, AccessTestCase<T> atc) throws Throwable {
115         T t = atc.get();
116         int iters = atc.requiresLoop() ? ITERS : 1;
117         for (int c = 0; c < iters; c++) {
118             atc.testAccess(t);
119         }
120     }
121 
122     static void testInstanceField(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
123         // Plain
124         {
125             hs.get(TestAccessMode.SET).invokeExact(recv, "foo");
126             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
127             assertEquals("foo", x, "set String value");
128         }
129 
130 
131         // Volatile
132         {
133             hs.get(TestAccessMode.SET_VOLATILE).invokeExact(recv, "bar");
134             String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(recv);
135             assertEquals("bar", x, "setVolatile String value");
136         }
137 
138         // Lazy
139         {
140             hs.get(TestAccessMode.SET_RELEASE).invokeExact(recv, "foo");
141             String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(recv);
142             assertEquals("foo", x, "setRelease String value");
143         }
144 
145         // Opaque
146         {
147             hs.get(TestAccessMode.SET_OPAQUE).invokeExact(recv, "bar");
148             String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(recv);
149             assertEquals("bar", x, "setOpaque String value");
150         }
151 
152         hs.get(TestAccessMode.SET).invokeExact(recv, "foo");
153 
154         // Compare
155         {
156             boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, "foo", "bar");
157             assertEquals(r, true, "success compareAndSet String");
158             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
159             assertEquals("bar", x, "success compareAndSet String value");
160         }
161 
162         {
163             boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(recv, "foo", "baz");
164             assertEquals(r, false, "failing compareAndSet String");
165             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
166             assertEquals("bar", x, "failing compareAndSet String value");
167         }
168 
169         {
170             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, "bar", "foo");
171             assertEquals(r, "bar", "success compareAndExchange String");
172             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
173             assertEquals("foo", x, "success compareAndExchange String value");
174         }
175 
176         {
177             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(recv, "bar", "baz");
178             assertEquals(r, "foo", "failing compareAndExchange String");
179             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
180             assertEquals("foo", x, "failing compareAndExchange String value");
181         }
182 
183         {
184             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, "foo", "bar");
185             assertEquals(r, "foo", "success compareAndExchangeAcquire String");
186             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
187             assertEquals("bar", x, "success compareAndExchangeAcquire String value");
188         }
189 
190         {
191             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(recv, "foo", "baz");
192             assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
193             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
194             assertEquals("bar", x, "failing compareAndExchangeAcquire String value");
195         }
196 
197         {
198             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, "bar", "foo");
199             assertEquals(r, "bar", "success compareAndExchangeRelease String");
200             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
201             assertEquals("foo", x, "success compareAndExchangeRelease String value");
202         }
203 
204         {
205             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(recv, "bar", "baz");
206             assertEquals(r, "foo", "failing compareAndExchangeRelease String");
207             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
208             assertEquals("foo", x, "failing compareAndExchangeRelease String value");
209         }
210 
211         {
212             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
213             boolean success = false;
214             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
215                 success = (boolean) mh.invokeExact(recv, "foo", "bar");
216                 if (!success) weakDelay();
217             }
218             assertEquals(success, true, "success weakCompareAndSetPlain String");
219             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
220             assertEquals("bar", x, "success weakCompareAndSetPlain String value");
221         }
222 
223         {
224             boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(recv, "foo", "baz");
225             assertEquals(success, false, "failing weakCompareAndSetPlain String");
226             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
227             assertEquals("bar", x, "failing weakCompareAndSetPlain String value");
228         }
229 
230         {
231             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
232             boolean success = false;
233             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
234                 success = (boolean) mh.invokeExact(recv, "bar", "foo");
235                 if (!success) weakDelay();
236             }
237             assertEquals(success, true, "success weakCompareAndSetAcquire String");
238             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
239             assertEquals("foo", x, "success weakCompareAndSetAcquire String");
240         }
241 
242         {
243             boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(recv, "bar", "baz");
244             assertEquals(success, false, "failing weakCompareAndSetAcquire String");
245             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
246             assertEquals("foo", x, "failing weakCompareAndSetAcquire String value");
247         }
248 
249         {
250             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
251             boolean success = false;
252             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
253                 success = (boolean) mh.invokeExact(recv, "foo", "bar");
254                 if (!success) weakDelay();
255             }
256             assertEquals(success, true, "success weakCompareAndSetRelease String");
257             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
258             assertEquals("bar", x, "success weakCompareAndSetRelease String");
259         }
260 
261         {
262             boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(recv, "foo", "baz");
263             assertEquals(success, false, "failing weakCompareAndSetRelease String");
264             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
265             assertEquals("bar", x, "failing weakCompareAndSetRelease String value");
266         }
267 
268         {
269             boolean success = false;
270             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
271             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
272                 success = (boolean) mh.invokeExact(recv, "bar", "foo");
273                 if (!success) weakDelay();
274             }
275             assertEquals(success, true, "success weakCompareAndSet String");
276             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
277             assertEquals("foo", x, "success weakCompareAndSet String");
278         }
279 
280         {
281             boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(recv, "bar", "baz");
282             assertEquals(success, false, "failing weakCompareAndSet String");
283             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
284             assertEquals("foo", x, "failing weakCompareAndSet String value");
285         }
286 
287         // Compare set and get
288         {
289             String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "bar");
290             assertEquals("foo", o, "getAndSet String");
291             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
292             assertEquals("bar", x, "getAndSet String value");
293         }
294 
295 
296     }
297 
298     static void testInstanceFieldUnsupported(VarHandleTestMethodHandleAccessString recv, Handles hs) throws Throwable {
299 
300         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
301             checkUOE(am, () -> {
302                 String r = (String) hs.get(am).invokeExact(recv, "foo");
303             });
304         }
305 
306         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
307             checkUOE(am, () -> {
308                 String r = (String) hs.get(am).invokeExact(recv, "foo");
309             });
310         }
311     }
312 
313 
314     static void testStaticField(Handles hs) throws Throwable {
315         // Plain
316         {
317             hs.get(TestAccessMode.SET).invokeExact("foo");
318             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
319             assertEquals("foo", x, "set String value");
320         }
321 
322 
323         // Volatile
324         {
325             hs.get(TestAccessMode.SET_VOLATILE).invokeExact("bar");
326             String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact();
327             assertEquals("bar", x, "setVolatile String value");
328         }
329 
330         // Lazy
331         {
332             hs.get(TestAccessMode.SET_RELEASE).invokeExact("foo");
333             String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact();
334             assertEquals("foo", x, "setRelease String value");
335         }
336 
337         // Opaque
338         {
339             hs.get(TestAccessMode.SET_OPAQUE).invokeExact("bar");
340             String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact();
341             assertEquals("bar", x, "setOpaque String value");
342         }
343 
344         hs.get(TestAccessMode.SET).invokeExact("foo");
345 
346         // Compare
347         {
348             boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact("foo", "bar");
349             assertEquals(r, true, "success compareAndSet String");
350             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
351             assertEquals("bar", x, "success compareAndSet String value");
352         }
353 
354         {
355             boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact("foo", "baz");
356             assertEquals(r, false, "failing compareAndSet String");
357             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
358             assertEquals("bar", x, "failing compareAndSet String value");
359         }
360 
361         {
362             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact("bar", "foo");
363             assertEquals(r, "bar", "success compareAndExchange String");
364             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
365             assertEquals("foo", x, "success compareAndExchange String value");
366         }
367 
368         {
369             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact("bar", "baz");
370             assertEquals(r, "foo", "failing compareAndExchange String");
371             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
372             assertEquals("foo", x, "failing compareAndExchange String value");
373         }
374 
375         {
376             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact("foo", "bar");
377             assertEquals(r, "foo", "success compareAndExchangeAcquire String");
378             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
379             assertEquals("bar", x, "success compareAndExchangeAcquire String value");
380         }
381 
382         {
383             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact("foo", "baz");
384             assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
385             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
386             assertEquals("bar", x, "failing compareAndExchangeAcquire String value");
387         }
388 
389         {
390             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact("bar", "foo");
391             assertEquals(r, "bar", "success compareAndExchangeRelease String");
392             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
393             assertEquals("foo", x, "success compareAndExchangeRelease String value");
394         }
395 
396         {
397             String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact("bar", "baz");
398             assertEquals(r, "foo", "failing compareAndExchangeRelease String");
399             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
400             assertEquals("foo", x, "failing compareAndExchangeRelease String value");
401         }
402 
403         {
404             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
405             boolean success = false;
406             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
407                 success = (boolean) mh.invokeExact("foo", "bar");
408                 if (!success) weakDelay();
409             }
410             assertEquals(success, true, "success weakCompareAndSetPlain String");
411             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
412             assertEquals("bar", x, "success weakCompareAndSetPlain String value");
413         }
414 
415         {
416             boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact("foo", "baz");
417             assertEquals(success, false, "failing weakCompareAndSetPlain String");
418             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
419             assertEquals("bar", x, "failing weakCompareAndSetPlain String value");
420         }
421 
422         {
423             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
424             boolean success = false;
425             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
426                 success = (boolean) mh.invokeExact("bar", "foo");
427                 if (!success) weakDelay();
428             }
429             assertEquals(success, true, "success weakCompareAndSetAcquire String");
430             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
431             assertEquals("foo", x, "success weakCompareAndSetAcquire String");
432         }
433 
434         {
435             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
436             boolean success = (boolean) mh.invokeExact("bar", "baz");
437             assertEquals(success, false, "failing weakCompareAndSetAcquire String");
438             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
439             assertEquals("foo", x, "failing weakCompareAndSetAcquire String value");
440         }
441 
442         {
443             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
444             boolean success = false;
445             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
446                 success = (boolean) mh.invokeExact("foo", "bar");
447                 if (!success) weakDelay();
448             }
449             assertEquals(success, true, "success weakCompareAndSetRelease String");
450             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
451             assertEquals("bar", x, "success weakCompareAndSetRelease String");
452         }
453 
454         {
455             boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "baz");
456             assertEquals(success, false, "failing weakCompareAndSetRelease String");
457             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
458             assertEquals("bar", x, "failing weakCompareAndSetRelease String value");
459         }
460 
461         {
462             MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
463             boolean success = false;
464             for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
465                 success = (boolean) mh.invokeExact("bar", "foo");
466                 if (!success) weakDelay();
467             }
468             assertEquals(success, true, "success weakCompareAndSet String");
469             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
470             assertEquals("foo", x, "success weakCompareAndSet String");
471         }
472 
473         {
474             boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact("bar", "baz");
475             assertEquals(success, false, "failing weakCompareAndSet String");
476             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
477             assertEquals("foo", x, "failing weakCompareAndSetRe String value");
478         }
479 
480         // Compare set and get
481         {
482             hs.get(TestAccessMode.SET).invokeExact("foo");
483 
484             String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact("bar");
485             assertEquals("foo", o, "getAndSet String");
486             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
487             assertEquals("bar", x, "getAndSet String value");
488         }
489 
490         // Compare set and get
491         {
492             hs.get(TestAccessMode.SET).invokeExact("foo");
493 
494             String o = (String) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact("bar");
495             assertEquals("foo", o, "getAndSetAcquire String");
496             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
497             assertEquals("bar", x, "getAndSetAcquire String value");
498         }
499 
500         // Compare set and get
501         {
502             hs.get(TestAccessMode.SET).invokeExact("foo");
503 
504             String o = (String) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact("bar");
505             assertEquals("foo", o, "getAndSetRelease String");
506             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
507             assertEquals("bar", x, "getAndSetRelease String value");
508         }
509 
510 
511     }
512 
513     static void testStaticFieldUnsupported(Handles hs) throws Throwable {
514 
515         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
516             checkUOE(am, () -> {
517                 String r = (String) hs.get(am).invokeExact("foo");
518             });
519         }
520 
521         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
522             checkUOE(am, () -> {
523                 String r = (String) hs.get(am).invokeExact("foo");
524             });
525         }
526     }
527 
528 
529     static void testArray(Handles hs) throws Throwable {
530         String[] array = new String[10];
531 
532         for (int i = 0; i < array.length; i++) {
533             // Plain
534             {
535                 hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
536                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
537                 assertEquals("foo", x, "get String value");
538             }
539 
540 
541             // Volatile
542             {
543                 hs.get(TestAccessMode.SET_VOLATILE).invokeExact(array, i, "bar");
544                 String x = (String) hs.get(TestAccessMode.GET_VOLATILE).invokeExact(array, i);
545                 assertEquals("bar", x, "setVolatile String value");
546             }
547 
548             // Lazy
549             {
550                 hs.get(TestAccessMode.SET_RELEASE).invokeExact(array, i, "foo");
551                 String x = (String) hs.get(TestAccessMode.GET_ACQUIRE).invokeExact(array, i);
552                 assertEquals("foo", x, "setRelease String value");
553             }
554 
555             // Opaque
556             {
557                 hs.get(TestAccessMode.SET_OPAQUE).invokeExact(array, i, "bar");
558                 String x = (String) hs.get(TestAccessMode.GET_OPAQUE).invokeExact(array, i);
559                 assertEquals("bar", x, "setOpaque String value");
560             }
561 
562             hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
563 
564             // Compare
565             {
566                 boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, "foo", "bar");
567                 assertEquals(r, true, "success compareAndSet String");
568                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
569                 assertEquals("bar", x, "success compareAndSet String value");
570             }
571 
572             {
573                 boolean r = (boolean) hs.get(TestAccessMode.COMPARE_AND_SET).invokeExact(array, i, "foo", "baz");
574                 assertEquals(r, false, "failing compareAndSet String");
575                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
576                 assertEquals("bar", x, "failing compareAndSet String value");
577             }
578 
579             {
580                 String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, "bar", "foo");
581                 assertEquals(r, "bar", "success compareAndExchange String");
582                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
583                 assertEquals("foo", x, "success compareAndExchange String value");
584             }
585 
586             {
587                 String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE).invokeExact(array, i, "bar", "baz");
588                 assertEquals(r, "foo", "failing compareAndExchange String");
589                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
590                 assertEquals("foo", x, "failing compareAndExchange String value");
591             }
592 
593             {
594                 String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, "foo", "bar");
595                 assertEquals(r, "foo", "success compareAndExchangeAcquire String");
596                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
597                 assertEquals("bar", x, "success compareAndExchangeAcquire String value");
598             }
599 
600             {
601                 String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_ACQUIRE).invokeExact(array, i, "foo", "baz");
602                 assertEquals(r, "bar", "failing compareAndExchangeAcquire String");
603                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
604                 assertEquals("bar", x, "failing compareAndExchangeAcquire String value");
605             }
606 
607             {
608                 String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, "bar", "foo");
609                 assertEquals(r, "bar", "success compareAndExchangeRelease String");
610                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
611                 assertEquals("foo", x, "success compareAndExchangeRelease String value");
612             }
613 
614             {
615                 String r = (String) hs.get(TestAccessMode.COMPARE_AND_EXCHANGE_RELEASE).invokeExact(array, i, "bar", "baz");
616                 assertEquals(r, "foo", "failing compareAndExchangeRelease String");
617                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
618                 assertEquals("foo", x, "failing compareAndExchangeRelease String value");
619             }
620 
621             {
622                 MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN);
623                 boolean success = false;
624                 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
625                     success = (boolean) mh.invokeExact(array, i, "foo", "bar");
626                     if (!success) weakDelay();
627                 }
628                 assertEquals(success, true, "success weakCompareAndSetPlain String");
629                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
630                 assertEquals("bar", x, "success weakCompareAndSetPlain String value");
631             }
632 
633             {
634                 boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_PLAIN).invokeExact(array, i, "foo", "baz");
635                 assertEquals(success, false, "failing weakCompareAndSetPlain String");
636                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
637                 assertEquals("bar", x, "failing weakCompareAndSetPlain String value");
638             }
639 
640             {
641                 MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE);
642                 boolean success = false;
643                 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
644                     success = (boolean) mh.invokeExact(array, i, "bar", "foo");
645                     if (!success) weakDelay();
646                 }
647                 assertEquals(success, true, "success weakCompareAndSetAcquire String");
648                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
649                 assertEquals("foo", x, "success weakCompareAndSetAcquire String");
650             }
651 
652             {
653                 boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "bar", "baz");
654                 assertEquals(success, false, "failing weakCompareAndSetAcquire String");
655                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
656                 assertEquals("foo", x, "failing weakCompareAndSetAcquire String value");
657             }
658 
659             {
660                 MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE);
661                 boolean success = false;
662                 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
663                     success = (boolean) mh.invokeExact(array, i, "foo", "bar");
664                     if (!success) weakDelay();
665                 }
666                 assertEquals(success, true, "success weakCompareAndSetRelease String");
667                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
668                 assertEquals("bar", x, "success weakCompareAndSetRelease String");
669             }
670 
671             {
672                 boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_ACQUIRE).invokeExact(array, i, "foo", "baz");
673                 assertEquals(success, false, "failing weakCompareAndSetAcquire String");
674                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
675                 assertEquals("bar", x, "failing weakCompareAndSetAcquire String value");
676             }
677 
678             {
679                 MethodHandle mh = hs.get(TestAccessMode.WEAK_COMPARE_AND_SET);
680                 boolean success = false;
681                 for (int c = 0; c < WEAK_ATTEMPTS && !success; c++) {
682                     success = (boolean) mh.invokeExact(array, i, "bar", "foo");
683                     if (!success) weakDelay();
684                 }
685                 assertEquals(success, true, "success weakCompareAndSet String");
686                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
687                 assertEquals("foo", x, "success weakCompareAndSet String");
688             }
689 
690             {
691                 boolean success = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET).invokeExact(array, i, "bar", "baz");
692                 assertEquals(success, false, "failing weakCompareAndSet String");
693                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
694                 assertEquals("foo", x, "failing weakCompareAndSet String value");
695             }
696 
697             // Compare set and get
698             {
699                 hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
700 
701                 String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "bar");
702                 assertEquals("foo", o, "getAndSet String");
703                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
704                 assertEquals("bar", x, "getAndSet String value");
705             }
706 
707             {
708                 hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
709 
710                 String o = (String) hs.get(TestAccessMode.GET_AND_SET_ACQUIRE).invokeExact(array, i, "bar");
711                 assertEquals("foo", o, "getAndSetAcquire String");
712                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
713                 assertEquals("bar", x, "getAndSetAcquire String value");
714             }
715 
716             {
717                 hs.get(TestAccessMode.SET).invokeExact(array, i, "foo");
718 
719                 String o = (String) hs.get(TestAccessMode.GET_AND_SET_RELEASE).invokeExact(array, i, "bar");
720                 assertEquals("foo", o, "getAndSetRelease String");
721                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
722                 assertEquals("bar", x, "getAndSetRelease String value");
723             }
724 
725 
726         }
727     }
728 
729     static void testArrayUnsupported(Handles hs) throws Throwable {
730         String[] array = new String[10];
731 
732         final int i = 0;
733 
734         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_ADD)) {
735             checkUOE(am, () -> {
736                 String o = (String) hs.get(am).invokeExact(array, i, "foo");
737             });
738         }
739 
740         for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_BITWISE)) {
741             checkUOE(am, () -> {
742                 String o = (String) hs.get(am).invokeExact(array, i, "foo");
743             });
744         }
745     }
746 
747     static void testArrayIndexOutOfBounds(Handles hs) throws Throwable {
748         String[] array = new String[10];
749 
750         for (int i : new int[]{-1, Integer.MIN_VALUE, 10, 11, Integer.MAX_VALUE}) {
751             final int ci = i;
752 
753             for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET)) {
754                 checkAIOOBE(am, () -> {
755                     String x = (String) hs.get(am).invokeExact(array, ci);
756                 });
757             }
758 
759             for (TestAccessMode am : testAccessModesOfType(TestAccessType.SET)) {
760                 checkAIOOBE(am, () -> {
761                     hs.get(am).invokeExact(array, ci, "foo");
762                 });
763             }
764 
765             for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_SET)) {
766                 checkAIOOBE(am, () -> {
767                     boolean r = (boolean) hs.get(am).invokeExact(array, ci, "foo", "bar");
768                 });
769             }
770 
771             for (TestAccessMode am : testAccessModesOfType(TestAccessType.COMPARE_AND_EXCHANGE)) {
772                 checkAIOOBE(am, () -> {
773                     String r = (String) hs.get(am).invokeExact(array, ci, "bar", "foo");
774                 });
775             }
776 
777             for (TestAccessMode am : testAccessModesOfType(TestAccessType.GET_AND_SET)) {
778                 checkAIOOBE(am, () -> {
779                     String o = (String) hs.get(am).invokeExact(array, ci, "foo");
780                 });
781             }
782 
783 
784         }
785     }
786 }
787