Skip to content

Commit

Permalink
Implement ByteStorage using extended UnsafeUtils and add TruffleExecu…
Browse files Browse the repository at this point in the history
…table
  • Loading branch information
MariusDoe committed Nov 11, 2023
1 parent 63632dc commit 34cafd2
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
*/
package de.hpi.swa.trufflesqueak.nodes.primitives;

import com.oracle.truffle.api.TruffleFile;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import com.oracle.truffle.api.library.ExportLibrary;
import com.oracle.truffle.api.library.ExportMessage;
import com.oracle.truffle.api.source.Source;
import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed;
import de.hpi.swa.trufflesqueak.image.SqueakImageContext;
Expand Down Expand Up @@ -56,15 +59,13 @@
import de.hpi.swa.trufflesqueak.nodes.primitives.impl.StoragePrimitives;
import de.hpi.swa.trufflesqueak.util.FrameAccess;
import de.hpi.swa.trufflesqueak.util.OS;
import de.hpi.swa.trufflesqueak.util.UnsafeUtils;
import org.graalvm.collections.EconomicMap;

import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;

public final class PrimitiveNodeFactory {
public static final int PRIMITIVE_SIMULATION_GUARD_INDEX = 19;
Expand Down Expand Up @@ -220,6 +221,57 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me
}
}

@ExportLibrary(InteropLibrary.class)
static class TruffleExecutable implements TruffleObject {
ITruffleExecutable executable;

public TruffleExecutable(ITruffleExecutable executable) {
this.executable = executable;
}

static<T, R> TruffleExecutable wrapFunction(TruffleFunction<T, R> function) {
return new TruffleExecutable(function);
}

static<R> TruffleExecutable wrapSupplier(TruffleSupplier<R> supplier) {
return new TruffleExecutable(supplier);
}

@ExportMessage
boolean isExecutable() {
return true;
}

@ExportMessage
Object execute(Object... arguments) {
return executable.execute(arguments);
}
}

interface ITruffleExecutable {
Object execute(Object... arguments);
}

@FunctionalInterface
interface TruffleFunction<T, R> extends ITruffleExecutable {
R run(T argument);

default Object execute(Object... arguments) {
assert arguments.length == 1;
return run((T) arguments[0]);
}
}

@FunctionalInterface
interface TruffleSupplier<R> extends ITruffleExecutable {
R run();

default Object execute(Object... arguments) {
assert arguments.length == 0;
return run();
}
}

