Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8291473: Unify MemorySegment and MemoryAddress #694

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8122f21
Initial push
mcimadamore Jul 18, 2022
32829bc
Minimize diffs
mcimadamore Jul 20, 2022
076d687
Further minimize diffs
mcimadamore Jul 20, 2022
39d5014
Simplify TestUpcallBase
mcimadamore Jul 20, 2022
41d2c14
Simplify TestUpcallHighArity
mcimadamore Jul 20, 2022
8c8a253
Merge branch 'foreign-memaccess+abi' into ffm_segment_unification
mcimadamore Jul 27, 2022
31fa30b
Tweak javadoc for MemorySegment::get(Address)
mcimadamore Jul 27, 2022
3942fec
Update src/java.base/share/classes/java/lang/foreign/package-info.java
mcimadamore Jul 28, 2022
0407106
Update src/java.base/share/classes/java/lang/foreign/ValueLayout.java
mcimadamore Jul 28, 2022
811f84f
Update src/java.base/share/classes/java/lang/foreign/VaList.java
mcimadamore Jul 28, 2022
118cf04
Update src/java.base/share/classes/jdk/internal/foreign/abi/AbstractL…
mcimadamore Jul 28, 2022
22f8e4c
Update src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStu…
mcimadamore Jul 28, 2022
2312cb3
Update test/jdk/java/foreign/TestUpcallHighArity.java
mcimadamore Jul 28, 2022
18e7f60
Add missing copyright headers
mcimadamore Jul 28, 2022
3543e66
Improve upcall tests
mcimadamore Jul 28, 2022
b8e59b1
Re-add MemorySegment::segmentOffset/MemorySegment::asOverlappingSlice
mcimadamore Jul 28, 2022
5e6794d
Simplify BindingSpecializer::popType
mcimadamore Jul 28, 2022
dcfe28f
Simplify layout equality test
mcimadamore Jul 28, 2022
390c52f
Tweak ToSegment binding to work on long
mcimadamore Jul 28, 2022
98ece3e
Merge ToSegment into BoxAddress
mcimadamore Jul 28, 2022
142dd03
Drop references to MemoryAddress/Addressable
mcimadamore Jul 29, 2022
6de1fa7
Remove whitespace
mcimadamore Jul 29, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 0 additions & 47 deletions src/java.base/share/classes/java/lang/foreign/Addressable.java

This file was deleted.

