12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 *
25 */
26
27 package jdk.internal.foreign;
28
29 import java.lang.foreign.AddressLayout;
30 import java.lang.foreign.MemoryLayout;
31 import java.lang.foreign.MemorySegment;
32 import java.lang.foreign.SegmentAllocator;
33 import java.lang.foreign.StructLayout;
34 import java.lang.foreign.ValueLayout;
35 import java.lang.invoke.MethodHandle;
36 import java.lang.invoke.MethodHandles;
37 import java.lang.invoke.MethodType;
38 import java.lang.invoke.VarHandle;
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.concurrent.ConcurrentHashMap;
43 import java.util.function.Supplier;
44
45 import jdk.internal.access.SharedSecrets;
46 import jdk.internal.foreign.abi.SharedUtils;
47 import jdk.internal.vm.annotation.ForceInline;
48 import sun.invoke.util.Wrapper;
49
50 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
51 import static sun.security.action.GetPropertyAction.privilegedGetProperty;
52
53 /**
54 * This class contains misc helper functions to support creation of memory segments.
55 */
56 public final class Utils {
57
58 public static final boolean IS_WINDOWS = privilegedGetProperty("os.name").startsWith("Windows");
59
60 // Suppresses default constructor, ensuring non-instantiability.
61 private Utils() {}
62
63 private static final MethodHandle BYTE_TO_BOOL;
64 private static final MethodHandle BOOL_TO_BYTE;
65 private static final MethodHandle ADDRESS_TO_LONG;
66 private static final MethodHandle LONG_TO_ADDRESS;
67
68 static {
69 try {
70 MethodHandles.Lookup lookup = MethodHandles.lookup();
81 }
82 }
83
84 public static long alignUp(long n, long alignment) {
85 return (n + alignment - 1) & -alignment;
86 }
87
88 public static MemorySegment alignUp(MemorySegment ms, long alignment) {
89 long offset = ms.address();
90 return ms.asSlice(alignUp(offset, alignment) - offset);
91 }
92
93 public static VarHandle makeSegmentViewVarHandle(ValueLayout layout) {
94 final class VarHandleCache {
95 private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>();
96
97 static VarHandle put(ValueLayout layout, VarHandle handle) {
98 VarHandle prev = HANDLE_MAP.putIfAbsent(layout, handle);
99 return prev != null ? prev : handle;
100 }
101 }
102 Class<?> baseCarrier = layout.carrier();
103 if (layout.carrier() == MemorySegment.class) {
104 baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) {
105 case Long.BYTES -> long.class;
106 case Integer.BYTES -> int.class;
107 default -> throw new UnsupportedOperationException("Unsupported address layout");
108 };
109 } else if (layout.carrier() == boolean.class) {
110 baseCarrier = byte.class;
111 }
112
113 VarHandle handle = SharedSecrets.getJavaLangInvokeAccess().memorySegmentViewHandle(baseCarrier,
114 layout.byteAlignment() - 1, layout.order());
115
116 if (layout.carrier() == boolean.class) {
117 handle = MethodHandles.filterValue(handle, BOOL_TO_BYTE, BYTE_TO_BOOL);
118 } else if (layout instanceof AddressLayout addressLayout) {
119 handle = MethodHandles.filterValue(handle,
120 MethodHandles.explicitCastArguments(ADDRESS_TO_LONG, MethodType.methodType(baseCarrier, MemorySegment.class)),
121 MethodHandles.explicitCastArguments(MethodHandles.insertArguments(LONG_TO_ADDRESS, 1,
122 pointeeByteSize(addressLayout), pointeeByteAlign(addressLayout)),
123 MethodType.methodType(MemorySegment.class, baseCarrier)));
124 }
125 return VarHandleCache.put(layout, handle);
126 }
127
128 public static boolean byteToBoolean(byte b) {
129 return b != 0;
130 }
131
132 private static byte booleanToByte(boolean b) {
133 return b ? (byte)1 : (byte)0;
134 }
135
136 @ForceInline
137 public static MemorySegment longToAddress(long addr, long size, long align) {
138 if (!isAligned(addr, align)) {
139 throw new IllegalArgumentException("Invalid alignment constraint for address: " + addr);
140 }
141 return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, size);
142 }
143
144 @ForceInline
145 public static MemorySegment longToAddress(long addr, long size, long align, MemorySessionImpl scope) {
146 if (!isAligned(addr, align)) {
147 throw new IllegalArgumentException("Invalid alignment constraint for address: " + addr);
148 }
149 return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, size, scope);
150 }
151
152 public static void copy(MemorySegment addr, byte[] bytes) {
153 var heapSegment = MemorySegment.ofArray(bytes);
154 addr.copyFrom(heapSegment);
155 addr.set(JAVA_BYTE, bytes.length, (byte)0);
156 }
157
158 public static MemorySegment toCString(byte[] bytes, SegmentAllocator allocator) {
159 MemorySegment addr = allocator.allocate(bytes.length + 1);
160 copy(addr, bytes);
161 return addr;
162 }
163
164 @ForceInline
165 public static boolean isAligned(long offset, long align) {
166 return (offset & (align - 1)) == 0;
167 }
168
169 @ForceInline
170 public static boolean isElementAligned(ValueLayout layout) {
171 // Fast-path: if both size and alignment are powers of two, we can just
172 // check if one is greater than the other.
173 assert isPowerOfTwo(layout.byteSize());
174 return layout.byteAlignment() <= layout.byteSize();
175 }
176
177 @ForceInline
178 public static void checkElementAlignment(ValueLayout layout, String msg) {
179 if (!isElementAligned(layout)) {
180 throw new IllegalArgumentException(msg);
181 }
182 }
183
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 *
25 */
26
27 package jdk.internal.foreign;
28
29 import java.lang.foreign.AddressLayout;
30 import java.lang.foreign.MemoryLayout;
31 import java.lang.foreign.MemorySegment;
32 import java.lang.foreign.StructLayout;
33 import java.lang.foreign.ValueLayout;
34 import java.lang.invoke.MethodHandle;
35 import java.lang.invoke.MethodHandles;
36 import java.lang.invoke.MethodType;
37 import java.lang.invoke.VarHandle;
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.concurrent.ConcurrentHashMap;
42 import java.util.function.Supplier;
43
44 import jdk.internal.access.SharedSecrets;
45 import jdk.internal.foreign.abi.SharedUtils;
46 import jdk.internal.vm.annotation.ForceInline;
47 import sun.invoke.util.Wrapper;
48
49 import static sun.security.action.GetPropertyAction.privilegedGetProperty;
50
51 /**
52 * This class contains misc helper functions to support creation of memory segments.
53 */
54 public final class Utils {
55
56 public static final boolean IS_WINDOWS = privilegedGetProperty("os.name").startsWith("Windows");
57
58 // Suppresses default constructor, ensuring non-instantiability.
59 private Utils() {}
60
61 private static final MethodHandle BYTE_TO_BOOL;
62 private static final MethodHandle BOOL_TO_BYTE;
63 private static final MethodHandle ADDRESS_TO_LONG;
64 private static final MethodHandle LONG_TO_ADDRESS;
65
66 static {
67 try {
68 MethodHandles.Lookup lookup = MethodHandles.lookup();
79 }
80 }
81
82 public static long alignUp(long n, long alignment) {
83 return (n + alignment - 1) & -alignment;
84 }
85
86 public static MemorySegment alignUp(MemorySegment ms, long alignment) {
87 long offset = ms.address();
88 return ms.asSlice(alignUp(offset, alignment) - offset);
89 }
90
91 public static VarHandle makeSegmentViewVarHandle(ValueLayout layout) {
92 final class VarHandleCache {
93 private static final Map<ValueLayout, VarHandle> HANDLE_MAP = new ConcurrentHashMap<>();
94
95 static VarHandle put(ValueLayout layout, VarHandle handle) {
96 VarHandle prev = HANDLE_MAP.putIfAbsent(layout, handle);
97 return prev != null ? prev : handle;
98 }
99
100 static VarHandle get(ValueLayout layout) {
101 return HANDLE_MAP.get(layout);
102 }
103 }
104 layout = layout.withoutName(); // name doesn't matter
105 // keep the addressee layout as it's used below
106
107 VarHandle handle = VarHandleCache.get(layout);
108 if (handle != null) {
109 return handle;
110 }
111
112 Class<?> baseCarrier = layout.carrier();
113 if (layout.carrier() == MemorySegment.class) {
114 baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) {
115 case Long.BYTES -> long.class;
116 case Integer.BYTES -> int.class;
117 default -> throw new UnsupportedOperationException("Unsupported address layout");
118 };
119 } else if (layout.carrier() == boolean.class) {
120 baseCarrier = byte.class;
121 }
122
123 handle = SharedSecrets.getJavaLangInvokeAccess().memorySegmentViewHandle(baseCarrier,
124 layout.byteAlignment() - 1, layout.order());
125
126 if (layout.carrier() == boolean.class) {
127 handle = MethodHandles.filterValue(handle, BOOL_TO_BYTE, BYTE_TO_BOOL);
128 } else if (layout instanceof AddressLayout addressLayout) {
129 handle = MethodHandles.filterValue(handle,
130 MethodHandles.explicitCastArguments(ADDRESS_TO_LONG, MethodType.methodType(baseCarrier, MemorySegment.class)),
131 MethodHandles.explicitCastArguments(MethodHandles.insertArguments(LONG_TO_ADDRESS, 1,
132 pointeeByteSize(addressLayout), pointeeByteAlign(addressLayout)),
133 MethodType.methodType(MemorySegment.class, baseCarrier)));
134 }
135 return VarHandleCache.put(layout, handle);
136 }
137
138 public static boolean byteToBoolean(byte b) {
139 return b != 0;
140 }
141
142 private static byte booleanToByte(boolean b) {
143 return b ? (byte)1 : (byte)0;
144 }
145
146 @ForceInline
147 public static MemorySegment longToAddress(long addr, long size, long align) {
148 if (!isAligned(addr, align)) {
149 throw new IllegalArgumentException("Invalid alignment constraint for address: " + toHexString(addr));
150 }
151 return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, size);
152 }
153
154 @ForceInline
155 public static MemorySegment longToAddress(long addr, long size, long align, MemorySessionImpl scope) {
156 if (!isAligned(addr, align)) {
157 throw new IllegalArgumentException("Invalid alignment constraint for address: " + toHexString(addr));
158 }
159 return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, size, scope);
160 }
161
162 @ForceInline
163 public static boolean isAligned(long offset, long align) {
164 return (offset & (align - 1)) == 0;
165 }
166
167 @ForceInline
168 public static boolean isElementAligned(ValueLayout layout) {
169 // Fast-path: if both size and alignment are powers of two, we can just
170 // check if one is greater than the other.
171 assert isPowerOfTwo(layout.byteSize());
172 return layout.byteAlignment() <= layout.byteSize();
173 }
174
175 @ForceInline
176 public static void checkElementAlignment(ValueLayout layout, String msg) {
177 if (!isElementAligned(layout)) {
178 throw new IllegalArgumentException(msg);
179 }
180 }
181
|