static class NonExistentPrimitiveNode extends AbstractPrimitiveNode {
final String moduleName;
final String functionName;
Expand All @@ -232,31 +284,37 @@ public NonExistentPrimitiveNode(String moduleName, String functionName) {
@Override
public Object execute(VirtualFrame frame) {
final Object interpreterProxy = loadLibrary("libInterpreterProxy",
"{ createInterpreterProxy((SINT64):SINT64,(SINT64):[UINT8],(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }");
"{ createInterpreterProxy((SINT64):SINT64,(SINT64):POINTER,(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }");
final Object uuidPlugin = loadLibrary("UUIDPlugin", "{ " +
"initialiseModule():VOID; " +
"setInterpreter(POINTER):VOID; " +
"shutdownModule():VOID; " +
functionName + "():STRING; " +
"initialiseModule():SINT64; " +
"setInterpreter(POINTER):SINT64; " +
"shutdownModule():SINT64; " +
functionName + "():SINT64; " +
" }");
final InteropLibrary interpreterProxyLibrary = getInteropLibrary(interpreterProxy);
final InteropLibrary uuidPluginLibrary = getInteropLibrary(uuidPlugin);
ArrayList<PostPrimitiveCleanup> postPrimitiveCleanups = new ArrayList<>();
try {

ArrayList<Object> objectRegistry = new ArrayList<>();
Function<Integer, Integer> byteSizeOf = (index) -> 16;
Function<Integer, byte[]> firstIndexableField = (index) -> ((NativeObject)objectRegistry.get(index)).getByteStorage();
Function<Integer, Boolean> isBytes = (integer) -> true;
Supplier<Integer> majorVersion = () -> 1;
Supplier<Integer> methodArgumentCount = () -> 0;
Supplier<Integer> minorVersion = () -> 17;
Supplier<Integer> primitiveFail = () -> { assert false; return -1; };
Function<Integer, Integer> stackValue = (stackIndex) -> {
Object objectOnStack = FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame));
TruffleExecutable byteSizeOf = TruffleExecutable.wrapSupplier(() -> 16L);
TruffleExecutable firstIndexableField = TruffleExecutable.wrapFunction((index) -> {
byte[] storage = ((NativeObject) objectRegistry.get((int)(long)index)).getByteStorage();
ByteStorage byteStorage = new ByteStorage(storage);
postPrimitiveCleanups.add(byteStorage);
return byteStorage;
});
TruffleExecutable isBytes = TruffleExecutable.wrapFunction((integer) -> 1L); // true
TruffleExecutable majorVersion = TruffleExecutable.wrapSupplier(() -> 1L);
TruffleExecutable methodArgumentCount = TruffleExecutable.wrapSupplier(() -> 0L);
TruffleExecutable minorVersion = TruffleExecutable.wrapSupplier(() -> 17L);
TruffleExecutable primitiveFail = TruffleExecutable.wrapSupplier(() -> { assert false; return -1L; });
TruffleExecutable stackValue = TruffleExecutable.wrapFunction((stackIndex) -> {
Object objectOnStack = FrameAccess.getStackValue(frame, (int)(long)stackIndex, FrameAccess.getNumArguments(frame));
int objectIndex = objectRegistry.size();
objectRegistry.add(objectOnStack);
return objectIndex;
};
return (long)objectIndex;
});
final Object interpreterProxyPointer = interpreterProxyLibrary.invokeMember(
interpreterProxy,
"createInterpreterProxy",
Expand All @@ -269,7 +327,6 @@ public Object execute(VirtualFrame frame) {
primitiveFail,
stackValue);
System.out.println("interpreterProxyPointer = " + interpreterProxyPointer);

final Object initialiseOk = uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule");
System.out.println("initialiseOk = " + initialiseOk);
final Object setInterpreterOk = uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxyPointer);
Expand All @@ -282,7 +339,11 @@ public Object execute(VirtualFrame frame) {
} catch (Exception e) {
System.out.println("error");
e.printStackTrace(System.err);
return null;
throw PrimitiveFailed.GENERIC_ERROR;
} finally {
for (var postPrimitiveCleanup : postPrimitiveCleanups) {
postPrimitiveCleanup.cleanup();
}
}
}

Expand All @@ -309,6 +370,36 @@ public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArgu
}
}

interface PostPrimitiveCleanup {
void cleanup();
}

@ExportLibrary(InteropLibrary.class)
static class ByteStorage implements PostPrimitiveCleanup, TruffleObject {
byte[] storage;
public long nativeAddress;

public ByteStorage(byte[] storage) {
this.storage = storage;
nativeAddress = UnsafeUtils.allocateNativeBytes(storage);
}

@ExportMessage
public boolean isPointer() {
return true;
}

@ExportMessage
public long asPointer() {
return nativeAddress;
}

@Override
public void cleanup() {
UnsafeUtils.copyNativeBytesBackAndFree(nativeAddress, storage);
}
}

private static boolean isLoadInstVar(final int primitiveIndex) {
return PRIMITIVE_LOAD_INST_VAR_LOWER_INDEX <= primitiveIndex && primitiveIndex <= PRIMITIVE_LOAD_INST_VAR_UPPER_INDEX;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ public static void copyShorts(final short[] src, final long srcPos, final short[
dest, Unsafe.ARRAY_SHORT_BASE_OFFSET + destPos * Unsafe.ARRAY_SHORT_INDEX_SCALE, Short.BYTES * length);
}

public static long allocateNativeBytes(final byte[] src) {
final long address = UNSAFE.allocateMemory(src.length);
UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length * Byte.BYTES);
return address;
}

public static void copyNativeBytesBackAndFree(final long address, byte[] dest) {
UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_BYTE_BASE_OFFSET, dest.length * Byte.BYTES);
UNSAFE.freeMemory(address);
}

public static long fromLongsOffset(final long offset) {
return (offset - Unsafe.ARRAY_LONG_BASE_OFFSET) / Unsafe.ARRAY_LONG_INDEX_SCALE;
}
Expand Down

0 comments on commit 34cafd2

Please sign in to comment.