Expand Up @@ -39,7 +39,7 @@
/**
* A function descriptor is made up of zero or more argument layouts and zero or one return layout. A function descriptor
* is used to model the signature of foreign functions when creating
* {@linkplain Linker#downcallHandle(Addressable, FunctionDescriptor) downcall method handles} or
* {@linkplain Linker#downcallHandle(MemorySegment, FunctionDescriptor) downcall method handles} or
* {@linkplain Linker#upcallStub(MethodHandle, FunctionDescriptor, MemorySession) upcall stubs}.
*
* @implSpec
Expand Down
81 changes: 36 additions & 45 deletions src/java.base/share/classes/java/lang/foreign/Linker.java
Expand Up @@ -47,7 +47,7 @@
* in the JVM and foreign functions in the library. In particular:
* <ul>
* <li>A linker allows Java code to link against foreign functions, via
* {@linkplain #downcallHandle(Addressable, FunctionDescriptor) downcall method handles}; and</li>
* {@linkplain #downcallHandle(MemorySegment, FunctionDescriptor) downcall method handles}; and</li>
* <li>A linker allows foreign functions to call Java method handles,
* via the generation of {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, MemorySession) upcall stubs}.</li>
* </ul>
Expand All @@ -67,24 +67,19 @@
* when complete, a downcall method handle, that is, a method handle that can be used to invoke the target foreign function.
* <p>
* The Java {@linkplain java.lang.invoke.MethodType method type} associated with the returned method handle is
* {@linkplain #downcallType(FunctionDescriptor) derived} from the argument and return layouts in the function descriptor.
* {@linkplain #methodType(FunctionDescriptor) derived} from the argument and return layouts in the function descriptor.
* More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred,
* as described below:
* <ul>
* <li>if {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases:
* <ul>
* <li>if {@code L} occurs in a parameter position and {@code E} is {@code MemoryAddress.class},
* then {@code C = Addressable.class};</li>
* <li>otherwise, {@code C = E};
* </ul></li>
* <li>or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>
* <li>if {@code L} is a {@link ValueLayout} with carrier {@code E} then {@code C = E}; or</li>
* <li>if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>
* </ul>
* <p>
* The downcall method handle type, derived as above, might be decorated by additional leading parameters,
* in the given order if both are present:
* <ul>
* <li>If the downcall method handle is created {@linkplain #downcallHandle(FunctionDescriptor) without specifying a target address},
* the downcall method handle type features a leading parameter of type {@link Addressable}, from which the
* the downcall method handle type features a leading parameter of type {@link MemorySegment}, from which the
* address of the target foreign function can be derived.</li>
* <li>If the function descriptor's return layout is a group layout, the resulting downcall method handle accepts
* an additional leading parameter of type {@link SegmentAllocator}, which is used by the linker runtime to allocate the
Expand All @@ -97,22 +92,17 @@
* handle and a function descriptor; in this case, the set of memory layouts in the function descriptor
* specify the signature of the function pointer associated with the upcall stub.
* <p>
* The type of the provided method handle has to {@linkplain #upcallType(FunctionDescriptor) match} the Java
* The type of the provided method handle has to {@linkplain #methodType(FunctionDescriptor) match} the Java
* {@linkplain java.lang.invoke.MethodType method type} associated with the upcall stub, which is derived from the argument
* and return layouts in the function descriptor. More specifically, given each layout {@code L} in the function descriptor,
* a corresponding carrier {@code C} is inferred, as described below:
* <ul>
* <li>If {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases:
* <ul>
* <li>If {@code L} occurs in a return position and {@code E} is {@code MemoryAddress.class},
* then {@code C = Addressable.class};</li>
* <li>Otherwise, {@code C = E};
* </ul></li>
* <li>Or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>
* <li>if {@code L} is a {@link ValueLayout} with carrier {@code E} then {@code C = E}; or</li>
* <li>if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>
* </ul>
* Upcall stubs are modelled by instances of type {@link MemorySegment}; upcall stubs can be passed by reference to other
* downcall method handles (as {@link MemorySegment} implements the {@link Addressable} interface) and,
* when no longer required, they can be {@linkplain MemorySession#close() released}, via their associated {@linkplain MemorySession session}.
* downcall method handles and, when no longer required, they can be {@linkplain MemorySession#close() released},
* via their associated {@linkplain MemorySession memory session}.
*
* <h2 id="safety">Safety considerations</h2>
*
Expand All @@ -121,23 +111,34 @@
* the linker runtime cannot validate linkage requests. When a client interacts with a downcall method handle obtained
* through an invalid linkage request (e.g. by specifying a function descriptor featuring too many argument layouts),
* the result of such interaction is unspecified and can lead to JVM crashes. On downcall handle invocation,
* the linker runtime guarantees the following for any argument that is a memory resource {@code R} (of type {@link MemorySegment}
* or {@link VaList}):
* the linker runtime guarantees the following for any argument {@code A} of type {@link MemorySegment} whose corresponding
* layout is {@link ValueLayout#ADDRESS}:
* <ul>
* <li>The memory session of {@code R} is {@linkplain MemorySession#isAlive() alive}. Otherwise, the invocation throws
* <li>The memory session of {@code A} is {@linkplain MemorySession#isAlive() alive}. Otherwise, the invocation throws
* {@link IllegalStateException};</li>
* <li>The invocation occurs in same thread as the one {@linkplain MemorySession#ownerThread() owning} the memory session of {@code R},
* if said session is confined. Otherwise, the invocation throws {@link WrongThreadException}; and</li>
* <li>The memory session of {@code R} is {@linkplain MemorySession#whileAlive(Runnable) kept alive} (and cannot be closed) during the invocation.</li>
* <li>The memory session of {@code R} is <em>kept alive</em> (and cannot be closed) during the invocation.</li>
*</ul>
* A downcall method handle created from a function descriptor whose return layout is an
* {@linkplain ValueLayout.OfAddress address layout} returns a native memory segment associated with
* the {@linkplain MemorySession#global() global session}. Under normal conditions, the size of the returned segment is {@code 0}.
* However, if the return layout is an {@linkplain ValueLayout.OfAddress#asUnbounded() unbounded} address layout,
* then the size of the returned segment is {@code Long.MAX_VALUE}.
* <p>
* When creating upcall stubs the linker runtime validates the type of the target method handle against the provided
* function descriptor and report an error if any mismatch is detected. As for downcalls, JVM crashes might occur,
* if the foreign code casts the function pointer associated with an upcall stub to a type
* that is incompatible with the provided function descriptor. Moreover, if the target method
* handle associated with an upcall stub returns a {@linkplain MemoryAddress memory address}, clients must ensure
* handle associated with an upcall stub returns a {@linkplain MemorySegment memory segment}, clients must ensure
* that this address cannot become invalid after the upcall completes. This can lead to unspecified behavior,
* and even JVM crashes, since an upcall is typically executed in the context of a downcall method handle invocation.
* <p>
* An upcall stub argument whose corresponding layout is an {@linkplain ValueLayout.OfAddress address layout}
* is a native memory segment associated with the {@linkplain MemorySession#global() global session}.
* Under normal conditions, the size of this segment argument is {@code 0}. However, if the layout associated with
* the upcall stub argument is an {@linkplain ValueLayout.OfAddress#asUnbounded() unbounded} address layout,
* then the size of the segment argument is {@code Long.MAX_VALUE}.
*
* @implSpec
* Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
Expand All @@ -160,13 +161,13 @@ public sealed interface Linker permits AbstractLinker {
* <li>Composite types are modelled by a {@linkplain GroupLayout group layout}. Depending on the ABI of the
* returned linker, additional {@linkplain MemoryLayout#paddingLayout(long) padding} member layouts might be required to conform
* to the size and alignment constraints of a composite type definition in C (e.g. using {@code struct} or {@code union}); and</li>
* <li>Pointer types are modelled by a {@linkplain ValueLayout value layout} instance with carrier {@link MemoryAddress}.
* <li>Pointer types are modelled by a {@linkplain ValueLayout value layout} instance with carrier {@link MemorySegment}.
* Examples of pointer types in C are {@code int**} and {@code int(*)(size_t*, size_t*)};</li>
* </ul>
* <p>
* Any layout not listed above is <em>unsupported</em>; function descriptors containing unsupported layouts
* will cause an {@link IllegalArgumentException} to be thrown, when used to create a
* {@link #downcallHandle(Addressable, FunctionDescriptor) downcall method handle} or an
* {@link #downcallHandle(MemorySegment, FunctionDescriptor) downcall method handle} or an
* {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, MemorySession) upcall stub}.
* <p>
* Variadic functions (e.g. a C function declared with a trailing ellipses {@code ...} at the end of the formal parameter
Expand Down Expand Up @@ -214,25 +215,25 @@ static Linker nativeLinker() {
* @param function the function descriptor of the target function.
* @return a downcall method handle. The method handle type is <a href="Linker.html#downcall-method-handles"><em>inferred</em></a>
* @throws IllegalArgumentException if the provided function descriptor is not supported by this linker.
* or if the symbol is {@link MemoryAddress#NULL}
* or if the symbol is {@link MemorySegment#NULL}
*/
default MethodHandle downcallHandle(Addressable symbol, FunctionDescriptor function) {
default MethodHandle downcallHandle(MemorySegment symbol, FunctionDescriptor function) {
SharedUtils.checkSymbol(symbol);
return downcallHandle(function).bindTo(symbol);
}

/**
* Creates a method handle which can be used to call a target foreign function with the given signature.
* The resulting method handle features a prefix parameter (as the first parameter) corresponding to the foreign function
* entry point, of type {@link Addressable}, which is used to specify the address of the target function
* entry point, of type {@link MemorySegment}, which is used to specify the address of the target function
* to be called.
* <p>
* If the provided function descriptor's return layout is a {@link GroupLayout}, then the resulting method handle features an
* additional prefix parameter (inserted immediately after the address parameter), of type {@link SegmentAllocator}),
* which will be used by the linker runtime to allocate structs returned by-value.
* <p>
* The returned method handle will throw an {@link IllegalArgumentException} if the {@link Addressable} parameter passed to it is
* associated with the {@link MemoryAddress#NULL} address, or a {@link NullPointerException} if that parameter is {@code null}.
* The returned method handle will throw an {@link IllegalArgumentException} if the {@link MemorySegment} parameter passed to it is
* associated with the {@link MemorySegment#NULL} address, or a {@link NullPointerException} if that parameter is {@code null}.
*
* @param function the function descriptor of the target function.
* @return a downcall method handle. The method handle type is <a href="Linker.html#downcall-method-handles"><em>inferred</em></a>
Expand Down Expand Up @@ -284,22 +285,12 @@ default MethodHandle downcallHandle(Addressable symbol, FunctionDescriptor funct
SymbolLookup defaultLookup();

/**
* {@return the downcall method handle {@linkplain MethodType type} associated with the given function descriptor}
* @param functionDescriptor a function descriptor.
* @throws IllegalArgumentException if one or more layouts in the function descriptor are not supported
* (e.g. if they are sequence layouts or padding layouts).
*/
static MethodType downcallType(FunctionDescriptor functionDescriptor) {
return SharedUtils.inferMethodType(functionDescriptor, false);
}

/**
* {@return the method handle {@linkplain MethodType type} associated with an upcall stub with the given function descriptor}
* {@return the linker method handle {@linkplain MethodType type} associated with the given function descriptor}
* @param functionDescriptor a function descriptor.
* @throws IllegalArgumentException if one or more layouts in the function descriptor are not supported
* (e.g. if they are sequence layouts or padding layouts).
*/
static MethodType upcallType(FunctionDescriptor functionDescriptor) {
return SharedUtils.inferMethodType(functionDescriptor, true);
static MethodType methodType(FunctionDescriptor functionDescriptor) {
return SharedUtils.inferMethodType(functionDescriptor);
}
}