1 /*
  2  * Copyright (c) 2019, 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 /*
 26  * @test
 27  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAddressHandle
 28  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=true -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAddressHandle
 29  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=false -Xverify:all TestAddressHandle
 30  * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAddressHandle
 31  */
 32 
 33 import java.lang.invoke.*;
 34 import java.nio.ByteOrder;
 35 import jdk.incubator.foreign.*;
 36 
 37 import org.testng.annotations.*;
 38 import static org.testng.Assert.*;
 39 
 40 public class TestAddressHandle {
 41 
 42     static final MethodHandle INT_TO_BOOL;
 43     static final MethodHandle BOOL_TO_INT;
 44     static final MethodHandle INT_TO_STRING;
 45     static final MethodHandle STRING_TO_INT;
 46 
 47     static {
 48         try {
 49             INT_TO_BOOL = MethodHandles.lookup().findStatic(TestAddressHandle.class, "intToBool",
 50                     MethodType.methodType(boolean.class, int.class));
 51             BOOL_TO_INT = MethodHandles.lookup().findStatic(TestAddressHandle.class, "boolToInt",
 52                     MethodType.methodType(int.class, boolean.class));
 53             INT_TO_STRING = MethodHandles.lookup().findStatic(TestAddressHandle.class, "intToString",
 54                     MethodType.methodType(String.class, int.class));
 55             STRING_TO_INT = MethodHandles.lookup().findStatic(TestAddressHandle.class, "stringToInt",
 56                     MethodType.methodType(int.class, String.class));
 57         } catch (Throwable ex) {
 58             throw new ExceptionInInitializerError(ex);
 59         }
 60     }
 61 
 62     @Test(dataProvider = "addressHandles")
 63     public void testAddressHandle(VarHandle addrHandle, int byteSize) {
 64         VarHandle longHandle = MemoryLayouts.JAVA_LONG.varHandle(long.class);
 65         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
 66             MemorySegment segment = MemorySegment.allocateNative(8, scope);
 67             MemorySegment target = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN ?
 68                     segment.asSlice(8 - byteSize) :
 69                     segment;
 70             longHandle.set(segment, 42L);
 71             MemoryAddress address = (MemoryAddress)addrHandle.get(target);
 72             assertEquals(address.toRawLongValue(), 42L);
 73             addrHandle.set(target, address.addOffset(1));
 74             long result = (long)longHandle.get(segment);
 75             assertEquals(43L, result);
 76         }
 77     }
 78 
 79     @Test(dataProvider = "addressHandles")
 80     public void testNull(VarHandle addrHandle, int byteSize) {
 81         VarHandle longHandle = MemoryLayouts.JAVA_LONG.varHandle(long.class);
 82         try (ResourceScope scope = ResourceScope.newConfinedScope()) {
 83             MemorySegment segment = MemorySegment.allocateNative(8, scope);
 84             longHandle.set(segment, 0L);
 85             MemoryAddress address = (MemoryAddress)addrHandle.get(segment);
 86             assertTrue(address == MemoryAddress.NULL);
 87         }
 88     }
 89 
 90     @Test(expectedExceptions = IllegalArgumentException.class)
 91     public void testBadAdaptFloat() {
 92         VarHandle floatHandle = MemoryLayouts.JAVA_FLOAT.varHandle(float.class);
 93         MemoryHandles.asAddressVarHandle(floatHandle);
 94     }
 95 
 96     @Test(expectedExceptions = IllegalArgumentException.class)
 97     public void testBadAdaptDouble() {
 98         VarHandle doubleHandle = MemoryLayouts.JAVA_DOUBLE.varHandle(double.class);
 99         MemoryHandles.asAddressVarHandle(doubleHandle);
100     }
101 
102     @Test(expectedExceptions = IllegalArgumentException.class)
103     public void testBadAdaptBoolean() {
104         VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class);
105         VarHandle boolHandle = MemoryHandles.filterValue(intHandle, BOOL_TO_INT, INT_TO_BOOL);
106         MemoryHandles.asAddressVarHandle(boolHandle);
107     }
108 
109     @Test(expectedExceptions = IllegalArgumentException.class)
110     public void testBadAdaptString() {
111         VarHandle intHandle = MemoryLayouts.JAVA_INT.varHandle(int.class);
112         VarHandle stringHandle = MemoryHandles.filterValue(intHandle, STRING_TO_INT, INT_TO_STRING);
113         MemoryHandles.asAddressVarHandle(stringHandle);
114     }
115 
116     @DataProvider(name = "addressHandles")
117     static Object[][] addressHandles() {
118         return new Object[][] {
119                 // long
120                 { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder()), 0)), 8 },
121                 { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_LONG.varHandle(long.class)), 8 },
122 
123                 // int
124                 { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder()), 0)), 4 },
125                 { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_INT.varHandle(int.class)), 4 },
126 
127                 // short
128                 { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(short.class, ByteOrder.nativeOrder()), 0)), 2 },
129                 { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_SHORT.varHandle(short.class)), 2 },
130 
131                 // char
132                 { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(char.class, ByteOrder.nativeOrder()), 0)), 2 },
133                 { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_CHAR.varHandle(char.class)), 2 },
134 
135                 // byte
136                 { MemoryHandles.asAddressVarHandle(at(MemoryHandles.varHandle(byte.class, ByteOrder.nativeOrder()), 0)), 1 },
137                 { MemoryHandles.asAddressVarHandle(MemoryLayouts.JAVA_BYTE.varHandle(byte.class)), 1 }
138         };
139     }
140 
141     static VarHandle at(VarHandle handle, long offset) {
142         return MemoryHandles.insertCoordinates(handle, 1, offset);
143     }
144 
145     static int boolToInt(boolean value) {
146         return value ? 1 : 0;
147     }
148 
149     static boolean intToBool(int value) {
150         return value != 0;
151     }
152 
153     static int stringToInt(String value) {
154         return value.length();
155     }
156 
157     static String intToString(int value) {
158         return String.valueOf(value);
159     }
160 }