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