1 /* 2 * Copyright (c) 2021, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 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 package java.lang.foreign; 27 28 import java.lang.invoke.VarHandle; 29 import java.lang.reflect.Array; 30 import java.nio.ByteOrder; 31 import java.nio.charset.StandardCharsets; 32 import java.util.Objects; 33 import java.util.function.Function; 34 import jdk.internal.foreign.AbstractMemorySegmentImpl; 35 import jdk.internal.foreign.SlicingAllocator; 36 import jdk.internal.foreign.Utils; 37 import jdk.internal.javac.PreviewFeature; 38 39 /** 40 * An object that may be used to allocate {@linkplain MemorySegment memory segments}. Clients implementing this interface 41 * must implement the {@link #allocate(long, long)} method. A segment allocator defines several methods 42 * which can be useful to create segments from several kinds of Java values such as primitives and arrays. 43 * <p> 44 * {@code SegmentAllocator} is a {@linkplain FunctionalInterface functional interface}. Clients can easily obtain a new 45 * segment allocator by using either a lambda expression or a method reference: 46 * 47 * {@snippet lang=java : 48 * SegmentAllocator autoAllocator = (byteSize, byteAlignment) -> Arena.ofAuto().allocate(byteSize, byteAlignment); 49 * } 50 * <p> 51 * This interface defines factories for commonly used allocators: 52 * <ul> 53 * <li>{@link #slicingAllocator(MemorySegment)} obtains an efficient slicing allocator, where memory 54 * is allocated by repeatedly slicing the provided memory segment;</li> 55 * <li>{@link #prefixAllocator(MemorySegment)} obtains an allocator which wraps a segment 56 * and recycles its content upon each new allocation request.</li> 57 * </ul> 58 * <p> 59 * Passing a segment allocator to an API can be especially useful in circumstances where a client wants to communicate <em>where</em> 60 * the results of a certain operation (performed by the API) should be stored, as a memory segment. For instance, 61 * {@linkplain Linker#downcallHandle(FunctionDescriptor, Linker.Option...) downcall method handles} can accept an additional 62 * {@link SegmentAllocator} parameter if the underlying foreign function is known to return a struct by-value. Effectively, 63 * the allocator parameter tells the linker where to store the return value of the foreign function. 64 * 65 * @apiNote Unless otherwise specified, the {@link #allocate(long, long)} method is not thread-safe. 66 * Furthermore, memory segments allocated by a segment allocator can be associated with different 67 * lifetimes, and can even be backed by overlapping regions of memory. For these reasons, clients should generally 68 * only interact with a segment allocator they own. 69 * <p> 70 * Clients should consider using an {@linkplain Arena arena} instead, which, provides strong thread-safety, 71 * lifetime and non-overlapping guarantees. 72 * 73 * @since 19 74 */ 75 @FunctionalInterface 76 @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) 77 public interface SegmentAllocator { 78 79 /** 80 * {@return a new memory segment with a Java string converted into a UTF-8 encoded, null-terminated C string} 81 * <p> 82 * This method always replaces malformed-input and unmappable-character 83 * sequences with this charset's default replacement byte array. The 84 * {@link java.nio.charset.CharsetEncoder} class should be used when more 85 * control over the encoding process is required. 86 * <p> 87 * If the given string contains any {@code '\0'} characters, they will be 88 * copied as well. This means that, depending on the method used to read 89 * the string, such as {@link MemorySegment#getUtf8String(long)}, the string 90 * will appear truncated when read again. 91 * 92 * @implSpec The default implementation for this method copies the contents of the provided Java string 93 * into a new memory segment obtained by calling {@code this.allocate(str.length() + 1)}. 94 * @param str the Java string to be converted into a C string. 95 */ 96 default MemorySegment allocateUtf8String(String str) { 97 Objects.requireNonNull(str); 98 return Utils.toCString(str.getBytes(StandardCharsets.UTF_8), this); 99 } 100 101 /** 102 * {@return a new memory segment initialized with the provided {@code byte} {@code value} as 103 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 104 * 105 * @implSpec The default implementation is equivalent to: 106 * {@snippet lang=java : 107 * MemorySegment seg = allocate(Objects.requireNonNull(layout)); 108 * seg.set(layout, 0, value); 109 * return seg; 110 * } 111 * 112 * @param layout the layout of the block of memory to be allocated. 113 * @param value the value to be set in the newly allocated memory segment. 114 */ 115 default MemorySegment allocate(ValueLayout.OfByte layout, byte value) { 116 Objects.requireNonNull(layout); 117 VarHandle handle = layout.varHandle(); 118 MemorySegment seg = allocate(layout); 119 handle.set(seg, value); 120 return seg; 121 } 122 123 /** 124 * {@return a new memory segment initialized with the provided {@code char} {@code value} as 125 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 126 * 127 * @implSpec The default implementation is equivalent to: 128 * {@snippet lang=java : 129 * MemorySegment seg = allocate(Objects.requireNonNull(layout)); 130 * seg.set(layout, 0, value); 131 * return seg; 132 * } 133 * 134 * @param layout the layout of the block of memory to be allocated. 135 * @param value the value to be set in the newly allocated memory segment. 136 */ 137 default MemorySegment allocate(ValueLayout.OfChar layout, char value) { 138 Objects.requireNonNull(layout); 139 VarHandle handle = layout.varHandle(); 140 MemorySegment seg = allocate(layout); 141 handle.set(seg, value); 142 return seg; 143 } 144 145 /** 146 * {@return a new memory segment initialized with the provided {@code short} {@code value} as 147 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 148 * 149 * @implSpec The default implementation is equivalent to: 150 * {@snippet lang=java : 151 * MemorySegment seg = allocate(Objects.requireNonNull(layout)); 152 * seg.set(layout, 0, value); 153 * return seg; 154 * } 155 * 156 * @param layout the layout of the block of memory to be allocated. 157 * @param value the value to be set in the newly allocated memory segment. 158 */ 159 default MemorySegment allocate(ValueLayout.OfShort layout, short value) { 160 Objects.requireNonNull(layout); 161 VarHandle handle = layout.varHandle(); 162 MemorySegment seg = allocate(layout); 163 handle.set(seg, value); 164 return seg; 165 } 166 167 /** 168 * {@return a new memory segment initialized with the provided {@code int} {@code value} as 169 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 170 * 171 * @implSpec The default implementation is equivalent to: 172 * {@snippet lang=java : 173 * MemorySegment seg = allocate(Objects.requireNonNull(layout)); 174 * seg.set(layout, 0, value); 175 * return seg; 176 * } 177 * 178 * @param layout the layout of the block of memory to be allocated. 179 * @param value the value to be set in the newly allocated memory segment. 180 */ 181 default MemorySegment allocate(ValueLayout.OfInt layout, int value) { 182 Objects.requireNonNull(layout); 183 VarHandle handle = layout.varHandle(); 184 MemorySegment seg = allocate(layout); 185 handle.set(seg, value); 186 return seg; 187 } 188 189 /** 190 * {@return a new memory segment initialized with the provided {@code float} {@code value} as 191 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 192 * 193 * @implSpec The default implementation is equivalent to: 194 * {@snippet lang=java : 195 * MemorySegment seg = allocate(Objects.requireNonNull(layout)); 196 * seg.set(layout, 0, value); 197 * return seg; 198 * } 199 * 200 * @param layout the layout of the block of memory to be allocated. 201 * @param value the value to be set in the newly allocated memory segment. 202 */ 203 default MemorySegment allocate(ValueLayout.OfFloat layout, float value) { 204 Objects.requireNonNull(layout); 205 VarHandle handle = layout.varHandle(); 206 MemorySegment seg = allocate(layout); 207 handle.set(seg, value); 208 return seg; 209 } 210 211 /** 212 * {@return a new memory segment initialized with the provided {@code long} {@code value} as 213 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 214 * 215 * @implSpec The default implementation is equivalent to: 216 * {@snippet lang=java : 217 * MemorySegment seg = allocate(Objects.requireNonNull(layout)); 218 * seg.set(layout, 0, value); 219 * return seg; 220 * } 221 * 222 * @param layout the layout of the block of memory to be allocated. 223 * @param value the value to be set in the newly allocated memory segment. 224 */ 225 default MemorySegment allocate(ValueLayout.OfLong layout, long value) { 226 Objects.requireNonNull(layout); 227 VarHandle handle = layout.varHandle(); 228 MemorySegment seg = allocate(layout); 229 handle.set(seg, value); 230 return seg; 231 } 232 233 /** 234 * {@return a new memory segment initialized with the provided {@code double} {@code value} as 235 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 236 * 237 * @implSpec The default implementation is equivalent to: 238 * {@snippet lang=java : 239 * MemorySegment seg = allocate(Objects.requireNonNull(layout)); 240 * seg.set(layout, 0, value); 241 * return seg; 242 * } 243 * 244 * @param layout the layout of the block of memory to be allocated. 245 * @param value the value to be set in the newly allocated memory segment. 246 */ 247 default MemorySegment allocate(ValueLayout.OfDouble layout, double value) { 248 Objects.requireNonNull(layout); 249 VarHandle handle = layout.varHandle(); 250 MemorySegment seg = allocate(layout); 251 handle.set(seg, value); 252 return seg; 253 } 254 255 /** 256 * {@return a new memory segment initialized with the address of the provided {@code value} as 257 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 258 * <p> 259 * The address value might be narrowed according to the platform address size (see {@link ValueLayout#ADDRESS}). 260 * 261 * @implSpec The default implementation is equivalent to: 262 * {@snippet lang=java : 263 * Objects.requireNonNull(value); 264 * MemorySegment seg = allocate(Objects.requireNonNull(layout)); 265 * seg.set(layout, 0, value); 266 * return seg; 267 * } 268 * 269 * @param layout the layout of the block of memory to be allocated. 270 * @param value the value to be set in the newly allocated memory segment. 271 */ 272 default MemorySegment allocate(AddressLayout layout, MemorySegment value) { 273 Objects.requireNonNull(value); 274 Objects.requireNonNull(layout); 275 MemorySegment seg = allocate(layout); 276 layout.varHandle().set(seg, value); 277 return seg; 278 } 279 280 /** 281 * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of 282 * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code byte} {@code elements} as 283 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 284 * 285 * @implSpec The default implementation is equivalent to: 286 * {@snippet lang=java : 287 * int size = Objects.requireNonNull(elements).length; 288 * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); 289 * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); 290 * return seg; 291 * } 292 * 293 * @param elementLayout the element layout of the array to be allocated. 294 * @param elements the short elements to be copied to the newly allocated memory block. 295 */ 296 default MemorySegment allocateArray(ValueLayout.OfByte elementLayout, byte... elements) { 297 return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); 298 } 299 300 /** 301 * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of 302 * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code short} {@code elements} as 303 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 304 * 305 * @implSpec The default implementation is equivalent to: 306 * {@snippet lang=java : 307 * int size = Objects.requireNonNull(elements).length; 308 * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); 309 * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); 310 * return seg; 311 * } 312 * 313 * @param elementLayout the element layout of the array to be allocated. 314 * @param elements the short elements to be copied to the newly allocated memory block. 315 */ 316 default MemorySegment allocateArray(ValueLayout.OfShort elementLayout, short... elements) { 317 return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); 318 } 319 320 /** 321 * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of 322 * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code char} {@code elements} as 323 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 324 * 325 * @implSpec The default implementation is equivalent to: 326 * {@snippet lang=java : 327 * int size = Objects.requireNonNull(elements).length; 328 * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); 329 * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); 330 * return seg; 331 * } 332 * 333 * @param elementLayout the element layout of the array to be allocated. 334 * @param elements the short elements to be copied to the newly allocated memory block. 335 */ 336 default MemorySegment allocateArray(ValueLayout.OfChar elementLayout, char... elements) { 337 return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); 338 } 339 340 /** 341 * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of 342 * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code int} {@code elements} as 343 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 344 * 345 * @implSpec The default implementation is equivalent to: 346 * {@snippet lang=java : 347 * int size = Objects.requireNonNull(elements).length; 348 * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); 349 * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); 350 * return seg; 351 * } 352 * 353 * @param elementLayout the element layout of the array to be allocated. 354 * @param elements the short elements to be copied to the newly allocated memory block. 355 */ 356 default MemorySegment allocateArray(ValueLayout.OfInt elementLayout, int... elements) { 357 return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); 358 } 359 360 /** 361 * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of 362 * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code float} {@code elements} as 363 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 364 * 365 * @implSpec The default implementation is equivalent to: 366 * {@snippet lang=java : 367 * int size = Objects.requireNonNull(elements).length; 368 * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); 369 * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); 370 * return seg; 371 * } 372 * 373 * @param elementLayout the element layout of the array to be allocated. 374 * @param elements the short elements to be copied to the newly allocated memory block. 375 */ 376 default MemorySegment allocateArray(ValueLayout.OfFloat elementLayout, float... elements) { 377 return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); 378 } 379 380 /** 381 * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of 382 * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code long} {@code elements} as 383 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 384 * 385 * @implSpec The default implementation is equivalent to: 386 * {@snippet lang=java : 387 * int size = Objects.requireNonNull(elements).length; 388 * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); 389 * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); 390 * return seg; 391 * } 392 * 393 * @param elementLayout the element layout of the array to be allocated. 394 * @param elements the short elements to be copied to the newly allocated memory block. 395 */ 396 default MemorySegment allocateArray(ValueLayout.OfLong elementLayout, long... elements) { 397 return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); 398 } 399 400 /** 401 * {@return a new memory segment with a {@linkplain MemorySegment#byteSize() byteSize()} of 402 * {@code E*layout.byteSize()} initialized with the provided {@code E} {@code double} {@code elements} as 403 * specified by the provided {@code layout} (i.e. byte ordering, alignment and size)} 404 * 405 * @implSpec The default implementation is equivalent to: 406 * {@snippet lang=java : 407 * int size = Objects.requireNonNull(elements).length; 408 * MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); 409 * MemorySegment.copy(elements, 0, seg, elementLayout, 0, size); 410 * return seg; 411 * } 412 * 413 * @param elementLayout the element layout of the array to be allocated. 414 * @param elements the short elements to be copied to the newly allocated memory block. 415 */ 416 default MemorySegment allocateArray(ValueLayout.OfDouble elementLayout, double... elements) { 417 return copyArrayWithSwapIfNeeded(elements, elementLayout, MemorySegment::ofArray); 418 } 419 420 private <Z> MemorySegment copyArrayWithSwapIfNeeded(Z array, ValueLayout elementLayout, 421 Function<Z, MemorySegment> heapSegmentFactory) { 422 int size = Array.getLength(Objects.requireNonNull(array)); 423 MemorySegment seg = allocateArray(Objects.requireNonNull(elementLayout), size); 424 if (size > 0) { 425 MemorySegment.copy(heapSegmentFactory.apply(array), elementLayout, 0, 426 seg, elementLayout.withOrder(ByteOrder.nativeOrder()), 0, size); 427 } 428 return seg; 429 } 430 431 /** 432 * {@return a new memory segment with the given layout} 433 * 434 * @implSpec The default implementation for this method calls 435 * {@code this.allocate(layout.byteSize(), layout.byteAlignment())}. 436 * 437 * @param layout the layout of the block of memory to be allocated. 438 */ 439 default MemorySegment allocate(MemoryLayout layout) { 440 Objects.requireNonNull(layout); 441 return allocate(layout.byteSize(), layout.byteAlignment()); 442 } 443 444 /** 445 * {@return a new memory segment with the given {@code elementLayout} and {@code count}} 446 * 447 * @implSpec The default implementation for this method calls 448 * {@code this.allocate(MemoryLayout.sequenceLayout(count, elementLayout))}. 449 * 450 * @param elementLayout the array element layout. 451 * @param count the array element count. 452 * @throws IllegalArgumentException if {@code elementLayout.byteSize() * count} overflows. 453 * @throws IllegalArgumentException if {@code count < 0}. 454 */ 455 default MemorySegment allocateArray(MemoryLayout elementLayout, long count) { 456 Objects.requireNonNull(elementLayout); 457 if (count < 0) { 458 throw new IllegalArgumentException("Negative array size"); 459 } 460 return allocate(MemoryLayout.sequenceLayout(count, elementLayout)); 461 } 462 463 /** 464 * {@return a new memory segment with the given {@code byteSize}} 465 * 466 * @implSpec The default implementation for this method calls 467 * {@code this.allocate(byteSize, 1)}. 468 * 469 * @param byteSize the size (in bytes) of the block of memory to be allocated. 470 * @throws IllegalArgumentException if {@code byteSize < 0} 471 */ 472 default MemorySegment allocate(long byteSize) { 473 return allocate(byteSize, 1); 474 } 475 476 /** 477 * {@return a new memory segment with the given {@code byteSize} and {@code byteAlignment}} 478 * 479 * @param byteSize the size (in bytes) of the block of memory to be allocated. 480 * @param byteAlignment the alignment (in bytes) of the block of memory to be allocated. 481 * @throws IllegalArgumentException if {@code byteSize < 0}, {@code byteAlignment <= 0}, 482 * or if {@code byteAlignment} is not a power of 2. 483 */ 484 MemorySegment allocate(long byteSize, long byteAlignment); 485 486 /** 487 * Returns a segment allocator which responds to allocation requests by returning consecutive slices 488 * obtained from the provided segment. Each new allocation request will return a new slice starting at the 489 * current offset (modulo additional padding to satisfy alignment constraint), with given size. 490 * <p> 491 * The returned allocator throws {@link IndexOutOfBoundsException} when a slice of the provided 492 * segment with the requested size and alignment cannot be found. 493 * 494 * @implNote A slicing allocator is not <em>thread-safe</em>. 495 * 496 * @param segment the segment which the returned allocator should slice from. 497 * @return a new slicing allocator 498 */ 499 static SegmentAllocator slicingAllocator(MemorySegment segment) { 500 Objects.requireNonNull(segment); 501 return new SlicingAllocator(segment); 502 } 503 504 /** 505 * Returns a segment allocator which responds to allocation requests by recycling a single segment. Each 506 * new allocation request will return a new slice starting at the segment offset {@code 0}, hence the name 507 * <em>prefix allocator</em>. 508 * Equivalent to (but likely more efficient than) the following code: 509 * {@snippet lang=java : 510 * MemorySegment segment = ... 511 * SegmentAllocator prefixAllocator = (size, align) -> segment.asSlice(0, size, align); 512 * } 513 * The returned allocator throws {@link IndexOutOfBoundsException} when a slice of the provided 514 * segment with the requested size and alignment cannot be found. 515 * 516 * @apiNote A prefix allocator can be useful to limit allocation requests in case a client 517 * knows that they have fully processed the contents of the allocated segment before the subsequent allocation request 518 * takes place. 519 * @implNote While a prefix allocator is <em>thread-safe</em>, concurrent access on the same recycling 520 * allocator might cause a thread to overwrite contents written to the underlying segment by a different thread. 521 * 522 * @param segment the memory segment to be recycled by the returned allocator. 523 * @return an allocator which recycles an existing segment upon each new allocation request. 524 */ 525 static SegmentAllocator prefixAllocator(MemorySegment segment) { 526 return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment); 527 } 528 }