Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions espresso/mx.espresso/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,19 @@
"checkstyle": "com.oracle.truffle.espresso",
},

"com.oracle.truffle.espresso.memory.panama": {
"subDir": "src",
"sourceDirs": ["src"],
"dependencies": [
"com.oracle.truffle.espresso",
"truffle:TRUFFLE_API",
],
"javaCompliance": "22+",
# GR-47124 spotbugs does not support jdk22
"spotbugs": "false",
"checkstyle": "com.oracle.truffle.espresso",
},

"com.oracle.truffle.espresso.hotswap": {
"subDir": "src",
"sourceDirs": ["src"],
Expand Down Expand Up @@ -181,6 +194,7 @@
],
"uses": [
"com.oracle.truffle.espresso.ffi.NativeAccess.Provider",
"com.oracle.truffle.espresso.ffi.memory.NativeMemory.Provider",
],
"annotationProcessors": ["truffle:TRUFFLE_DSL_PROCESSOR", "ESPRESSO_PROCESSOR"],
"jacoco" : "include",
Expand Down Expand Up @@ -553,6 +567,7 @@
"subDir": "src",
"dependencies": [
"com.oracle.truffle.espresso",
"com.oracle.truffle.espresso.memory.panama",
],
"distDependencies": [
"truffle:TRUFFLE_API",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ static int createJavaVM(@SuppressWarnings("unused") IsolateThread thread, JNIJav
STDERR.println("<JavaVM> is not available in the java bindings");
return JNIErrors.JNI_ERR();
}
/*
* Here we assume the value of asNativePointer actually refers to host memory which
* generally does not hold anymore since the introduction of NativeMemory (GR-70643).
* However, this could only pose problems in the unlikely case of explicitly choosing a
* "virtualized" NativeMemory while starting espresso from native.
*/
JNIJavaVM espressoJavaVM = WordFactory.pointer(java.asNativePointer());
bindings.removeMember("<JavaVM>");
ObjectHandle contextHandle = ObjectHandles.getGlobal().create(context);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.oracle.truffle.espresso.memory.panama.MemorySegmentChunkedMemoryImpl$Provider

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,13 @@ public class StructsProcessor extends AbstractProcessor {
private static final String IMPORT_BYTEBUFFER = "java.nio.ByteBuffer";
private static final String IMPORT_JNI_HANDLES = "com.oracle.truffle.espresso.jni.JNIHandles";
private static final String IMPORT_RAW_POINTER = "com.oracle.truffle.espresso.ffi.RawPointer";
private static final String IMPORT_NATIVE_MEMORY = "com.oracle.truffle.espresso.ffi.memory.NativeMemory";

// Classes
private static final String TRUFFLE_OBJECT = "TruffleObject";
private static final String INTEROP_LIBRARY = "InteropLibrary";
private static final String JNI_HANDLES_CLASS = "JNIHandles";
private static final String NATIVE_MEMORY_CLASS = "NativeMemory";
private static final String MEMBER_OFFSET_GETTER_CLASS = "MemberOffsetGetter";
private static final String NATIVE_MEMBER_OFFSET_GETTER_CLASS = "NativeMemberOffsetGetter";
private static final String JAVA_MEMBER_OFFSET_GETTER_CLASS = "JavaMemberOffsetGetter";
Expand All @@ -107,6 +109,7 @@ public class StructsProcessor extends AbstractProcessor {
// Arguments
private static final String VALUE = "valueToPut";
private static final String JNI_HANDLES_ARG = "handles";
private static final String NATIVE_MEMORY_ARG = "nativeMemory";
private static final String PTR = "pointer";
private static final String MEMBER_OFFSET_GETTER_ARG = "offsetGetter";
private static final String MEMBER_INFO_PTR = "memberInfoPtr";
Expand Down Expand Up @@ -257,7 +260,7 @@ private static String generateStruct(String strName, List<String> members, List<
.inPackage(STRUCTS_PACKAGE) //
.withImportGroup(Collections.singletonList(IMPORT_BYTEBUFFER)) //
.withImportGroup(Collections.singletonList(IMPORT_TRUFFLE_OBJECT)) //
.withImportGroup(Arrays.asList(IMPORT_STATIC_OBJECT, IMPORT_JNI_HANDLES, IMPORT_RAW_POINTER));
.withImportGroup(Arrays.asList(IMPORT_STATIC_OBJECT, IMPORT_JNI_HANDLES, IMPORT_NATIVE_MEMORY, IMPORT_RAW_POINTER));

String wrapperName = className + WRAPPER;

Expand Down Expand Up @@ -324,8 +327,8 @@ private static void generateWrapper(ClassBuilder struct, List<String> members, L

MethodBuilder wrapperConstructor = new MethodBuilder(wrapperName) //
.asConstructor() //
.withParams(argument(JNI_HANDLES_CLASS, JNI_HANDLES_ARG), argument(TRUFFLE_OBJECT, PTR)) //
.addBodyLine(call(null, "super", new String[]{JNI_HANDLES_ARG, PTR, STRUCT_SIZE}), ';');
.withParams(argument(JNI_HANDLES_CLASS, JNI_HANDLES_ARG), argument(NATIVE_MEMORY_CLASS, NATIVE_MEMORY_ARG), argument(TRUFFLE_OBJECT, PTR)) //
.addBodyLine(call(null, "super", new String[]{JNI_HANDLES_ARG, NATIVE_MEMORY_ARG, PTR, STRUCT_SIZE}), ';');
wrapper.withMethod(wrapperConstructor);

for (int i = 0; i < length; i++) {
Expand Down Expand Up @@ -361,8 +364,8 @@ private static void generateWrapMethod(ClassBuilder struct, String wrapperClass)
.withOverrideAnnotation() //
.withModifiers(new ModifierBuilder().asPublic()) //
.withReturnType(wrapperClass) //
.withParams(argument(JNI_HANDLES_CLASS, JNI_HANDLES_ARG), argument(TRUFFLE_OBJECT, PTR)) //
.addBodyLine("return new ", call(null, wrapperClass, new String[]{JNI_HANDLES_ARG, PTR}), ';');
.withParams(argument(JNI_HANDLES_CLASS, JNI_HANDLES_ARG), argument(NATIVE_MEMORY_CLASS, NATIVE_MEMORY_ARG), argument(TRUFFLE_OBJECT, PTR)) //
.addBodyLine("return new ", call(null, wrapperClass, new String[]{JNI_HANDLES_ARG, NATIVE_MEMORY_ARG, PTR}), ';');
struct.withMethod(wrapMethod);
}

Expand All @@ -371,7 +374,7 @@ private static String generateStructCollector(List<String> structs) {
.withCopyright() //
.inPackage(STRUCTS_PACKAGE) //
.withImportGroup(Arrays.asList(IMPORT_INTEROP_LIBRARY, IMPORT_TRUFFLE_OBJECT)) //
.withImportGroup(Collections.singletonList(IMPORT_JNI_HANDLES));
.withImportGroup(Arrays.asList(IMPORT_JNI_HANDLES, IMPORT_NATIVE_MEMORY));

ClassBuilder structCollector = new ClassBuilder(STRUCTS_CLASS) //
.withQualifiers(new ModifierBuilder().asPublic().asFinal());
Expand All @@ -393,10 +396,11 @@ private static void generateCollectorConstructor(ClassBuilder collector, List<St
MethodBuilder constructor = new MethodBuilder(STRUCTS_CLASS) //
.asConstructor() //
.withModifiers(new ModifierBuilder().asPublic()) //
.withParams(argument(JNI_HANDLES_CLASS, JNI_HANDLES_ARG), argument(TRUFFLE_OBJECT, MEMBER_INFO_PTR), argument(TRUFFLE_OBJECT, LOOKUP_MEMBER_OFFSET)) //
.withParams(argument(JNI_HANDLES_CLASS, JNI_HANDLES_ARG), argument(NATIVE_MEMORY_CLASS, NATIVE_MEMORY_ARG), argument(TRUFFLE_OBJECT, MEMBER_INFO_PTR),
argument(TRUFFLE_OBJECT, LOOKUP_MEMBER_OFFSET)) //
.addBodyLine(INTEROP_LIBRARY, ' ', assignment(LIBRARY, call(INTEROP_LIBRARY, GET_UNCACHED, EMPTY_ARGS))) //
.addBodyLine(MEMBER_OFFSET_GETTER_CLASS, ' ', assignment(MEMBER_OFFSET_GETTER_ARG,
"new " + call(null, NATIVE_MEMBER_OFFSET_GETTER_CLASS, new String[]{LIBRARY, MEMBER_INFO_PTR, LOOKUP_MEMBER_OFFSET})));
"new " + call(null, NATIVE_MEMBER_OFFSET_GETTER_CLASS, new String[]{LIBRARY, MEMBER_INFO_PTR, LOOKUP_MEMBER_OFFSET, NATIVE_MEMORY_ARG})));

generateOptionalMemberInfo(constructor, structs);

Expand All @@ -412,7 +416,7 @@ private static void generateOptionalMemberInfo(MethodBuilder constructor, List<S
constructor.addBodyLine(assignment(decapitalize(MEMBER_INFO), "new " + call(null, MEMBER_INFO, new String[]{MEMBER_OFFSET_GETTER_ARG})));
structs.remove(MEMBER_INFO);
constructor.addBodyLine(assignment(MEMBER_OFFSET_GETTER_ARG, "new " + call(null, JAVA_MEMBER_OFFSET_GETTER_CLASS,
new String[]{JNI_HANDLES_ARG, MEMBER_INFO_PTR, "this"})));
new String[]{JNI_HANDLES_ARG, NATIVE_MEMORY_ARG, MEMBER_INFO_PTR, "this"})));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
com.oracle.truffle.espresso.ffi.nfi.NFINativeAccess$Provider
com.oracle.truffle.espresso.ffi.nfi.NFIIsolatedNativeAccess$Provider
com.oracle.truffle.espresso.ffi.nfi.NFISulongNativeAccess$Provider
com.oracle.truffle.espresso.ffi.nfi.NFISulongNativeAccess$Provider
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
com.oracle.truffle.espresso.ffi.memory.TruffleByteArrayChunkedMemoryImpl$Provider
com.oracle.truffle.espresso.ffi.memory.UnsafeByteArrayChunkedMemoryImpl$Provider
com.oracle.truffle.espresso.ffi.memory.UnsafeNativeMemory$Provider
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,12 @@ public Long apply(String size) {
usageSyntax = "<nativeBackend>") //
public static final OptionKey<String> NativeBackend = new OptionKey<>("");

@Option(help = "NativeMemory used by Espresso. Can only be specified with no-native backend where memory can be fully virtualized.", //
category = OptionCategory.EXPERT, //
stability = OptionStability.EXPERIMENTAL, //
usageSyntax = "<nativeMemory>") //
public static final OptionKey<String> NativeMemory = new OptionKey<>("");

@Option(help = "Enable use of a custom Espresso implementation of boot libraries, which allows for not entering native code.\\n" +
"Will be automatically enabled if there is NO native access.\\n" +
"For example, this will replace the usual 'libjava'. Missing implementations will thus fail with 'UnsatifiedLinkError'.", //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,19 @@

import java.nio.file.Path;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.TruffleLogger;
import com.oracle.truffle.api.interop.ArityException;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.espresso.EspressoLanguage;
import com.oracle.truffle.espresso.ffi.memory.NativeMemory;
import com.oracle.truffle.espresso.impl.ContextAccessImpl;
import com.oracle.truffle.espresso.libs.Lib;
import com.oracle.truffle.espresso.libs.Libs;
import com.oracle.truffle.espresso.libs.SubstitutionFactoryWrapper;
import com.oracle.truffle.espresso.meta.EspressoError;
import com.oracle.truffle.espresso.runtime.EspressoContext;
import com.oracle.truffle.espresso.vm.UnsafeAccess;

import sun.misc.Unsafe;

/**
* Uses Espresso's implementation of standard JDK libraries, falling back to a delegate if the
Expand All @@ -68,11 +63,6 @@
public class EspressoLibsNativeAccess extends ContextAccessImpl implements NativeAccess {

private static final TruffleLogger logger = TruffleLogger.getLogger(EspressoLanguage.ID, EspressoLibsNativeAccess.class);
/*
* Temporarily used for off-heap memory access. Will be removed with the memory virtualization
* (GR-70643)
*/
private static final Unsafe UNSAFE = UnsafeAccess.get();

private static TruffleLogger getLogger() {
return logger;
Expand Down Expand Up @@ -187,52 +177,6 @@ public SignatureCallNode createSignatureCall(NativeSignature nativeSignature) {
return delegate.createSignatureCall(nativeSignature);
}

@Override
public @Buffer TruffleObject allocateMemory(long size) {
// Will be removed with the memory virtualization (GR-70643)
long address = 0L;
try {
address = UNSAFE.allocateMemory(size);
} catch (OutOfMemoryError e) {
return null;
}
return TruffleByteBuffer.wrap(RawPointer.create(address), Math.toIntExact(size));
}

@Override
public @Buffer TruffleObject reallocateMemory(@Pointer TruffleObject buffer, long newSize) {
// Will be removed with the memory virtualization (GR-70643)
assert InteropLibrary.getUncached().isPointer(buffer);
long oldAddress = 0L;
try {
oldAddress = InteropLibrary.getUncached().asPointer(buffer);
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw EspressoError.shouldNotReachHere(e);
}
long newAddress = 0L;
try {
newAddress = UNSAFE.reallocateMemory(oldAddress, newSize);
} catch (OutOfMemoryError e) {
return null;
}
return TruffleByteBuffer.wrap(RawPointer.create(newAddress), Math.toIntExact(newSize));
}

@Override
public void freeMemory(@Pointer TruffleObject buffer) {
// Will be removed with the memory virtualization (GR-70643)
assert InteropLibrary.getUncached().isPointer(buffer);
long address = 0L;
try {
address = InteropLibrary.getUncached().asPointer(buffer);
} catch (UnsupportedMessageException e) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw EspressoError.shouldNotReachHere(e);
}
UNSAFE.freeMemory(address);
}

@Override
public @Pointer TruffleObject createNativeClosure(TruffleObject executable, NativeSignature nativeSignature) {
return delegate.createNativeClosure(executable, nativeSignature);
Expand All @@ -243,6 +187,11 @@ public void prepareThread() {
delegate.prepareThread();
}

@Override
public NativeMemory nativeMemory() {
return delegate.nativeMemory();
}

@TruffleBoundary
public boolean isKnownBootLibrary(String path) {
Path p = Path.of(path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.espresso.EspressoOptions;
import com.oracle.truffle.espresso.classfile.JavaKind;
import com.oracle.truffle.espresso.ffi.memory.NativeMemory;
import com.oracle.truffle.espresso.meta.EspressoError;
import com.oracle.truffle.espresso.runtime.EspressoProperties;

Expand Down Expand Up @@ -210,33 +211,6 @@ default boolean isBuiltIn(@SuppressWarnings("unused") String libname) {
return bindSymbol(symbol, nativeSignature);
}

/**
* Similar to malloc. The result of allocating a 0-sized buffer is an implementation detail.
*
* <h3>Lifetime
*
* @return <code>null</code> if the memory cannot be allocated. Otherwise, a
* {@link InteropLibrary#hasBufferElements(Object) buffer}.
* @throws IllegalArgumentException if the size is negative
*/
@Buffer
TruffleObject allocateMemory(long size);

/**
* Similar to realloc. The result of allocating a 0-sized buffer is an implementation detail.
*
* @return <code>null</code> if the memory cannot be re-allocated. Otherwise, a
* {@link InteropLibrary#hasBufferElements(Object) buffer}.
* @throws IllegalArgumentException if the size is negative
*/
@Buffer
TruffleObject reallocateMemory(@Pointer TruffleObject buffer, long newSize);

/**
* Similar to free. Accessing the buffer after free may cause explosive undefined behavior.
*/
void freeMemory(@Pointer TruffleObject buffer);

/**
* Sinking, make a Java method accessible to the native world. Returns an
* {@link InteropLibrary#isPointer(Object) pointer} {@link TruffleObject object}, callable from
Expand Down Expand Up @@ -292,4 +266,18 @@ interface Provider {

NativeAccess create(TruffleLanguage.Env env);
}

/**
* Retrieves the {@link NativeMemory} associated with NativeAccess.
* <p>
* <h2>Implementation notes</h2> One should be extremely careful when determining which
* NativeMemory implementation to use for a new NativeAccess implementation. Some NativeMemory
* implementations virtualize guest memory such that addresses returned by
* {@link NativeMemory#allocateMemory(long)} do not directly map to host addresses, which can be
* problematic if the accessed "native world" works directly with those addresses as if they
* were host addresses. Thus, there needs to be synergy between Java and Native reads and writes
* to native memory. If unsure, use
* {@link com.oracle.truffle.espresso.ffi.memory.UnsafeNativeMemory}.
*/
NativeMemory nativeMemory();
}
Loading