1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import java.lang.reflect.Field; 18 import sun.misc.Unsafe; 19 20 public class Main { getUnsafe()21 private static Unsafe getUnsafe() throws NoSuchFieldException, IllegalAccessException { 22 Class<?> unsafeClass = Unsafe.class; 23 Field f = unsafeClass.getDeclaredField("theUnsafe"); 24 f.setAccessible(true); 25 return (Unsafe) f.get(null); 26 } 27 28 private static Unsafe unsafe; 29 assertEquals(int expected, int actual)30 static void assertEquals(int expected, int actual) { 31 if (expected != actual) { 32 throw new Error("Expected " + expected + ", got " + actual); 33 } 34 } 35 main(String[] args)36 public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 37 unsafe = getUnsafe(); 38 testPutZero(); 39 testPutFixedOffset(); 40 assertEquals(0, testGet()); 41 assertEquals(42, testGetFar()); 42 testGetAndPutAbsoluteAddress(); 43 } 44 45 /// CHECK-START-ARM64: void Main.testPutZero() disassembly (after) 46 /// CHECK: str wzr, [x{{[0-9]+}}, #12] testPutZero()47 private static void testPutZero() { 48 int[] object = new int[42]; 49 unsafe.putInt(object, unsafe.arrayBaseOffset(int[].class), 0); 50 } 51 52 /// CHECK-START-ARM64: void Main.testPutFixedOffset() disassembly (after) 53 /// CHECK: stur w{{[0-9]+}}, [x{{[0-9]+}}, #38] testPutFixedOffset()54 private static void testPutFixedOffset() { 55 int[] object = new int[42]; 56 unsafe.putInt(object, 38, 12); 57 } 58 59 /// CHECK-START-ARM64: int Main.testGet() disassembly (after) 60 /// CHECK: ldur w{{[0-9]+}}, [x{{[0-9]+}}, #38] testGet()61 private static int testGet() { 62 int[] object = new int[42]; 63 return unsafe.getInt(object, 38); 64 } 65 testGetFar()66 private static int testGetFar() { 67 int offset = 32 * 1024; 68 int arraySize = offset / 4; 69 int[] object = new int[arraySize]; 70 unsafe.putInt(object, offset, 42); 71 return unsafe.getInt(object, offset); 72 } 73 74 /// CHECK-START: int Main.testArrayBaseOffsetObject() instruction_simplifier (after) 75 /// CHECK: IntConstant 12 testArrayBaseOffsetObject()76 private static int testArrayBaseOffsetObject() { 77 return unsafe.arrayBaseOffset(Object[].class); 78 } 79 80 /// CHECK-START: int Main.testArrayBaseOffsetInt() instruction_simplifier (after) 81 /// CHECK: IntConstant 12 testArrayBaseOffsetInt()82 private static int testArrayBaseOffsetInt() { 83 return unsafe.arrayBaseOffset(int[].class); 84 } 85 86 /// CHECK-START: int Main.testArrayBaseOffsetDouble() instruction_simplifier (after) 87 /// CHECK: IntConstant 16 testArrayBaseOffsetDouble()88 private static int testArrayBaseOffsetDouble() { 89 return unsafe.arrayBaseOffset(double[].class); 90 } 91 testGetAndPutAbsoluteAddress()92 private static void testGetAndPutAbsoluteAddress() { 93 long address = 0; 94 try { 95 address = unsafe.allocateMemory(4); 96 $noinline$unsafePutAbsoluteInt(address, 0xDEADBEEF); 97 assertEquals(0xDEADBEEF, $noinline$unsafeGetAbsoluteInt(address)); 98 } finally { 99 if (address != 0) { 100 unsafe.freeMemory(address); 101 } 102 } 103 } 104 105 /// CHECK-START: void Main.$noinline$unsafePutAbsoluteInt(long, int) builder (after) 106 /// CHECK: InvokeVirtual intrinsic:UnsafePutAbsolute $noinline$unsafePutAbsoluteInt(long address, int value)107 private static void $noinline$unsafePutAbsoluteInt(long address, int value) { 108 unsafe.putInt(address, value); 109 } 110 111 /// CHECK-START: int Main.$noinline$unsafeGetAbsoluteInt(long) builder (after) 112 /// CHECK: InvokeVirtual intrinsic:UnsafeGetAbsolute $noinline$unsafeGetAbsoluteInt(long address)113 private static int $noinline$unsafeGetAbsoluteInt(long address) { 114 return unsafe.getInt(address); 115 } 116 } 117