1 /*
2  * Copyright (c) 2016, 2018, 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  * @summary tests on constant folding of unsafe get operations from stable arrays
27  * @library /test/lib
28  * @build sun.hotspot.WhiteBox
29  * @requires vm.flavor == "server" & !vm.emulatedClient
30  *
31  * @modules java.base/jdk.internal.vm.annotation
32  *          java.base/jdk.internal.misc
33  * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
34  *
35  * @run main/bootclasspath/othervm -XX:+UnlockDiagnosticVMOptions
36  *                   -Xbatch -XX:-TieredCompilation
37  *                   -XX:+FoldStableValues
38  *                   -XX:+WhiteBoxAPI
39  *                   -XX:CompileCommand=dontinline,*Test::test*
40  *                   compiler.unsafe.UnsafeGetStableArrayElement
41  */
42 
43 package compiler.unsafe;
44 
45 import jdk.internal.misc.Unsafe;
46 import jdk.internal.vm.annotation.Stable;
47 import jdk.test.lib.Platform;
48 
49 import java.util.concurrent.Callable;
50 
51 import static jdk.internal.misc.Unsafe.*;
52 import static jdk.test.lib.Asserts.assertEQ;
53 import static jdk.test.lib.Asserts.assertNE;
54 
55 import sun.hotspot.code.Compiler;
56 
57 public class UnsafeGetStableArrayElement {
58     @Stable static final boolean[] STABLE_BOOLEAN_ARRAY = new boolean[16];
59     @Stable static final    byte[]    STABLE_BYTE_ARRAY = new    byte[16];
60     @Stable static final   short[]   STABLE_SHORT_ARRAY = new   short[8];
61     @Stable static final    char[]    STABLE_CHAR_ARRAY = new    char[8];
62     @Stable static final     int[]     STABLE_INT_ARRAY = new     int[4];
63     @Stable static final    long[]    STABLE_LONG_ARRAY = new    long[2];
64     @Stable static final   float[]   STABLE_FLOAT_ARRAY = new   float[4];
65     @Stable static final  double[]  STABLE_DOUBLE_ARRAY = new  double[2];
66     @Stable static final  Object[]  STABLE_OBJECT_ARRAY = new  Object[4];
67 
68     static {
Setter.reset()69         Setter.reset();
70     }
71     static final Unsafe U = Unsafe.getUnsafe();
72 
73     static class Setter {
setZ(boolean defaultVal)74         private static void setZ(boolean defaultVal) { STABLE_BOOLEAN_ARRAY[0] = defaultVal ? false :                true; }
setB(boolean defaultVal)75         private static void setB(boolean defaultVal) { STABLE_BYTE_ARRAY[0]    = defaultVal ?     0 :      Byte.MAX_VALUE; }
setS(boolean defaultVal)76         private static void setS(boolean defaultVal) { STABLE_SHORT_ARRAY[0]   = defaultVal ?     0 :     Short.MAX_VALUE; }
setC(boolean defaultVal)77         private static void setC(boolean defaultVal) { STABLE_CHAR_ARRAY[0]    = defaultVal ?     0 : Character.MAX_VALUE; }
setI(boolean defaultVal)78         private static void setI(boolean defaultVal) { STABLE_INT_ARRAY[0]     = defaultVal ?     0 :   Integer.MAX_VALUE; }
setJ(boolean defaultVal)79         private static void setJ(boolean defaultVal) { STABLE_LONG_ARRAY[0]    = defaultVal ?     0 :      Long.MAX_VALUE; }
setF(boolean defaultVal)80         private static void setF(boolean defaultVal) { STABLE_FLOAT_ARRAY[0]   = defaultVal ?     0 :     Float.MAX_VALUE; }
setD(boolean defaultVal)81         private static void setD(boolean defaultVal) { STABLE_DOUBLE_ARRAY[0]  = defaultVal ?     0 :    Double.MAX_VALUE; }
setL(boolean defaultVal)82         private static void setL(boolean defaultVal) { STABLE_OBJECT_ARRAY[0]  = defaultVal ?  null :        new Object(); }
83 
reset()84         static void reset() {
85             setZ(false);
86             setB(false);
87             setS(false);
88             setC(false);
89             setI(false);
90             setJ(false);
91             setF(false);
92             setD(false);
93             setL(false);
94         }
95     }
96 
97     static class Test {
changeZ()98         static void changeZ() { Setter.setZ(true); }
changeB()99         static void changeB() { Setter.setB(true); }
changeS()100         static void changeS() { Setter.setS(true); }
changeC()101         static void changeC() { Setter.setC(true); }
changeI()102         static void changeI() { Setter.setI(true); }
changeJ()103         static void changeJ() { Setter.setJ(true); }
changeF()104         static void changeF() { Setter.setF(true); }
changeD()105         static void changeD() { Setter.setD(true); }
changeL()106         static void changeL() { Setter.setL(true); }
107 
testZ_Z()108         static boolean testZ_Z() { return U.getBoolean(STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
testZ_B()109         static byte    testZ_B() { return U.getByte(   STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
testZ_S()110         static short   testZ_S() { return U.getShort(  STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
testZ_C()111         static char    testZ_C() { return U.getChar(   STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
testZ_I()112         static int     testZ_I() { return U.getInt(    STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
testZ_J()113         static long    testZ_J() { return U.getLong(   STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
testZ_F()114         static float   testZ_F() { return U.getFloat(  STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
testZ_D()115         static double  testZ_D() { return U.getDouble( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
116 
testB_Z()117         static boolean testB_Z() { return U.getBoolean(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
testB_B()118         static byte    testB_B() { return U.getByte(   STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
testB_S()119         static short   testB_S() { return U.getShort(  STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
testB_C()120         static char    testB_C() { return U.getChar(   STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
testB_I()121         static int     testB_I() { return U.getInt(    STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
testB_J()122         static long    testB_J() { return U.getLong(   STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
testB_F()123         static float   testB_F() { return U.getFloat(  STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
testB_D()124         static double  testB_D() { return U.getDouble( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
125 
testS_Z()126         static boolean testS_Z() { return U.getBoolean(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
testS_B()127         static byte    testS_B() { return U.getByte(   STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
testS_S()128         static short   testS_S() { return U.getShort(  STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
testS_C()129         static char    testS_C() { return U.getChar(   STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
testS_I()130         static int     testS_I() { return U.getInt(    STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
testS_J()131         static long    testS_J() { return U.getLong(   STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
testS_F()132         static float   testS_F() { return U.getFloat(  STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
testS_D()133         static double  testS_D() { return U.getDouble( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
134 
testC_Z()135         static boolean testC_Z() { return U.getBoolean(STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
testC_B()136         static byte    testC_B() { return U.getByte(   STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
testC_S()137         static short   testC_S() { return U.getShort(  STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
testC_C()138         static char    testC_C() { return U.getChar(   STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
testC_I()139         static int     testC_I() { return U.getInt(    STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
testC_J()140         static long    testC_J() { return U.getLong(   STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
testC_F()141         static float   testC_F() { return U.getFloat(  STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
testC_D()142         static double  testC_D() { return U.getDouble( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
143 
testI_Z()144         static boolean testI_Z() { return U.getBoolean(STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
testI_B()145         static byte    testI_B() { return U.getByte(   STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
testI_S()146         static short   testI_S() { return U.getShort(  STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
testI_C()147         static char    testI_C() { return U.getChar(   STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
testI_I()148         static int     testI_I() { return U.getInt(    STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
testI_J()149         static long    testI_J() { return U.getLong(   STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
testI_F()150         static float   testI_F() { return U.getFloat(  STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
testI_D()151         static double  testI_D() { return U.getDouble( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
152 
testJ_Z()153         static boolean testJ_Z() { return U.getBoolean(STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
testJ_B()154         static byte    testJ_B() { return U.getByte(   STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
testJ_S()155         static short   testJ_S() { return U.getShort(  STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
testJ_C()156         static char    testJ_C() { return U.getChar(   STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
testJ_I()157         static int     testJ_I() { return U.getInt(    STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
testJ_J()158         static long    testJ_J() { return U.getLong(   STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
testJ_F()159         static float   testJ_F() { return U.getFloat(  STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
testJ_D()160         static double  testJ_D() { return U.getDouble( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
161 
testF_Z()162         static boolean testF_Z() { return U.getBoolean(STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
testF_B()163         static byte    testF_B() { return U.getByte(   STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
testF_S()164         static short   testF_S() { return U.getShort(  STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
testF_C()165         static char    testF_C() { return U.getChar(   STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
testF_I()166         static int     testF_I() { return U.getInt(    STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
testF_J()167         static long    testF_J() { return U.getLong(   STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
testF_F()168         static float   testF_F() { return U.getFloat(  STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
testF_D()169         static double  testF_D() { return U.getDouble( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
170 
testD_Z()171         static boolean testD_Z() { return U.getBoolean(STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
testD_B()172         static byte    testD_B() { return U.getByte(   STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
testD_S()173         static short   testD_S() { return U.getShort(  STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
testD_C()174         static char    testD_C() { return U.getChar(   STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
testD_I()175         static int     testD_I() { return U.getInt(    STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
testD_J()176         static long    testD_J() { return U.getLong(   STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
testD_F()177         static float   testD_F() { return U.getFloat(  STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
testD_D()178         static double  testD_D() { return U.getDouble( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
179 
testL_L()180         static Object  testL_L() { return U.getReference( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
testL_Z()181         static boolean testL_Z() { return U.getBoolean(STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET);    }
testL_B()182         static byte    testL_B() { return U.getByte(   STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET);    }
testL_S()183         static short   testL_S() { return U.getShort(  STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET);    }
testL_C()184         static char    testL_C() { return U.getChar(   STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET);    }
testL_I()185         static int     testL_I() { return U.getInt(    STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET);    }
testL_J()186         static long    testL_J() { return U.getLong(   STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET);    }
testL_F()187         static float   testL_F() { return U.getFloat(  STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET);    }
testL_D()188         static double  testL_D() { return U.getDouble( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET);    }
189 
testS_U()190         static short   testS_U() { return U.getShortUnaligned(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET + 1); }
testC_U()191         static char    testC_U() { return U.getCharUnaligned(  STABLE_CHAR_ARRAY,  ARRAY_CHAR_BASE_OFFSET + 1); }
testI_U()192         static int     testI_U() { return U.getIntUnaligned(    STABLE_INT_ARRAY,   ARRAY_INT_BASE_OFFSET + 1); }
testJ_U()193         static long    testJ_U() { return U.getLongUnaligned(  STABLE_LONG_ARRAY,  ARRAY_LONG_BASE_OFFSET + 1); }
194     }
195 
run(Callable<?> c)196     static void run(Callable<?> c) throws Exception {
197         run(c, null, null);
198     }
199 
run(Callable<?> c, Runnable sameResultAction, Runnable changeResultAction)200     static void run(Callable<?> c, Runnable sameResultAction, Runnable changeResultAction) throws Exception {
201         Object first = c.call();
202 
203         // Trigger compilation.
204         for (int i = 0; i < 20_000; i++) {
205             // Don't compare results here, since most of Test::testL_* results vary across iterations (due to GC).
206             c.call();
207         }
208 
209         if (sameResultAction != null) {
210             sameResultAction.run();
211             assertEQ(first, c.call());
212         }
213 
214         if (changeResultAction != null) {
215             changeResultAction.run();
216             assertNE(first, c.call());
217             assertEQ(c.call(), c.call());
218         }
219     }
220 
testMatched(Callable<?> c, Runnable setDefaultAction)221     static void testMatched(Callable<?> c, Runnable setDefaultAction) throws Exception {
222         run(c, setDefaultAction, null);
223         Setter.reset();
224     }
225 
testMismatched(Callable<?> c, Runnable setDefaultAction)226     static void testMismatched(Callable<?> c, Runnable setDefaultAction) throws Exception {
227         testMismatched(c, setDefaultAction, false);
228     }
229 
testMismatched(Callable<?> c, Runnable setDefaultAction, boolean objectArray)230     static void testMismatched(Callable<?> c, Runnable setDefaultAction, boolean objectArray) throws Exception {
231         if (Compiler.isGraalEnabled() && !objectArray) {
232             // Graal will constant fold mismatched reads from primitive stable arrays
233             run(c, setDefaultAction, null);
234         } else {
235             run(c, null, setDefaultAction);
236         }
237         Setter.reset();
238     }
239 
testUnsafeAccess()240     static void testUnsafeAccess() throws Exception {
241         // boolean[], aligned accesses
242         testMatched(   Test::testZ_Z, Test::changeZ);
243         testMismatched(Test::testZ_B, Test::changeZ);
244         testMismatched(Test::testZ_S, Test::changeZ);
245         testMismatched(Test::testZ_C, Test::changeZ);
246         testMismatched(Test::testZ_I, Test::changeZ);
247         testMismatched(Test::testZ_J, Test::changeZ);
248         testMismatched(Test::testZ_F, Test::changeZ);
249         testMismatched(Test::testZ_D, Test::changeZ);
250 
251         // byte[], aligned accesses
252         testMismatched(Test::testB_Z, Test::changeB);
253         testMatched(   Test::testB_B, Test::changeB);
254         testMismatched(Test::testB_S, Test::changeB);
255         testMismatched(Test::testB_C, Test::changeB);
256         testMismatched(Test::testB_I, Test::changeB);
257         testMismatched(Test::testB_J, Test::changeB);
258         testMismatched(Test::testB_F, Test::changeB);
259         testMismatched(Test::testB_D, Test::changeB);
260 
261         // short[], aligned accesses
262         testMismatched(Test::testS_Z, Test::changeS);
263         testMismatched(Test::testS_B, Test::changeS);
264         testMatched(   Test::testS_S, Test::changeS);
265         testMismatched(Test::testS_C, Test::changeS);
266         testMismatched(Test::testS_I, Test::changeS);
267         testMismatched(Test::testS_J, Test::changeS);
268         testMismatched(Test::testS_F, Test::changeS);
269         testMismatched(Test::testS_D, Test::changeS);
270 
271         // char[], aligned accesses
272         testMismatched(Test::testC_Z, Test::changeC);
273         testMismatched(Test::testC_B, Test::changeC);
274         testMismatched(Test::testC_S, Test::changeC);
275         testMatched(   Test::testC_C, Test::changeC);
276         testMismatched(Test::testC_I, Test::changeC);
277         testMismatched(Test::testC_J, Test::changeC);
278         testMismatched(Test::testC_F, Test::changeC);
279         testMismatched(Test::testC_D, Test::changeC);
280 
281         // int[], aligned accesses
282         testMismatched(Test::testI_Z, Test::changeI);
283         testMismatched(Test::testI_B, Test::changeI);
284         testMismatched(Test::testI_S, Test::changeI);
285         testMismatched(Test::testI_C, Test::changeI);
286         testMatched(   Test::testI_I, Test::changeI);
287         testMismatched(Test::testI_J, Test::changeI);
288         testMismatched(Test::testI_F, Test::changeI);
289         testMismatched(Test::testI_D, Test::changeI);
290 
291         // long[], aligned accesses
292         testMismatched(Test::testJ_Z, Test::changeJ);
293         testMismatched(Test::testJ_B, Test::changeJ);
294         testMismatched(Test::testJ_S, Test::changeJ);
295         testMismatched(Test::testJ_C, Test::changeJ);
296         testMismatched(Test::testJ_I, Test::changeJ);
297         testMatched(   Test::testJ_J, Test::changeJ);
298         testMismatched(Test::testJ_F, Test::changeJ);
299         testMismatched(Test::testJ_D, Test::changeJ);
300 
301         // float[], aligned accesses
302         testMismatched(Test::testF_Z, Test::changeF);
303         testMismatched(Test::testF_B, Test::changeF);
304         testMismatched(Test::testF_S, Test::changeF);
305         testMismatched(Test::testF_C, Test::changeF);
306         testMismatched(Test::testF_I, Test::changeF);
307         testMismatched(Test::testF_J, Test::changeF);
308         testMatched(   Test::testF_F, Test::changeF);
309         testMismatched(Test::testF_D, Test::changeF);
310 
311         // double[], aligned accesses
312         testMismatched(Test::testD_Z, Test::changeD);
313         testMismatched(Test::testD_B, Test::changeD);
314         testMismatched(Test::testD_S, Test::changeD);
315         testMismatched(Test::testD_C, Test::changeD);
316         testMismatched(Test::testD_I, Test::changeD);
317         testMismatched(Test::testD_J, Test::changeD);
318         testMismatched(Test::testD_F, Test::changeD);
319         testMatched(   Test::testD_D, Test::changeD);
320 
321         // Object[], aligned accesses
322         testMismatched(Test::testL_J, Test::changeL, true); // long & double are always as large as an OOP
323         testMismatched(Test::testL_D, Test::changeL, true);
324         testMatched(   Test::testL_L, Test::changeL);
325 
326         // Unaligned accesses
327         testMismatched(Test::testS_U, Test::changeS);
328         testMismatched(Test::testC_U, Test::changeC);
329         testMismatched(Test::testI_U, Test::changeI);
330         testMismatched(Test::testJ_U, Test::changeJ);
331 
332         // No way to reliably check the expected behavior:
333         //   (1) OOPs change during GC;
334         //   (2) there's no way to reliably change some part of an OOP (e.g., when reading a byte from it).
335         //
336         // Just trigger the compilation hoping to catch any problems with asserts.
337         run(Test::testL_B);
338         run(Test::testL_Z);
339         run(Test::testL_S);
340         run(Test::testL_C);
341         run(Test::testL_I);
342         run(Test::testL_F);
343     }
344 
main(String[] args)345     public static void main(String[] args) throws Exception {
346         if (!Platform.isServer() || Platform.isEmulatedClient()) {
347             throw new Error("TESTBUG: Not server mode");
348         }
349         testUnsafeAccess();
350         System.out.println("TEST PASSED");
351     }
352 }
353