From a3a9490a82f2d6ea011d0d954c792aa204982175 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sun, 5 Nov 2023 22:08:30 +0100 Subject: [PATCH 001/159] [skip ci] Test NFI for non-existent named primitives --- .../primitives/PrimitiveNodeFactory.java | 117 ++++++++++++------ 1 file changed, 79 insertions(+), 38 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 941bec3f0..120a42ea7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -10,6 +10,16 @@ import java.util.List; import java.util.Set; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.nfi.backend.spi.NFIBackend; +import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.nodes.AbstractNode; import org.graalvm.collections.EconomicMap; import com.oracle.truffle.api.dsl.NodeFactory; @@ -77,45 +87,45 @@ public final class PrimitiveNodeFactory { static { final AbstractPrimitiveFactoryHolder[] indexPrimitives = { - new ArithmeticPrimitives(), - new ArrayStreamPrimitives(), - new BlockClosurePrimitives(), - new ContextPrimitives(), - new ControlPrimitives(), - new IOPrimitives(), - new MiscellaneousPrimitives(), - new StoragePrimitives()}; + new ArithmeticPrimitives(), + new ArrayStreamPrimitives(), + new BlockClosurePrimitives(), + new ContextPrimitives(), + new ControlPrimitives(), + new IOPrimitives(), + new MiscellaneousPrimitives(), + new StoragePrimitives()}; fillPrimitiveTable(indexPrimitives); final AbstractPrimitiveFactoryHolder[] plugins = { - new B2DPlugin(), - new BitBltPlugin(), - new BMPReadWriterPlugin(), - new ClipboardExtendedPlugin(), - new CroquetPlugin(), - new DropPlugin(), - new DSAPrims(), - new FilePlugin(), - new FloatArrayPlugin(), - new Float64ArrayPlugin(), - new TruffleSqueakPlugin(), - new HostWindowPlugin(), - new JPEGReaderPlugin(), - new JPEGReadWriter2Plugin(), - new LargeIntegers(), - new LocalePlugin(), - new Matrix2x3Plugin(), - new MiscPrimitivePlugin(), - new NullPlugin(), - new PolyglotPlugin(), - new SecurityPlugin(), - new SocketPlugin(), - new SoundCodecPrims(), - new SqueakFFIPrims(), - new SqueakSSL(), - new UUIDPlugin(), - new ZipPlugin(), - OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; + new B2DPlugin(), + new BitBltPlugin(), + new BMPReadWriterPlugin(), + new ClipboardExtendedPlugin(), + new CroquetPlugin(), + new DropPlugin(), + new DSAPrims(), + new FilePlugin(), + new FloatArrayPlugin(), + new Float64ArrayPlugin(), + new TruffleSqueakPlugin(), + new HostWindowPlugin(), + new JPEGReaderPlugin(), + new JPEGReadWriter2Plugin(), + new LargeIntegers(), + new LocalePlugin(), + new Matrix2x3Plugin(), + new MiscPrimitivePlugin(), + new NullPlugin(), + new PolyglotPlugin(), + new SecurityPlugin(), + new SocketPlugin(), + new SoundCodecPrims(), + new SqueakFFIPrims(), + new SqueakSSL(), + new UUIDPlugin(), + new ZipPlugin(), + OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; fillPrimitiveTable(plugins); fillPluginMap(plugins); } @@ -203,7 +213,38 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (nodeFactory != null) { return createNode(nodeFactory, location, numReceiverAndArguments); } else { - return null; + System.out.println("trying to execute " + moduleName + ":" + functionName); + + if (functionName.equals("primitivePluginVersion")) { + return null; + } + return new NonExistentPrimitiveNode(); + } + } + + static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { + @Override + public Object execute(VirtualFrame frame) { + final String nfiCode = "load \"UUIDPlugin.so\" { getModuleName():STRING; }"; + final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); + final SqueakImageContext image = getContext(); + final Object ffiTest = image.env.parseInternal(source).call(); + final InteropLibrary interopLib = InteropLibrary.getFactory().getUncached(ffiTest); + + final String name = "getModuleName"; + try { + Object returnValue = interopLib.invokeMember(ffiTest, name); + return returnValue; + + } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException | ArityException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { + return execute(frame); } } @@ -295,4 +336,4 @@ private static void addEntryToPrimitiveTable(final int index, final NodeFactory< assert !map.containsKey(numReceiverAndArguments) : "primitives are not allowed to override others (#" + index + ")"; map.put(nodeFactory.getExecutionSignature().size(), nodeFactory); } -} +} \ No newline at end of file From a5bb9a08fca5e44540e37d8b1e7a7ae4f984c9ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sun, 5 Nov 2023 22:13:39 +0100 Subject: [PATCH 002/159] [skip ci] Add initial createInterpreterProxy function in C --- .../include/sqMemoryAccess.h | 108 +++++ .../include/sqVirtualMachine.h | 379 ++++++++++++++++++ .../include/vmCallback.h | 33 ++ .../src/InterpreterProxy.c | 24 ++ 4 files changed, 544 insertions(+) create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h new file mode 100644 index 000000000..43f3e4de1 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h @@ -0,0 +1,108 @@ +#define SIZEOF_VOID_P 8 + +//////////// from here on: copied from +//////////// https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/ec421b99cf41fc5f2f5fb734b536d6233cdde809/platforms/Cross/vm/sqMemoryAccess.h + +#ifndef SIZEOF_LONG +# if LLP64 +# define SIZEOF_LONG 4 +# else +# define SIZEOF_LONG SIZEOF_VOID_P /* default is sizeof(long)==sizeof(void *) */ +# endif +#endif + +#if (SQ_VI_BYTES_PER_WORD == 4) +# define SQ_IMAGE32 1 +# define SQ_IMAGE64 0 +#else +# define SQ_IMAGE64 1 +# define SQ_IMAGE32 0 +#endif + +#if (SQ_IMAGE64 || SPURVM) +# define OBJECTS_64BIT_ALIGNED 1 +# define OBJECTS_32BIT_ALIGNED 0 +#else +# define OBJECTS_32BIT_ALIGNED 1 +# define OBJECTS_64BIT_ALIGNED 0 +#endif + +#if (SIZEOF_VOID_P == 4) +# define SQ_HOST32 1 +#elif (SIZEOF_VOID_P == 8) +# define SQ_HOST64 1 +#else +# error host is neither 32- nor 64-bit? +#endif + +/* sqInt is a signed integer with size adequate for holding an Object Oriented Pointer (or immediate value) + - that is 32bits long on a 32bits image or 64bits long on a 64bits image + we could use C99 int32_t and int64_t once retiring legacy compiler support this time has not yet come + usqInt is the unsigned flavour + SQABS is a macro for taking absolute value of an sqInt */ +#if SQ_IMAGE32 + typedef int sqInt; + typedef unsigned int usqInt; +#define PRIdSQINT "d" +#define PRIuSQINT "u" +#define PRIxSQINT "x" +#define PRIXSQINT "X" +# define SQABS abs +#elif SQ_HOST64 && (SIZEOF_LONG == 8) + typedef long sqInt; + typedef unsigned long usqInt; +#define PRIdSQINT "ld" +#define PRIuSQINT "lu" +#define PRIxSQINT "lx" +#define PRIXSQINT "lX" +# define SQABS labs +#elif (SIZEOF_LONG_LONG != 8) +# error long long integers are not 64-bits wide? +#else + typedef long long sqInt; + typedef unsigned long long usqInt; +#define PRIdSQINT "lld" +#define PRIuSQINT "llu" +#define PRIxSQINT "llx" +#define PRIXSQINT "llX" +# define SQABS llabs +#endif + +/* sqLong is a signed integer with at least 64bits on both 32 and 64 bits images + usqLong is the unsigned flavour + SQLABS is a macro for taking absolute value of a sqLong */ +#if !defined(sqLong) +# if SIZEOF_LONG == 8 +# define sqLong long +# define usqLong unsigned long +# define SQLABS labs +# elif _MSC_VER +# define sqLong __int64 +# define usqLong unsigned __int64 +# define SQLABS llabs +# else +# define sqLong long long +# define usqLong unsigned long long +# define SQLABS llabs +# endif +#endif /* !defined(sqLong) */ + +/* sqIntptr_t is a signed integer with enough bits to hold a pointer + usqIntptr_t is the unsigned flavour + this is essentially C99 intptr_t and uintptr_t but we support legacy compilers + the C99 printf formats macros are also defined with SQ prefix */ +#if SIZEOF_LONG == SIZEOF_VOID_P +typedef long sqIntptr_t; +typedef unsigned long usqIntptr_t; +#define PRIdSQPTR "ld" +#define PRIuSQPTR "lu" +#define PRIxSQPTR "lx" +#define PRIXSQPTR "lX" +#else +typedef long long sqIntptr_t; +typedef unsigned long long usqIntptr_t; +#define PRIdSQPTR "lld" +#define PRIuSQPTR "llu" +#define PRIxSQPTR "llx" +#define PRIXSQPTR "llX" +#endif diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h new file mode 100644 index 000000000..63143b70c --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h @@ -0,0 +1,379 @@ +#include "vmCallback.h" + +//////////// from here on: copied from +//////////// https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/ec421b99cf41fc5f2f5fb734b536d6233cdde809/platforms/Cross/vm/sqVirtualMachine.h + +#if SPURVM +# define VM_VERSION "5.0" +#else +# define VM_VERSION "4.5" +#endif + +#ifndef VM_PROXY_MAJOR +/* Increment the following number if you change the order of + functions listed or if you remove functions */ +# define VM_PROXY_MAJOR 1 +#endif + +#ifndef VM_PROXY_MINOR +/* Increment the following number if you add functions at the end */ +# if SPURVM +# define VM_PROXY_MINOR 13 +# else +# define VM_PROXY_MINOR 12 +# endif +#endif + +#include "sqMemoryAccess.h" + +#if VM_PROXY_MINOR > 8 +// Primitive error codes; see interp.h +# define PrimNoErr 0 + +/* VMCallbackContext opaque type avoids all including setjmp.h & vmCallback.h */ +typedef struct _VMCallbackContext *vmccp; +#endif + +typedef sqInt (*CompilerHook)(void); + +typedef struct VirtualMachine { + sqInt (*minorVersion)(void); + sqInt (*majorVersion)(void); + + /* InterpreterProxy methodsFor: 'stack access' */ + + sqInt (*pop)(sqInt nItems); + sqInt (*popthenPush)(sqInt nItems, sqInt oop); + sqInt (*push)(sqInt object); + sqInt (*pushBool)(sqInt trueOrFalse); + sqInt (*pushFloat)(double f); + sqInt (*pushInteger)(sqInt integerValue); + double (*stackFloatValue)(sqInt offset); + sqInt (*stackIntegerValue)(sqInt offset); + sqInt (*stackObjectValue)(sqInt offset); + sqInt (*stackValue)(sqInt offset); + + /* InterpreterProxy methodsFor: 'object access' */ + + sqInt (*argumentCountOf)(sqInt methodPointer); + void *(*arrayValueOf)(sqInt oop); + sqInt (*byteSizeOf)(sqInt oop); + void *(*fetchArrayofObject)(sqInt fieldIndex, sqInt objectPointer); + sqInt (*fetchClassOf)(sqInt oop); + double (*fetchFloatofObject)(sqInt fieldIndex, sqInt objectPointer); + sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer); + sqInt (*fetchPointerofObject)(sqInt fieldIndex, sqInt oop); +#if OLD_FOR_REFERENCE +/* sqInt (*fetchWordofObject)(sqInt fieldFieldIndex, sqInt oop); * + * has been rescinded as of VMMaker 3.8 and the 64bitclean VM * + * work. To support old plugins we keep a valid function in * + * the same location in the VM struct but rename it to * + * something utterly horrible to scare off the natives. A new * + * equivalent but 64 bit valid function is added as * + * 'fetchLong32OfObject' */ + sqInt (*obsoleteDontUseThisFetchWordofObject)(sqInt fieldFieldIndex, sqInt oop); +#else /* since there is no legacy plugin problem back to 3.8 we repurpose... */ + void (*error)(const char *); +#endif + void *(*firstFixedField)(sqInt oop); + void *(*firstIndexableField)(sqInt oop); + sqInt (*literalofMethod)(sqInt offset, sqInt methodPointer); + sqInt (*literalCountOf)(sqInt methodPointer); + sqInt (*methodArgumentCount)(void); + sqInt (*methodPrimitiveIndex)(void); + sqInt (*primitiveIndexOf)(sqInt methodPointer); + sqInt (*sizeOfSTArrayFromCPrimitive)(void *cPtr); + sqInt (*slotSizeOf)(sqInt oop); + sqInt (*stObjectat)(sqInt array, sqInt fieldIndex); + sqInt (*stObjectatput)(sqInt array, sqInt fieldIndex, sqInt value); + sqInt (*stSizeOf)(sqInt oop); + sqInt (*storeIntegerofObjectwithValue)(sqInt fieldIndex, sqInt oop, sqInt integer); + sqInt (*storePointerofObjectwithValue)(sqInt fieldIndex, sqInt oop, sqInt valuePointer); + + /* InterpreterProxy methodsFor: 'testing' */ + + sqInt (*isKindOf)(sqInt oop, char *aString); + sqInt (*isMemberOf)(sqInt oop, char *aString); + sqInt (*isBytes)(sqInt oop); + sqInt (*isFloatObject)(sqInt oop); + sqInt (*isIndexable)(sqInt oop); + sqInt (*isIntegerObject)(sqInt oop); + sqInt (*isIntegerValue)(sqInt intValue); + sqInt (*isPointers)(sqInt oop); + sqInt (*isWeak)(sqInt oop); + sqInt (*isWords)(sqInt oop); + sqInt (*isWordsOrBytes)(sqInt oop); + + /* InterpreterProxy methodsFor: 'converting' */ + + sqInt (*booleanValueOf)(sqInt obj); + sqInt (*checkedIntegerValueOf)(sqInt intOop); + sqInt (*floatObjectOf)(double aFloat); + double (*floatValueOf)(sqInt oop); + sqInt (*integerObjectOf)(sqInt value); + sqInt (*integerValueOf)(sqInt oop); + sqInt (*positive32BitIntegerFor)(unsigned int integerValue); + usqInt (*positive32BitValueOf)(sqInt oop); + + /* InterpreterProxy methodsFor: 'special objects' */ + + sqInt (*characterTable)(void); + sqInt (*displayObject)(void); + sqInt (*falseObject)(void); + sqInt (*nilObject)(void); + sqInt (*trueObject)(void); + + /* InterpreterProxy methodsFor: 'special classes' */ + + sqInt (*classArray)(void); + sqInt (*classBitmap)(void); + sqInt (*classByteArray)(void); + sqInt (*classCharacter)(void); + sqInt (*classFloat)(void); + sqInt (*classLargePositiveInteger)(void); + sqInt (*classPoint)(void); + sqInt (*classSemaphore)(void); + sqInt (*classSmallInteger)(void); + sqInt (*classString)(void); + + /* InterpreterProxy methodsFor: 'instance creation' */ + + sqInt (*cloneObject)(sqInt oop); + sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size); + sqInt (*makePointwithxValueyValue)(sqInt xValue, sqInt yValue); + sqInt (*popRemappableOop)(void); + sqInt (*pushRemappableOop)(sqInt oop); + + /* InterpreterProxy methodsFor: 'other' */ + + sqInt (*becomewith)(sqInt array1, sqInt array2); + sqInt (*byteSwapped)(sqInt w); + sqInt (*failed)(void); + sqInt (*fullDisplayUpdate)(void); + void (*fullGC)(void); + void (*incrementalGC)(void); + sqInt (*primitiveFail)(void); + sqInt (*showDisplayBitsLeftTopRightBottom)(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b); + sqInt (*signalSemaphoreWithIndex)(sqInt semaIndex); + sqInt (*success)(sqInt aBoolean); + sqInt (*superclassOf)(sqInt classPointer); + +# if VM_PROXY_MINOR > 13 + /* Reuse these now that Cog provides a production JIT. */ + sqInt (*statNumGCs)(void); + sqInt (*stringForCString)(char *nullTerminatedCString); +# else + /* InterpreterProxy methodsFor: 'compiler' */ + + CompilerHook *(*compilerHookVector)(void); + sqInt (*setCompilerInitialized)(sqInt initFlag); +# endif + +#if VM_PROXY_MINOR > 1 + + /* InterpreterProxy methodsFor: 'BitBlt support' */ + + sqInt (*loadBitBltFrom)(sqInt bbOop); + sqInt (*copyBits)(void); + sqInt (*copyBitsFromtoat)(sqInt leftX, sqInt rightX, sqInt yValue); + +#endif + +#if VM_PROXY_MINOR > 2 + + sqInt (*classLargeNegativeInteger)(void); + sqInt (*signed32BitIntegerFor)(sqInt integerValue); + int (*signed32BitValueOf)(sqInt oop); + sqInt (*includesBehaviorThatOf)(sqInt aClass, sqInt aSuperClass); + sqInt (*primitiveMethod)(void); + + /* InterpreterProxy methodsFor: 'FFI support' */ + + sqInt (*classExternalAddress)(void); + sqInt (*classExternalData)(void); + sqInt (*classExternalFunction)(void); + sqInt (*classExternalLibrary)(void); + sqInt (*classExternalStructure)(void); + void *(*ioLoadModuleOfLength)(sqInt modIndex, sqInt modLength); + void *(*ioLoadSymbolOfLengthFromModule)(sqInt fnIndex, sqInt fnLength, void *handle); + sqInt (*isInMemory)(sqInt address); + +#endif + +#if VM_PROXY_MINOR > 3 + + void *(*ioLoadFunctionFrom)(char *fnName, char *modName); + unsigned int (*ioMicroMSecs)(void); + +#endif + +#if VM_PROXY_MINOR > 4 + +# if !defined(sqLong) +# if _MSC_VER +# define sqLong __int64 +# define usqLong unsigned __int64 +# else +# define sqLong long long +# define usqLong unsigned long long +# endif +# endif + + sqInt (*positive64BitIntegerFor)(usqLong integerValue); + usqLong(*positive64BitValueOf)(sqInt oop); + sqInt (*signed64BitIntegerFor)(sqLong integerValue); + sqLong (*signed64BitValueOf)(sqInt oop); + +#endif + +#if VM_PROXY_MINOR > 5 + sqInt (*isArray)(sqInt oop); + void (*forceInterruptCheck)(void); +#endif + +#if VM_PROXY_MINOR > 6 + sqInt (*fetchLong32ofObject)(sqInt fieldFieldIndex, sqInt oop); + sqInt (*getThisSessionID)(void); + sqInt (*ioFilenamefromStringofLengthresolveAliases)(char* aCharBuffer, char* filenameIndex, sqInt filenameLength, sqInt resolveFlag); + sqInt (*vmEndianness)(void); +#endif + +#if VM_PROXY_MINOR > 7 + /* New methods for proxy version 1.8 */ + + /* callbackEnter: Re-enter the interpreter loop for a callback. + Arguments: + callbackID: Pointer to a location receiving the callback ID + used in callbackLeave + Returns: True if successful, false otherwise */ + sqInt (*callbackEnter)(sqInt *callbackID); + +#if OLD_FOR_REFERENCE + /* N.B. callbackLeave is only ever called from the interpreter. Further, it + * and callbackEnter are obsoleted by Alien/FFI callbacks that are simpler + * and faster. + */ + /* callbackLeave: Leave the interpreter from a previous callback + Arguments: + callbackID: The ID of the callback received from callbackEnter() + Returns: True if succcessful, false otherwise. */ + sqInt (*callbackLeave)(sqInt callbackID); +#else + sqInt (*primitiveFailForwithSecondary)(sqInt failCode, sqLong secondaryCode); +#endif + + /* addGCRoot: Add a variable location to the garbage collector. + The contents of the variable location will be updated accordingly. + Arguments: + varLoc: Pointer to the variable location + Returns: True if successful, false otherwise. */ + sqInt (*addGCRoot)(sqInt *varLoc); + + /* removeGCRoot: Remove a variable location from the garbage collector. + Arguments: + varLoc: Pointer to the variable location + Returns: True if successful, false otherwise. + */ + sqInt (*removeGCRoot)(sqInt *varLoc); +#endif + +#if VM_PROXY_MINOR > 8 + /* See interp.h and above for standard error codes. */ + sqInt (*primitiveFailFor)(sqInt code); + void *(*setInterruptCheckChain)(void (*aFunction)(void)); + sqInt (*classAlien)(void); + sqInt (*classUnsafeAlien)(void); +# if OLD_FOR_REFERENCE /* slot repurposed for storeLong32ofObjectwithValue */ + sqInt (*sendInvokeCallbackStackRegistersJmpbuf)(sqInt thunkPtrAsInt, sqInt stackPtrAsInt, sqInt regsPtrAsInt, sqInt jmpBufPtrAsInt); +# else + usqInt (*storeLong32ofObjectwithValue)(sqInt index, sqInt oop, usqInt); +# endif + sqInt (*reestablishContextPriorToCallback)(sqInt callbackContext); + sqInt *(*getStackPointer)(void); + sqInt (*isOopImmutable)(sqInt oop); + sqInt (*isOopMutable)(sqInt oop); +#endif + +#if VM_PROXY_MINOR > 9 +# if VM_PROXY_MINOR > 13 /* OS Errors available in primitives; easy return forms */ + sqInt (*methodReturnBool)(sqInt); + sqInt (*methodReturnFloat)(double); + sqInt (*methodReturnInteger)(sqInt); + sqInt (*methodReturnString)(char *); +# define returnSelf() methodReturnValue(0) +# else + sqInt (*methodArg) (sqInt index); /* These ended up never being used. */ + sqInt (*objectArg) (sqInt index); + sqInt (*integerArg) (sqInt index); + double (*floatArg) (sqInt index); +# endif + sqInt (*methodReturnValue) (sqInt oop); + sqInt (*topRemappableOop) (void); +#endif + +#if VM_PROXY_MINOR > 10 + sqInt (*disownVM)(sqInt flags); + sqInt (*ownVM) (sqInt threadIdAndFlags); + void (*addHighPriorityTickee)(void (*ticker)(void), unsigned periodms); + void (*addSynchronousTickee)(void (*ticker)(void), unsigned periodms, unsigned roundms); + usqLong (*utcMicroseconds)(void); + void (*tenuringIncrementalGC)(void); + sqInt (*isYoung) (sqInt anOop); + sqInt (*isKindOfClass)(sqInt oop, sqInt aClass); + sqInt (*primitiveErrorTable)(void); + sqInt (*primitiveFailureCode)(void); + sqInt (*instanceSizeOf)(sqInt aClass); +#endif + +#if VM_PROXY_MINOR > 11 +/* VMCallbackContext opaque type avoids all including setjmp.h & vmCallback.h */ + sqInt (*sendInvokeCallbackContext)(vmccp); + sqInt (*returnAsThroughCallbackContext)(sqInt, vmccp, sqInt); + sqIntptr_t (*signedMachineIntegerValueOf)(sqInt); + sqIntptr_t (*stackSignedMachineIntegerValue)(sqInt); + usqIntptr_t (*positiveMachineIntegerValueOf)(sqInt); + usqIntptr_t (*stackPositiveMachineIntegerValue)(sqInt); + sqInt (*getInterruptPending)(void); + char *(*cStringOrNullFor)(sqInt); + void *(*startOfAlienData)(sqInt); + usqInt (*sizeOfAlienData)(sqInt); + sqInt (*signalNoResume)(sqInt); +#endif + +#if VM_PROXY_MINOR > 12 /* Spur */ + sqInt (*isImmediate)(sqInt objOop); + sqInt (*characterObjectOf)(int charCode); + sqInt (*characterValueOf)(sqInt objOop); + sqInt (*isCharacterObject)(sqInt objOop); + sqInt (*isCharacterValue)(int charCode); + sqInt (*isPinned)(sqInt objOop); + sqInt (*pinObject)(sqInt objOop); + sqInt (*unpinObject)(sqInt objOop); +#endif + +#if VM_PROXY_MINOR > 13 /* OS Errors available in primitives; easy return forms (see above) */ + sqInt (*primitiveFailForOSError)(sqLong osErrorCode); + sqInt (*methodReturnReceiver)(void); + sqInt (*primitiveFailForFFIExceptionat)(usqLong exceptionCode, usqInt pc); +#endif + +#if VM_PROXY_MINOR > 14 /* SmartSyntaxPlugin validation rewrite support */ + sqInt (*isBooleanObject)(sqInt oop); + sqInt (*isPositiveMachineIntegerObject)(sqInt); +#endif +#if VM_PROXY_MINOR > 15 /* Spur integer and float array classes */ + sqInt (*classDoubleByteArray)(void); + sqInt (*classWordArray)(void); + sqInt (*classDoubleWordArray)(void); + sqInt (*classFloat32Array)(void); + sqInt (*classFloat64Array)(void); +#endif +#if VM_PROXY_MINOR > 16 /* Spur isShorts, isLong64s testing, hash etc */ + sqInt (*isShorts)(sqInt oop); + sqInt (*isLong64s)(sqInt oop); + sqInt (*identityHashOf)(sqInt oop); + sqInt (*isWordsOrShorts)(sqInt oop); /* for SoundPlugin et al */ + sqInt (*bytesPerElement)(sqInt oop); /* for SocketPugin et al */ + sqInt (*fileTimesInUTC)(void); /* for FilePlugin et al */ +#endif +} VirtualMachine; diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h new file mode 100644 index 000000000..2ee037cf6 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h @@ -0,0 +1,33 @@ +#include +#include "sqMemoryAccess.h" + +/* Automatically generated by + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3150 uuid: 832f44e4-6d22-4545-ae94-d8453b49d54f + */ + +#define VM_CALLBACK_INC 1 + +typedef struct _VMCallbackContext { + void *thunkp; + sqIntptr_t *stackp; + sqIntptr_t *intregargsp; + double *floatregargsp; + void *savedCStackPointer; + void *savedCFramePointer; + union { + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + }rvs; + void *savedMostRecentCallbackContext; + jmp_buf trampoline; + jmp_buf savedReenterInterpreter; + } VMCallbackContext; + +/* The callback return type codes */ +#define retword 1 +#define retword64 2 +#define retdouble 3 +#define retstruct 4 diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c new file mode 100644 index 000000000..bdc0adde5 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -0,0 +1,24 @@ +#include +#include "sqVirtualMachine.h" + +VirtualMachine* createInterpreterProxy( + sqInt (*byteSizeOf)(sqInt oop), + void *(*firstIndexableField)(sqInt oop), + sqInt (*isBytes)(sqInt oop), + sqInt (*majorVersion)(void), + sqInt (*methodArgumentCount)(void), + sqInt (*minorVersion)(void), + sqInt (*primitiveFail)(void), + sqInt (*stackValue)(sqInt offset) +) { + VirtualMachine* interpreterProxy = (VirtualMachine*)calloc(1, sizeof(VirtualMachine)); + interpreterProxy->byteSizeOf = byteSizeOf; + interpreterProxy->firstIndexableField = firstIndexableField; + interpreterProxy->isBytes = isBytes; + interpreterProxy->majorVersion = majorVersion; + interpreterProxy->methodArgumentCount = methodArgumentCount; + interpreterProxy->minorVersion = minorVersion; + interpreterProxy->primitiveFail = primitiveFail; + interpreterProxy->stackValue = stackValue; + return interpreterProxy; +} From 63632dcbb9467bc8e928c6f15cf7baf29ccb0fe1 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Fri, 10 Nov 2023 11:08:23 +0100 Subject: [PATCH 003/159] Add stub methods for interpreter proxy [skip ci] --- .../primitives/PrimitiveNodeFactory.java | 117 +++++++++++++----- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 120a42ea7..1b203314d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -6,24 +6,13 @@ */ package de.hpi.swa.trufflesqueak.nodes.primitives; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - +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.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnknownIdentifierException; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.nfi.backend.spi.NFIBackend; +import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; -import de.hpi.swa.trufflesqueak.nodes.AbstractNode; -import org.graalvm.collections.EconomicMap; - -import com.oracle.truffle.api.dsl.NodeFactory; - import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.NativeObject; @@ -53,7 +42,6 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakFFIPrims; import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakSSL; import de.hpi.swa.trufflesqueak.nodes.plugins.TruffleSqueakPlugin; -import de.hpi.swa.trufflesqueak.nodes.plugins.UUIDPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.UnixOSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.Win32OSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ZipPlugin; @@ -66,7 +54,17 @@ import de.hpi.swa.trufflesqueak.nodes.primitives.impl.IOPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.MiscellaneousPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.StoragePrimitives; +import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.OS; +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; @@ -123,7 +121,7 @@ public final class PrimitiveNodeFactory { new SoundCodecPrims(), new SqueakFFIPrims(), new SqueakSSL(), - new UUIDPlugin(), + //new UUIDPlugin(), new ZipPlugin(), OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; fillPrimitiveTable(plugins); @@ -218,30 +216,93 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (functionName.equals("primitivePluginVersion")) { return null; } - return new NonExistentPrimitiveNode(); + return new NonExistentPrimitiveNode(moduleName, functionName); } } static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { + final String moduleName; + final String functionName; + + public NonExistentPrimitiveNode(String moduleName, String functionName) { + this.moduleName = moduleName; + this.functionName = functionName; + } + @Override public Object execute(VirtualFrame frame) { - final String nfiCode = "load \"UUIDPlugin.so\" { getModuleName():STRING; }"; - final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); - final SqueakImageContext image = getContext(); - final Object ffiTest = image.env.parseInternal(source).call(); - final InteropLibrary interopLib = InteropLibrary.getFactory().getUncached(ffiTest); - - final String name = "getModuleName"; + final Object interpreterProxy = loadLibrary("libInterpreterProxy", + "{ createInterpreterProxy((SINT64):SINT64,(SINT64):[UINT8],(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }"); + final Object uuidPlugin = loadLibrary("UUIDPlugin", "{ " + + "initialiseModule():VOID; " + + "setInterpreter(POINTER):VOID; " + + "shutdownModule():VOID; " + + functionName + "():STRING; " + + " }"); + final InteropLibrary interpreterProxyLibrary = getInteropLibrary(interpreterProxy); + final InteropLibrary uuidPluginLibrary = getInteropLibrary(uuidPlugin); try { - Object returnValue = interopLib.invokeMember(ffiTest, name); - return returnValue; - } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException | ArityException e) { - e.printStackTrace(); + ArrayList objectRegistry = new ArrayList<>(); + Function byteSizeOf = (index) -> 16; + Function firstIndexableField = (index) -> ((NativeObject)objectRegistry.get(index)).getByteStorage(); + Function isBytes = (integer) -> true; + Supplier majorVersion = () -> 1; + Supplier methodArgumentCount = () -> 0; + Supplier minorVersion = () -> 17; + Supplier primitiveFail = () -> { assert false; return -1; }; + Function stackValue = (stackIndex) -> { + Object objectOnStack = FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); + int objectIndex = objectRegistry.size(); + objectRegistry.add(objectOnStack); + return objectIndex; + }; + final Object interpreterProxyPointer = interpreterProxyLibrary.invokeMember( + interpreterProxy, + "createInterpreterProxy", + byteSizeOf, + firstIndexableField, + isBytes, + majorVersion, + methodArgumentCount, + minorVersion, + 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); + System.out.println("setInterpreterOk = " + setInterpreterOk); + final Object result = uuidPluginLibrary.invokeMember(uuidPlugin, functionName); + System.out.println("result = " + result); + final Object shutdownOk = uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); + System.out.println("shutdownOk = " + shutdownOk); + return result; + } catch (Exception e) { + System.out.println("error"); + e.printStackTrace(System.err); return null; } } + private Object loadLibrary(String moduleName, String boundSymbols) { + final SqueakImageContext image = getContext(); + final String libName = System.mapLibraryName(moduleName); + final TruffleFile libPath = image.getHomePath().resolve("lib" + File.separatorChar + libName); + if (!libPath.exists()) { + throw PrimitiveFailed.GENERIC_ERROR; + } + + final String nfiCode = "load \"" + libPath.getPath() + "\" " + boundSymbols; + final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); + return image.env.parseInternal(source).call(); + } + + private InteropLibrary getInteropLibrary(Object loadedLibrary) { + return InteropLibrary.getFactory().getUncached(loadedLibrary); + } + @Override public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { return execute(frame); From 34cafd21ca385fff59103143a3a447300f89b3d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 11 Nov 2023 16:25:36 +0100 Subject: [PATCH 004/159] Implement ByteStorage using extended UnsafeUtils and add TruffleExecutable --- .../primitives/PrimitiveNodeFactory.java | 135 +++++++++++++++--- .../swa/trufflesqueak/util/UnsafeUtils.java | 11 ++ 2 files changed, 124 insertions(+), 22 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 1b203314d..80b8b5dcc 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -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; @@ -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; @@ -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 TruffleExecutable wrapFunction(TruffleFunction function) { + return new TruffleExecutable(function); + } + + static TruffleExecutable wrapSupplier(TruffleSupplier 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 extends ITruffleExecutable { + R run(T argument); + + default Object execute(Object... arguments) { + assert arguments.length == 1; + return run((T) arguments[0]); + } + } + + @FunctionalInterface + interface TruffleSupplier 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; @@ -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 postPrimitiveCleanups = new ArrayList<>(); try { ArrayList objectRegistry = new ArrayList<>(); - Function byteSizeOf = (index) -> 16; - Function firstIndexableField = (index) -> ((NativeObject)objectRegistry.get(index)).getByteStorage(); - Function isBytes = (integer) -> true; - Supplier majorVersion = () -> 1; - Supplier methodArgumentCount = () -> 0; - Supplier minorVersion = () -> 17; - Supplier primitiveFail = () -> { assert false; return -1; }; - Function 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", @@ -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); @@ -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(); + } } } @@ -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; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java index 324f0f31d..aea73e632 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java @@ -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; } From a4a53ade62e56c3e501be160ebaf7c1a6825ff4c Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 15 Nov 2023 14:50:25 +0100 Subject: [PATCH 005/159] Set absolute library path (for now) [skip ci] --- .../nodes/primitives/PrimitiveNodeFactory.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 80b8b5dcc..c90332892 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -10,12 +10,10 @@ 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; import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.NativeObject; @@ -306,15 +304,16 @@ public Object execute(VirtualFrame frame) { }); TruffleExecutable isBytes = TruffleExecutable.wrapFunction((integer) -> 1L); // true TruffleExecutable majorVersion = TruffleExecutable.wrapSupplier(() -> 1L); - TruffleExecutable methodArgumentCount = TruffleExecutable.wrapSupplier(() -> 0L); + TruffleExecutable methodArgumentCount = TruffleExecutable.wrapSupplier(() -> 0L) ; TruffleExecutable minorVersion = TruffleExecutable.wrapSupplier(() -> 17L); - TruffleExecutable primitiveFail = TruffleExecutable.wrapSupplier(() -> { assert false; return -1L; }); + TruffleExecutable primitiveFail = TruffleExecutable.wrapSupplier(() -> { throw PrimitiveFailed.GENERIC_ERROR; }); TruffleExecutable stackValue = TruffleExecutable.wrapFunction((stackIndex) -> { Object objectOnStack = FrameAccess.getStackValue(frame, (int)(long)stackIndex, FrameAccess.getNumArguments(frame)); int objectIndex = objectRegistry.size(); objectRegistry.add(objectOnStack); return (long)objectIndex; }); + final Object interpreterProxyPointer = interpreterProxyLibrary.invokeMember( interpreterProxy, "createInterpreterProxy", @@ -348,16 +347,9 @@ public Object execute(VirtualFrame frame) { } private Object loadLibrary(String moduleName, String boundSymbols) { - final SqueakImageContext image = getContext(); - final String libName = System.mapLibraryName(moduleName); - final TruffleFile libPath = image.getHomePath().resolve("lib" + File.separatorChar + libName); - if (!libPath.exists()) { - throw PrimitiveFailed.GENERIC_ERROR; - } - - final String nfiCode = "load \"" + libPath.getPath() + "\" " + boundSymbols; + final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); - return image.env.parseInternal(source).call(); + return getContext().env.parseInternal(source).call(); } private InteropLibrary getInteropLibrary(Object loadedLibrary) { From bb0e12b426ca13df90ebd840fa9727ab48cb4c67 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 15 Nov 2023 16:39:26 +0100 Subject: [PATCH 006/159] Create InterpreterProxy and extract inner classes --- .../nodes/plugins/ffi/InterpreterProxy.java | 94 +++++++++++ .../plugins/ffi/wrappers/ByteStorage.java | 34 ++++ .../primitives/PrimitiveNodeFactory.java | 157 ++---------------- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 85 ++++++++++ 4 files changed, 225 insertions(+), 145 deletions(-) create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java new file mode 100644 index 000000000..5dc516cb4 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -0,0 +1,94 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; + +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; +import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; +import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.model.NativeObject; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.ByteStorage; +import de.hpi.swa.trufflesqueak.util.FrameAccess; +import de.hpi.swa.trufflesqueak.util.NFIUtils; + +import java.util.ArrayList; + +public class InterpreterProxy { + + private final VirtualFrame frame; + private final ArrayList objectRegistry = new ArrayList<>(); + private final ArrayList postPrimitiveCleanups = new ArrayList<>(); + + private static Object interpreterProxyPointer = null; + + public InterpreterProxy(SqueakImageContext context, VirtualFrame frame) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + this.frame = frame; + if (interpreterProxyPointer == null) { + final Object interpreterProxy = NFIUtils.loadLibrary( + context, + "InterpreterProxy.so", + "{ createInterpreterProxy((SINT64):SINT64,(SINT64):POINTER,(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }" + ); + + final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); + interpreterProxyPointer = interpreterProxyLibrary.invokeMember( + interpreterProxy,"createInterpreterProxy", (Object[]) getExecutables()); + } + } + public Object getPointer() { + return interpreterProxyPointer; + } + + public NFIUtils.TruffleExecutable[] getExecutables() { + return new NFIUtils.TruffleExecutable[] { + NFIUtils.TruffleExecutable.wrap(this::byteSizeOf), + NFIUtils.TruffleExecutable.wrap(this::firstIndexableField), + NFIUtils.TruffleExecutable.wrap(this::isBytes), + NFIUtils.TruffleExecutable.wrap(this::majorVersion), + NFIUtils.TruffleExecutable.wrap(this::methodArgumentCount), + NFIUtils.TruffleExecutable.wrap(this::minorVersion), + NFIUtils.TruffleExecutable.wrap(this::primitiveFail), + NFIUtils.TruffleExecutable.wrap(this::stackValue), + }; + } + public void postPrimitiveCleanups() { + postPrimitiveCleanups.forEach(de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup::cleanup); + } + + private int byteSizeOf() { + return 16; + } + private ByteStorage firstIndexableField(long index) { + byte[] storage = ((NativeObject) objectRegistry.get((int) index)).getByteStorage(); + ByteStorage byteStorage = new ByteStorage(storage); + postPrimitiveCleanups.add(byteStorage); + return byteStorage; + } + private int isBytes(long oop) { + return 1; + } + private int majorVersion() { + return 1; + } + private int methodArgumentCount() { + return FrameAccess.getNumArguments(frame); + } + private int minorVersion() { + return 17; + } + private int primitiveFail() { + throw PrimitiveFailed.GENERIC_ERROR; + } + private int stackValue(long stackIndex) { + Object objectOnStack = FrameAccess.getStackValue(frame, (int) stackIndex, FrameAccess.getNumArguments(frame)); + int objectIndex = objectRegistry.size(); + objectRegistry.add(objectOnStack); + return objectIndex; + } + + public interface PostPrimitiveCleanup { + void cleanup(); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java new file mode 100644 index 000000000..df2703dac --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -0,0 +1,34 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public 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); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index c90332892..df9553a79 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -9,10 +9,6 @@ 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.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.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; @@ -46,6 +42,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.UnixOSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.Win32OSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ZipPlugin; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy; import de.hpi.swa.trufflesqueak.nodes.plugins.network.SocketPlugin; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArithmeticPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArrayStreamPrimitives; @@ -55,12 +52,10 @@ import de.hpi.swa.trufflesqueak.nodes.primitives.impl.IOPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.MiscellaneousPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.StoragePrimitives; -import de.hpi.swa.trufflesqueak.util.FrameAccess; +import de.hpi.swa.trufflesqueak.util.NFIUtils; import de.hpi.swa.trufflesqueak.util.OS; -import de.hpi.swa.trufflesqueak.util.UnsafeUtils; import org.graalvm.collections.EconomicMap; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -219,57 +214,6 @@ 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 TruffleExecutable wrapFunction(TruffleFunction function) { - return new TruffleExecutable(function); - } - - static TruffleExecutable wrapSupplier(TruffleSupplier 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 extends ITruffleExecutable { - R run(T argument); - - default Object execute(Object... arguments) { - assert arguments.length == 1; - return run((T) arguments[0]); - } - } - - @FunctionalInterface - interface TruffleSupplier 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; @@ -281,117 +225,40 @@ public NonExistentPrimitiveNode(String moduleName, String functionName) { @Override public Object execute(VirtualFrame frame) { - final Object interpreterProxy = loadLibrary("libInterpreterProxy", - "{ createInterpreterProxy((SINT64):SINT64,(SINT64):POINTER,(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }"); - final Object uuidPlugin = loadLibrary("UUIDPlugin", "{ " + + final Object uuidPlugin = NFIUtils.loadLibrary(getContext(), "UUIDPlugin.so", "{ " + "initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + "shutdownModule():SINT64; " + functionName + "():SINT64; " + " }"); - final InteropLibrary interpreterProxyLibrary = getInteropLibrary(interpreterProxy); - final InteropLibrary uuidPluginLibrary = getInteropLibrary(uuidPlugin); - ArrayList postPrimitiveCleanups = new ArrayList<>(); + final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); + InterpreterProxy interpreterProxy = null; try { + interpreterProxy = new InterpreterProxy(getContext(), frame); - ArrayList objectRegistry = new ArrayList<>(); - 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(() -> { throw PrimitiveFailed.GENERIC_ERROR; }); - TruffleExecutable stackValue = TruffleExecutable.wrapFunction((stackIndex) -> { - Object objectOnStack = FrameAccess.getStackValue(frame, (int)(long)stackIndex, FrameAccess.getNumArguments(frame)); - int objectIndex = objectRegistry.size(); - objectRegistry.add(objectOnStack); - return (long)objectIndex; - }); - - final Object interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy, - "createInterpreterProxy", - byteSizeOf, - firstIndexableField, - isBytes, - majorVersion, - methodArgumentCount, - minorVersion, - 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); - System.out.println("setInterpreterOk = " + setInterpreterOk); + uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); + uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); final Object result = uuidPluginLibrary.invokeMember(uuidPlugin, functionName); - System.out.println("result = " + result); - final Object shutdownOk = uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); - System.out.println("shutdownOk = " + shutdownOk); + uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); + return result; } catch (Exception e) { System.out.println("error"); e.printStackTrace(System.err); throw PrimitiveFailed.GENERIC_ERROR; } finally { - for (var postPrimitiveCleanup : postPrimitiveCleanups) { - postPrimitiveCleanup.cleanup(); + if (interpreterProxy != null) { + interpreterProxy.postPrimitiveCleanups(); } } } - private Object loadLibrary(String moduleName, String boundSymbols) { - final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; - final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); - return getContext().env.parseInternal(source).call(); - } - - private InteropLibrary getInteropLibrary(Object loadedLibrary) { - return InteropLibrary.getFactory().getUncached(loadedLibrary); - } - @Override public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { return execute(frame); } } - 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; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java new file mode 100644 index 000000000..c5e11832d --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -0,0 +1,85 @@ +package de.hpi.swa.trufflesqueak.util; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +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.image.SqueakImageContext; + +public class NFIUtils { + + @ExportLibrary(InteropLibrary.class) + public static class TruffleExecutable implements TruffleObject { + ITruffleExecutable executable; + + public TruffleExecutable(ITruffleExecutable executable) { + this.executable = executable; + } + + public static TruffleExecutable wrap(TruffleFunction function) { + return new TruffleExecutable(function); + } + static TruffleExecutable wrap(TruffleBiFunction function) { + return new TruffleExecutable(function); + } + + public static TruffleExecutable wrap(TruffleSupplier supplier) { + return new TruffleExecutable(supplier); + } + + @ExportMessage + boolean isExecutable() { + return true; + } + + @ExportMessage + Object execute(Object... arguments) { + return executable.execute(arguments); + } + } + + public interface ITruffleExecutable { + Object execute(Object... arguments); + } + + @FunctionalInterface + public interface TruffleFunction extends ITruffleExecutable { + R run(T argument); + + default Object execute(Object... arguments) { + assert arguments.length == 1; + return run((T) arguments[0]); + } + } + + @FunctionalInterface + public interface TruffleBiFunction extends ITruffleExecutable { + R run(S argument1, T argument2); + + default Object execute(Object... arguments) { + assert arguments.length == 2; + return run((S) arguments[0], (T) arguments[1]); + } + } + + @FunctionalInterface + public interface TruffleSupplier extends ITruffleExecutable { + R run(); + + default Object execute(Object... arguments) { + assert arguments.length == 0; + return run(); + } + } + + public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { + final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; + final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); + return context.env.parseInternal(source).call(); + } + + public static InteropLibrary getInteropLibrary(Object loadedLibrary) { + return InteropLibrary.getFactory().getUncached(loadedLibrary); + } +} From ea1f4cefce89b74f6afa6596f5f6b9786e7ab7a0 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 15 Nov 2023 16:41:05 +0100 Subject: [PATCH 007/159] Fix argument --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 5dc516cb4..620df1f50 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -57,11 +57,11 @@ public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup::cleanup); } - private int byteSizeOf() { + private int byteSizeOf(long oop) { return 16; } - private ByteStorage firstIndexableField(long index) { - byte[] storage = ((NativeObject) objectRegistry.get((int) index)).getByteStorage(); + private ByteStorage firstIndexableField(long oop) { + byte[] storage = ((NativeObject) objectRegistry.get((int) oop)).getByteStorage(); ByteStorage byteStorage = new ByteStorage(storage); postPrimitiveCleanups.add(byteStorage); return byteStorage; From 25f9726105378af8cfd5e90df8a93df5c39c13e8 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 15 Nov 2023 16:59:02 +0100 Subject: [PATCH 008/159] Generalize ByteStorage --- .../plugins/ffi/wrappers/ByteStorage.java | 18 +++------- .../plugins/ffi/wrappers/IntStorage.java | 24 +++++++++++++ .../plugins/ffi/wrappers/LongStorage.java | 24 +++++++++++++ .../ffi/wrappers/NativeObjectStorage.java | 33 +++++++++++++++++ .../plugins/ffi/wrappers/ShortStorage.java | 24 +++++++++++++ .../swa/trufflesqueak/util/UnsafeUtils.java | 35 ++++++++++++++++++- 6 files changed, 143 insertions(+), 15 deletions(-) create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index df2703dac..9cc63ee32 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -1,30 +1,20 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; -import com.oracle.truffle.api.library.ExportMessage; -import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; @ExportLibrary(InteropLibrary.class) -public class ByteStorage implements PostPrimitiveCleanup, TruffleObject { +public class ByteStorage extends NativeObjectStorage { 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 + protected void allocate() { + nativeAddress = UnsafeUtils.allocateNativeBytes(storage); } @Override diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java new file mode 100644 index 000000000..fc904a805 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -0,0 +1,24 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public class IntStorage extends NativeObjectStorage { + int[] storage; + + public IntStorage(int[] storage) { + this.storage = storage; + } + + @Override + protected void allocate() { + nativeAddress = UnsafeUtils.allocateNativeInts(storage); + } + + @Override + public void cleanup() { + UnsafeUtils.copyNativeIntsBackAndFree(nativeAddress, storage); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java new file mode 100644 index 000000000..3d8955f4c --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -0,0 +1,24 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public class LongStorage extends NativeObjectStorage { + long[] storage; + + public LongStorage(long[] storage) { + this.storage = storage; + } + + @Override + protected void allocate() { + nativeAddress = UnsafeUtils.allocateNativeLongs(storage); + } + + @Override + public void cleanup() { + UnsafeUtils.copyNativeLongsBackAndFree(nativeAddress, storage); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java new file mode 100644 index 000000000..73199e579 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -0,0 +1,33 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public abstract class NativeObjectStorage implements PostPrimitiveCleanup, TruffleObject { + protected long nativeAddress; + private boolean isAllocated = false; + + @ExportMessage + public boolean isPointer() { + return isAllocated; + } + + @ExportMessage + public long asPointer() { + return nativeAddress; + } + + @ExportMessage + public void toNative() { + if (isAllocated) return; + allocate(); + isAllocated = true; + } + + protected abstract void allocate(); +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java new file mode 100644 index 000000000..8ad6a2cf2 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -0,0 +1,24 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public class ShortStorage extends NativeObjectStorage { + short[] storage; + + public ShortStorage(short[] storage) { + this.storage = storage; + } + + @Override + protected void allocate() { + nativeAddress = UnsafeUtils.allocateNativeShorts(storage); + } + + @Override + public void cleanup() { + UnsafeUtils.copyNativeShortsBackAndFree(nativeAddress, storage); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java index aea73e632..640ba9ac7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java @@ -67,16 +67,49 @@ public static void copyShorts(final short[] src, final long srcPos, final short[ } public static long allocateNativeBytes(final byte[] src) { - final long address = UNSAFE.allocateMemory(src.length); + final long address = UNSAFE.allocateMemory((long) src.length * Byte.BYTES); UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length * Byte.BYTES); return address; } + public static long allocateNativeShorts(final short[] src) { + final long address = UNSAFE.allocateMemory((long) src.length * Short.BYTES); + UNSAFE.copyMemory(src, Unsafe.ARRAY_SHORT_BASE_OFFSET, null, address, (long) src.length * Short.BYTES); + return address; + } + + public static long allocateNativeInts(final int[] src) { + final long address = UNSAFE.allocateMemory((long) src.length * Integer.BYTES); + UNSAFE.copyMemory(src, Unsafe.ARRAY_INT_BASE_OFFSET, null, address, (long) src.length * Integer.BYTES); + return address; + } + + public static long allocateNativeLongs(final long[] src) { + final long address = UNSAFE.allocateMemory((long) src.length * Long.BYTES); + UNSAFE.copyMemory(src, Unsafe.ARRAY_LONG_BASE_OFFSET, null, address, (long) src.length * Long.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 void copyNativeShortsBackAndFree(final long address, short[] dest) { + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_SHORT_BASE_OFFSET, (long) dest.length * Short.BYTES); + UNSAFE.freeMemory(address); + } + + public static void copyNativeIntsBackAndFree(final long address, int[] dest) { + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_INT_BASE_OFFSET, (long) dest.length * Integer.BYTES); + UNSAFE.freeMemory(address); + } + + public static void copyNativeLongsBackAndFree(final long address, long[] dest) { + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_LONG_BASE_OFFSET, (long) dest.length * Long.BYTES); + UNSAFE.freeMemory(address); + } + public static long fromLongsOffset(final long offset) { return (offset - Unsafe.ARRAY_LONG_BASE_OFFSET) / Unsafe.ARRAY_LONG_INDEX_SCALE; } From 4ba75fc3b1a67c029b5aea8cc6285a8a3f98d0e0 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 14:09:06 +0100 Subject: [PATCH 009/159] Remove redundant fully-qualified class name --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 620df1f50..ad44af54e 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -19,7 +19,7 @@ public class InterpreterProxy { private final VirtualFrame frame; private final ArrayList objectRegistry = new ArrayList<>(); - private final ArrayList postPrimitiveCleanups = new ArrayList<>(); + private final ArrayList postPrimitiveCleanups = new ArrayList<>(); private static Object interpreterProxyPointer = null; @@ -54,7 +54,7 @@ public NFIUtils.TruffleExecutable[] getExecutables() { }; } public void postPrimitiveCleanups() { - postPrimitiveCleanups.forEach(de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup::cleanup); + postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); } private int byteSizeOf(long oop) { From f88ae6d8e92fee6183cd2669c0194df8bd71c321 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 14:15:49 +0100 Subject: [PATCH 010/159] Do not assume ByteStorage --- .../nodes/plugins/ffi/InterpreterProxy.java | 11 +++++------ .../ffi/wrappers/NativeObjectStorage.java | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index ad44af54e..7773d0e02 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -9,7 +9,7 @@ import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.model.NativeObject; -import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.ByteStorage; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; @@ -60,11 +60,10 @@ public void postPrimitiveCleanups() { private int byteSizeOf(long oop) { return 16; } - private ByteStorage firstIndexableField(long oop) { - byte[] storage = ((NativeObject) objectRegistry.get((int) oop)).getByteStorage(); - ByteStorage byteStorage = new ByteStorage(storage); - postPrimitiveCleanups.add(byteStorage); - return byteStorage; + private NativeObjectStorage firstIndexableField(long oop) { + NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistry.get((int) oop)); + postPrimitiveCleanups.add(storage); + return storage; } private int isBytes(long oop) { return 1; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index 73199e579..ae0a6fefb 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -4,14 +4,29 @@ import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; +import de.hpi.swa.trufflesqueak.model.NativeObject; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; -import de.hpi.swa.trufflesqueak.util.UnsafeUtils; @ExportLibrary(InteropLibrary.class) public abstract class NativeObjectStorage implements PostPrimitiveCleanup, TruffleObject { protected long nativeAddress; private boolean isAllocated = false; + public static NativeObjectStorage from(NativeObject object) { + if (object.isByteType()) { + return new ByteStorage(object.getByteStorage()); + } else if (object.isIntType()) { + return new IntStorage(object.getIntStorage()); + } else if (object.isLongType()) { + return new LongStorage(object.getLongStorage()); + } else if (object.isShortType()) { + return new ShortStorage(object.getShortStorage()); + } else { + throw new IllegalArgumentException("Object storage type is not supported."); + } + } + + @ExportMessage public boolean isPointer() { return isAllocated; From f34023364ed462b4dc06e4af6d76f76aa4d6644b Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 14:33:25 +0100 Subject: [PATCH 011/159] Get correct byteSize for storage type --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 7 +++++-- .../nodes/plugins/ffi/wrappers/ByteStorage.java | 5 +++++ .../nodes/plugins/ffi/wrappers/IntStorage.java | 5 +++++ .../nodes/plugins/ffi/wrappers/LongStorage.java | 5 +++++ .../nodes/plugins/ffi/wrappers/NativeObjectStorage.java | 2 ++ .../nodes/plugins/ffi/wrappers/ShortStorage.java | 5 +++++ 6 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 7773d0e02..df2de931d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -56,12 +56,15 @@ public NFIUtils.TruffleExecutable[] getExecutables() { public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); } + private NativeObject objectRegistryGet(long oop) { + return (NativeObject) objectRegistry.get((int) oop); + } private int byteSizeOf(long oop) { - return 16; + return NativeObjectStorage.from(objectRegistryGet(oop)).byteSizeOf(); } private NativeObjectStorage firstIndexableField(long oop) { - NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistry.get((int) oop)); + NativeObjectStorage storage = NativeObjectStorage.from(objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); return storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index 9cc63ee32..8da40a8d8 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -12,6 +12,11 @@ public ByteStorage(byte[] storage) { this.storage = storage; } + @Override + public int byteSizeOf() { + return storage.length * Byte.BYTES; + } + @Override protected void allocate() { nativeAddress = UnsafeUtils.allocateNativeBytes(storage); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index fc904a805..170f3735c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -12,6 +12,11 @@ public IntStorage(int[] storage) { this.storage = storage; } + @Override + public int byteSizeOf() { + return storage.length * Integer.BYTES; + } + @Override protected void allocate() { nativeAddress = UnsafeUtils.allocateNativeInts(storage); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index 3d8955f4c..8a923c123 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -12,6 +12,11 @@ public LongStorage(long[] storage) { this.storage = storage; } + @Override + public int byteSizeOf() { + return storage.length * Long.BYTES; + } + @Override protected void allocate() { nativeAddress = UnsafeUtils.allocateNativeLongs(storage); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index ae0a6fefb..9b68e2a00 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -44,5 +44,7 @@ public void toNative() { isAllocated = true; } + public abstract int byteSizeOf(); + protected abstract void allocate(); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 8ad6a2cf2..9f7a9d58f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -12,6 +12,11 @@ public ShortStorage(short[] storage) { this.storage = storage; } + @Override + public int byteSizeOf() { + return storage.length * Short.BYTES; + } + @Override protected void allocate() { nativeAddress = UnsafeUtils.allocateNativeShorts(storage); From cb53d61ecc84718f4139d9b1c7193b19127fc059 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 14:38:11 +0100 Subject: [PATCH 012/159] Return isBytes by storage type --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index df2de931d..88159a372 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -69,7 +69,7 @@ private NativeObjectStorage firstIndexableField(long oop) { return storage; } private int isBytes(long oop) { - return 1; + return objectRegistryGet(oop).isByteType() ? 1 : 0; } private int majorVersion() { return 1; From bcc3f00b049907db847429ebe6422114011fa07e Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 15:27:22 +0100 Subject: [PATCH 013/159] Stub symbols needed to support SqueakSSL [skip ci] --- .../src/InterpreterProxy.c | 20 ++++++ .../nodes/plugins/ffi/InterpreterProxy.java | 69 +++++++++++++++---- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 16 +++-- 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index bdc0adde5..7b219d965 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -3,22 +3,42 @@ VirtualMachine* createInterpreterProxy( sqInt (*byteSizeOf)(sqInt oop), + sqInt (*classString)(void), + sqInt (*failed)(void), void *(*firstIndexableField)(sqInt oop), + sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size), sqInt (*isBytes)(sqInt oop), sqInt (*majorVersion)(void), sqInt (*methodArgumentCount)(void), sqInt (*minorVersion)(void), + sqInt (*nilObject)(void), + sqInt (*pop)(sqInt nItems), + sqInt (*popthenPush)(sqInt nItems, sqInt oop), sqInt (*primitiveFail)(void), + sqInt (*pushInteger)(sqInt integerValue), + sqInt (*signed32BitIntegerFor)(sqInt integerValue), + int (*signed32BitValueOf)(sqInt oop), + sqInt (*stackIntegerValue)(sqInt offset), sqInt (*stackValue)(sqInt offset) ) { VirtualMachine* interpreterProxy = (VirtualMachine*)calloc(1, sizeof(VirtualMachine)); interpreterProxy->byteSizeOf = byteSizeOf; + interpreterProxy->classString = classString; + interpreterProxy->failed = failed; interpreterProxy->firstIndexableField = firstIndexableField; + interpreterProxy->instantiateClassindexableSize = instantiateClassindexableSize; interpreterProxy->isBytes = isBytes; interpreterProxy->majorVersion = majorVersion; interpreterProxy->methodArgumentCount = methodArgumentCount; interpreterProxy->minorVersion = minorVersion; + interpreterProxy->nilObject = nilObject; + interpreterProxy->pop = pop; + interpreterProxy->popthenPush = popthenPush; interpreterProxy->primitiveFail = primitiveFail; + interpreterProxy->pushInteger = pushInteger; + interpreterProxy->signed32BitIntegerFor = signed32BitIntegerFor; + interpreterProxy->signed32BitValueOf = signed32BitValueOf; + interpreterProxy->stackIntegerValue = stackIntegerValue; interpreterProxy->stackValue = stackValue; return interpreterProxy; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 88159a372..0e21633b4 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -12,8 +12,11 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; +import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Collectors; public class InterpreterProxy { @@ -26,31 +29,43 @@ public class InterpreterProxy { public InterpreterProxy(SqueakImageContext context, VirtualFrame frame) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { this.frame = frame; if (interpreterProxyPointer == null) { + final TruffleExecutable[] truffleExecutables = getExecutables(); + final String truffleExecutablesSignatures = Arrays.stream(truffleExecutables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); final Object interpreterProxy = NFIUtils.loadLibrary( context, "InterpreterProxy.so", - "{ createInterpreterProxy((SINT64):SINT64,(SINT64):POINTER,(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }" + "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" ); final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy,"createInterpreterProxy", (Object[]) getExecutables()); + interpreterProxy,"createInterpreterProxy", (Object[]) truffleExecutables); } } public Object getPointer() { return interpreterProxyPointer; } - public NFIUtils.TruffleExecutable[] getExecutables() { - return new NFIUtils.TruffleExecutable[] { - NFIUtils.TruffleExecutable.wrap(this::byteSizeOf), - NFIUtils.TruffleExecutable.wrap(this::firstIndexableField), - NFIUtils.TruffleExecutable.wrap(this::isBytes), - NFIUtils.TruffleExecutable.wrap(this::majorVersion), - NFIUtils.TruffleExecutable.wrap(this::methodArgumentCount), - NFIUtils.TruffleExecutable.wrap(this::minorVersion), - NFIUtils.TruffleExecutable.wrap(this::primitiveFail), - NFIUtils.TruffleExecutable.wrap(this::stackValue), + public TruffleExecutable[] getExecutables() { + return new TruffleExecutable[] { + TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), + TruffleExecutable.wrap("():SINT64", this::classString), + TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("():SINT64", this::majorVersion), + TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("():SINT64", this::minorVersion), + TruffleExecutable.wrap("():SINT64", this::nilObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::pop), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), }; } public void postPrimitiveCleanups() { @@ -63,11 +78,20 @@ private NativeObject objectRegistryGet(long oop) { private int byteSizeOf(long oop) { return NativeObjectStorage.from(objectRegistryGet(oop)).byteSizeOf(); } + private int classString() { + return 1;// TODO + } + private int failed() { + return 1;// TODO + } private NativeObjectStorage firstIndexableField(long oop) { NativeObjectStorage storage = NativeObjectStorage.from(objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); return storage; } + private int instantiateClassindexableSize(long classPointer, long size) { + return 1;// TODO + } private int isBytes(long oop) { return objectRegistryGet(oop).isByteType() ? 1 : 0; } @@ -80,9 +104,30 @@ private int methodArgumentCount() { private int minorVersion() { return 17; } + private int nilObject() { + return 1;// TODO + } + private int pop(long nItems) { + return 1;// TODO + } + private int popthenPush(long nItems, long oop) { + return 1;// TODO + } private int primitiveFail() { throw PrimitiveFailed.GENERIC_ERROR; } + private int pushInteger(long integerValue) { + return 1;// TODO + } + private int signed32BitIntegerFor(long integerValue) { + return 1;// TODO + } + private int signed32BitValueOf(long oop) { + return 1;// TODO + } + private int stackIntegerValue(long stackIndex) { + return 1;// TODO + } private int stackValue(long stackIndex) { Object objectOnStack = FrameAccess.getStackValue(frame, (int) stackIndex, FrameAccess.getNumArguments(frame)); int objectIndex = objectRegistry.size(); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index c5e11832d..6ace8f37b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -11,21 +11,23 @@ public class NFIUtils { @ExportLibrary(InteropLibrary.class) public static class TruffleExecutable implements TruffleObject { + public String nfiSignature; ITruffleExecutable executable; - public TruffleExecutable(ITruffleExecutable executable) { + public TruffleExecutable(String nfiSignature, ITruffleExecutable executable) { + this.nfiSignature = nfiSignature; this.executable = executable; } - public static TruffleExecutable wrap(TruffleFunction function) { - return new TruffleExecutable(function); + public static TruffleExecutable wrap(String nfiSignature, TruffleFunction function) { + return new TruffleExecutable(nfiSignature, function); } - static TruffleExecutable wrap(TruffleBiFunction function) { - return new TruffleExecutable(function); + public static TruffleExecutable wrap(String nfiSignature, TruffleBiFunction function) { + return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(TruffleSupplier supplier) { - return new TruffleExecutable(supplier); + public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { + return new TruffleExecutable(nfiSignature, supplier); } @ExportMessage From 2185699408819ac906cba3fa8fd5f411ba7c0305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 18 Nov 2023 19:18:38 +0100 Subject: [PATCH 014/159] Towards using SqueakSSL.so * Add numReceiverAndArguments to InterpreterProxy * Turn InterpreterProxy into a singleton with mutable members frame and numReceiverAndArguments * objectRegistry is now effectively static, so all primitive invocations share an oop namespace * Implement most InterpreterProxy stubs required for SqueakSSL.so --- .../nodes/plugins/ffi/InterpreterProxy.java | 144 +++++++++++++++--- .../primitives/PrimitiveNodeFactory.java | 24 +-- 2 files changed, 133 insertions(+), 35 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 0e21633b4..d596ffe29 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -8,7 +8,11 @@ import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject; +import de.hpi.swa.trufflesqueak.model.ClassObject; import de.hpi.swa.trufflesqueak.model.NativeObject; +import de.hpi.swa.trufflesqueak.model.NilObject; +import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; @@ -19,15 +23,20 @@ import java.util.stream.Collectors; public class InterpreterProxy { + private static InterpreterProxy INSTANCE = null; - private final VirtualFrame frame; + private final SqueakImageContext context; + private VirtualFrame frame; + private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); private static Object interpreterProxyPointer = null; - public InterpreterProxy(SqueakImageContext context, VirtualFrame frame) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + private InterpreterProxy(SqueakImageContext context, VirtualFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + this.context = context; this.frame = frame; + this.numReceiverAndArguments = numReceiverAndArguments; if (interpreterProxyPointer == null) { final TruffleExecutable[] truffleExecutables = getExecutables(); final String truffleExecutablesSignatures = Arrays.stream(truffleExecutables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); @@ -42,6 +51,20 @@ public InterpreterProxy(SqueakImageContext context, VirtualFrame frame) throws U interpreterProxy,"createInterpreterProxy", (Object[]) truffleExecutables); } } + + public static InterpreterProxy instanceFor(SqueakImageContext context, VirtualFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + if (INSTANCE == null) { + INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); + return INSTANCE; + } + if (INSTANCE.context != context) { + throw new RuntimeException("InterpreterProxy does not support multiple SqueakImageContexts"); + } + INSTANCE.frame = frame; + INSTANCE.numReceiverAndArguments = numReceiverAndArguments; + return INSTANCE; + } + public Object getPointer() { return interpreterProxyPointer; } @@ -70,69 +93,142 @@ public TruffleExecutable[] getExecutables() { } public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); + postPrimitiveCleanups.clear(); + } + private Object objectRegistryGet(long oop) { + System.out.println("Asked for oop " + oop); + return objectRegistry.get((int) oop); + } + + private int addObjectToRegistry(Object object) { + int oop = objectRegistry.size(); + objectRegistry.add(object); + return oop; + } + + private int oopFor(Object object) { + int oop = objectRegistry.indexOf(object); + if (oop < 0) { + oop = addObjectToRegistry(object); + } + System.out.println("Giving out oop " + oop + " for " + object); + return oop; + } + + private int getStackPointer() { + return FrameAccess.getStackPointer(frame); + } + + private void setStackPointer(int stackPointer) { + FrameAccess.setStackPointer(frame, stackPointer); + } + + private void pushObject(Object object) { + System.out.println("Pushing object " + object); + int stackPointer = getStackPointer() + 1; + setStackPointer(stackPointer); + FrameAccess.setSlot(frame, stackPointer, object); } - private NativeObject objectRegistryGet(long oop) { - return (NativeObject) objectRegistry.get((int) oop); + + private Object getObjectOnStack(long reverseStackIndex) { + if (reverseStackIndex < 0) { + primitiveFail(); + return null; + } + int stackIndex = getStackPointer() - (int) reverseStackIndex; + if (stackIndex < 0) { + primitiveFail(); + return null; + } + return FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); + } + + private long objectToLong(Object object) { + if (!(object instanceof Long)) { + System.out.println("Object to long called with non-Long: " + object); + primitiveFail(); + return 0; + } + return (Long)object; } private int byteSizeOf(long oop) { - return NativeObjectStorage.from(objectRegistryGet(oop)).byteSizeOf(); + return NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)).byteSizeOf(); } private int classString() { - return 1;// TODO + return oopFor(context.byteStringClass); } private int failed() { - return 1;// TODO + return 0; // TODO: when changing primitiveFail to continue executing, properly implement this } private NativeObjectStorage firstIndexableField(long oop) { - NativeObjectStorage storage = NativeObjectStorage.from(objectRegistryGet(oop)); + NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); return storage; } private int instantiateClassindexableSize(long classPointer, long size) { - return 1;// TODO + Object classObject = objectRegistryGet(classPointer); + if (!(classObject instanceof ClassObject)) { + System.out.println("instantiateClassindexableSize called with non-ClassObject: " + classObject); + primitiveFail(); + return -1; + } + SqueakObjectNewNode objectNewNode = SqueakObjectNewNode.create(); + AbstractSqueakObject newObject = objectNewNode.execute(context, (ClassObject) classObject, (int)size); + return oopFor(newObject); } private int isBytes(long oop) { - return objectRegistryGet(oop).isByteType() ? 1 : 0; + Object object = objectRegistryGet(oop); + if (!(object instanceof NativeObject)) { + return 0; + } + return ((NativeObject) object).isByteType() ? 1 : 0; } private int majorVersion() { return 1; } private int methodArgumentCount() { - return FrameAccess.getNumArguments(frame); + return numReceiverAndArguments - 1; } private int minorVersion() { return 17; } private int nilObject() { - return 1;// TODO + return oopFor(NilObject.SINGLETON); } private int pop(long nItems) { - return 1;// TODO + setStackPointer(getStackPointer() - (int)nItems); + return 1; } private int popthenPush(long nItems, long oop) { - return 1;// TODO + pop(nItems); + push(oop); + return 1; } private int primitiveFail() { + // TODO: continue executing C code + // TODO: adjust failed accordingly throw PrimitiveFailed.GENERIC_ERROR; } private int pushInteger(long integerValue) { - return 1;// TODO + pushObject(integerValue); + return 1; + } + private int push(long oop) { + pushObject(objectRegistryGet(oop)); + return 1; } private int signed32BitIntegerFor(long integerValue) { - return 1;// TODO + return oopFor(integerValue); } private int signed32BitValueOf(long oop) { - return 1;// TODO + return (int)objectToLong(objectRegistryGet(oop)); } - private int stackIntegerValue(long stackIndex) { - return 1;// TODO + private long stackIntegerValue(long reverseStackIndex) { + return objectToLong(getObjectOnStack(reverseStackIndex)); } - private int stackValue(long stackIndex) { - Object objectOnStack = FrameAccess.getStackValue(frame, (int) stackIndex, FrameAccess.getNumArguments(frame)); - int objectIndex = objectRegistry.size(); - objectRegistry.add(objectOnStack); - return objectIndex; + private int stackValue(long reverseStackIndex) { + return oopFor(getObjectOnStack(reverseStackIndex)); } public interface PostPrimitiveCleanup { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index df9553a79..92fdb2cf1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -37,8 +37,8 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.SecurityPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.SoundCodecPrims; import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakFFIPrims; -import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakSSL; import de.hpi.swa.trufflesqueak.nodes.plugins.TruffleSqueakPlugin; +import de.hpi.swa.trufflesqueak.nodes.plugins.UUIDPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.UnixOSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.Win32OSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ZipPlugin; @@ -114,8 +114,8 @@ public final class PrimitiveNodeFactory { new SocketPlugin(), new SoundCodecPrims(), new SqueakFFIPrims(), - new SqueakSSL(), - //new UUIDPlugin(), + //new SqueakSSL(), + new UUIDPlugin(), new ZipPlugin(), OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; fillPrimitiveTable(plugins); @@ -210,36 +210,38 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (functionName.equals("primitivePluginVersion")) { return null; } - return new NonExistentPrimitiveNode(moduleName, functionName); + return new NonExistentPrimitiveNode(moduleName, functionName, numReceiverAndArguments); } } static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { final String moduleName; final String functionName; + final int numReceiverAndArguments; - public NonExistentPrimitiveNode(String moduleName, String functionName) { + public NonExistentPrimitiveNode(String moduleName, String functionName, int numReceiverAndArguments) { this.moduleName = moduleName; this.functionName = functionName; + this.numReceiverAndArguments = numReceiverAndArguments; } @Override public Object execute(VirtualFrame frame) { - final Object uuidPlugin = NFIUtils.loadLibrary(getContext(), "UUIDPlugin.so", "{ " + - "initialiseModule():SINT64; " + + final Object uuidPlugin = NFIUtils.loadLibrary(getContext(), "SqueakSSL.so", "{ " + + //"initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + - "shutdownModule():SINT64; " + + //"shutdownModule():SINT64; " + functionName + "():SINT64; " + " }"); final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { - interpreterProxy = new InterpreterProxy(getContext(), frame); + interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); - uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); + //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); final Object result = uuidPluginLibrary.invokeMember(uuidPlugin, functionName); - uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); + //uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); return result; } catch (Exception e) { From d2498bb635db8616071aea4391aa480399fcaafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 20 Nov 2023 15:17:58 +0100 Subject: [PATCH 015/159] Fix stack pointer before running C code --- .../nodes/primitives/PrimitiveNodeFactory.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 92fdb2cf1..64c342133 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -7,6 +7,7 @@ package de.hpi.swa.trufflesqueak.nodes.primitives; import com.oracle.truffle.api.dsl.NodeFactory; +import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropLibrary; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; @@ -52,6 +53,7 @@ import de.hpi.swa.trufflesqueak.nodes.primitives.impl.IOPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.MiscellaneousPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.StoragePrimitives; +import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; import de.hpi.swa.trufflesqueak.util.OS; import org.graalvm.collections.EconomicMap; @@ -236,6 +238,10 @@ public Object execute(VirtualFrame frame) { final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { + // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by the number of arguments + // before transferring control. We need the stack pointer to point at the last argument, + // since the C code expects that. Therefore, we undo the decrement operation here. + FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments - 1); interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); From 36a22face9851923517fc9673bd1b7392e662b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:35:14 +0100 Subject: [PATCH 016/159] Use MaterializedFrames [skip ci] --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 7 ++++--- .../nodes/primitives/PrimitiveNodeFactory.java | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index d596ffe29..c94be952a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -1,5 +1,6 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; +import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -26,14 +27,14 @@ public class InterpreterProxy { private static InterpreterProxy INSTANCE = null; private final SqueakImageContext context; - private VirtualFrame frame; + private MaterializedFrame frame; private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); private static Object interpreterProxyPointer = null; - private InterpreterProxy(SqueakImageContext context, VirtualFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { this.context = context; this.frame = frame; this.numReceiverAndArguments = numReceiverAndArguments; @@ -52,7 +53,7 @@ private InterpreterProxy(SqueakImageContext context, VirtualFrame frame, int num } } - public static InterpreterProxy instanceFor(SqueakImageContext context, VirtualFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static InterpreterProxy instanceFor(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { if (INSTANCE == null) { INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); return INSTANCE; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 64c342133..44b5ff94f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -242,7 +242,7 @@ public Object execute(VirtualFrame frame) { // before transferring control. We need the stack pointer to point at the last argument, // since the C code expects that. Therefore, we undo the decrement operation here. FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments - 1); - interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); + interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); From 78c60d14380370b001767a9ed7177d5d0060f471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:36:38 +0100 Subject: [PATCH 017/159] Fix off-by-one in pre-call stackPointer adjustment [skip ci] --- .../trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 44b5ff94f..e538080b3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -238,10 +238,10 @@ public Object execute(VirtualFrame frame) { final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { - // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by the number of arguments + // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by numReceiverAndArguments // before transferring control. We need the stack pointer to point at the last argument, // since the C code expects that. Therefore, we undo the decrement operation here. - FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments - 1); + FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments); interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); From 042a901ed6ea6d30958d60e1b201f5bb6f4f9d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:38:21 +0100 Subject: [PATCH 018/159] Fix stack access using stackPointer [skip ci] --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index c94be952a..6ed796625 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -128,7 +128,7 @@ private void pushObject(Object object) { System.out.println("Pushing object " + object); int stackPointer = getStackPointer() + 1; setStackPointer(stackPointer); - FrameAccess.setSlot(frame, stackPointer, object); + FrameAccess.setStackSlot(frame, stackPointer - 1, object); } private Object getObjectOnStack(long reverseStackIndex) { @@ -136,7 +136,9 @@ private Object getObjectOnStack(long reverseStackIndex) { primitiveFail(); return null; } - int stackIndex = getStackPointer() - (int) reverseStackIndex; + // the stack pointer is the index of the object that is pushed onto the stack next, + // so we subtract 1 to get the index of the object that was last pushed onto the stack + int stackIndex = getStackPointer() - 1 - (int) reverseStackIndex; if (stackIndex < 0) { primitiveFail(); return null; From 903e97490fd0a67960df19c1eb7147d5804ce181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:40:56 +0100 Subject: [PATCH 019/159] Only load libraries once --- .../nodes/primitives/PrimitiveNodeFactory.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index e538080b3..c16afd936 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -58,8 +58,10 @@ import de.hpi.swa.trufflesqueak.util.OS; import org.graalvm.collections.EconomicMap; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; public final class PrimitiveNodeFactory { @@ -220,6 +222,7 @@ static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { final String moduleName; final String functionName; final int numReceiverAndArguments; + static Map loadedLibraries = new HashMap<>(); public NonExistentPrimitiveNode(String moduleName, String functionName, int numReceiverAndArguments) { this.moduleName = moduleName; @@ -229,12 +232,13 @@ public NonExistentPrimitiveNode(String moduleName, String functionName, int numR @Override public Object execute(VirtualFrame frame) { - final Object uuidPlugin = NFIUtils.loadLibrary(getContext(), "SqueakSSL.so", "{ " + - //"initialiseModule():SINT64; " + - "setInterpreter(POINTER):SINT64; " + - //"shutdownModule():SINT64; " + - functionName + "():SINT64; " + - " }"); + final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> + NFIUtils.loadLibrary(getContext(), "SqueakSSL.so", "{ " + + //"initialiseModule():SINT64; " + + "setInterpreter(POINTER):SINT64; " + + //"shutdownModule():SINT64; " + + functionName + "():SINT64; " + + " }")); final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { From 1f6ce90f6ae3d5189ec8b74cef2297bf3f8844ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:41:44 +0100 Subject: [PATCH 020/159] Add NFIUtils.loadMember [skip ci] --- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 6ace8f37b..777a91de7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,7 +1,11 @@ package de.hpi.swa.trufflesqueak.util; +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.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +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; @@ -75,12 +79,24 @@ default Object execute(Object... arguments) { } } - public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { - final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; + public static Object executeNFI(SqueakImageContext context, String nfiCode) { final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); return context.env.parseInternal(source).call(); } + public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { + final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; + return executeNFI(context, nfiCode); + } + + public static Object loadMember(SqueakImageContext context, Object library, String name, String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + InteropLibrary interopLibrary = getInteropLibrary(library); + Object symbol = interopLibrary.readMember(library, name); + Object nfiSignature = executeNFI(context, signature); + InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); + return signatureInteropLibrary.invokeMember(nfiSignature, "bind", symbol); + } + public static InteropLibrary getInteropLibrary(Object loadedLibrary) { return InteropLibrary.getFactory().getUncached(loadedLibrary); } From 87ca9d347fe08a5844ea41c7e3ad5743b3d8120a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:43:52 +0100 Subject: [PATCH 021/159] Add loading of function symbols [skip ci] --- .../trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index c16afd936..4332b9d77 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -237,11 +237,12 @@ public Object execute(VirtualFrame frame) { //"initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + //"shutdownModule():SINT64; " + - functionName + "():SINT64; " + " }")); final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { + Object functionSymbol = NFIUtils.loadMember(getContext(), uuidPlugin, functionName, "():SINT64"); + InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by numReceiverAndArguments // before transferring control. We need the stack pointer to point at the last argument, // since the C code expects that. Therefore, we undo the decrement operation here. @@ -250,7 +251,7 @@ public Object execute(VirtualFrame frame) { //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); - final Object result = uuidPluginLibrary.invokeMember(uuidPlugin, functionName); + final Object result = functionInteropLibrary.execute(functionSymbol); //uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); return result; From 1e4983b23760aa73c6dfe61738a1e3cc591404dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:44:33 +0100 Subject: [PATCH 022/159] Fix handling of return values [skip ci] --- .../nodes/primitives/PrimitiveNodeFactory.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 4332b9d77..3d8f1aaa8 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -253,8 +253,12 @@ public Object execute(VirtualFrame frame) { uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); final Object result = functionInteropLibrary.execute(functionSymbol); //uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); - - return result; + // The return value is pushed onto the stack by the Plugin via the InterpreterProxy, but TruffleSqueak + // expects the return value to be returned by this function (AbstractSendNode.executeVoid). + // Pop the return value and return it. + final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); + FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); + return returnValue; } catch (Exception e) { System.out.println("error"); e.printStackTrace(System.err); From ff31a648c9715c4920a1a9ecfcc0a260e8a1f56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 16:35:12 +0100 Subject: [PATCH 023/159] Keep TruffleExecutables in memory [skip ci] --- .../nodes/plugins/ffi/InterpreterProxy.java | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 6ed796625..e81822838 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -31,6 +31,26 @@ public class InterpreterProxy { private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); + private final TruffleExecutable[] executables = new TruffleExecutable[] { + TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), + TruffleExecutable.wrap("():SINT64", this::classString), + TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("():SINT64", this::majorVersion), + TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("():SINT64", this::minorVersion), + TruffleExecutable.wrap("():SINT64", this::nilObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::pop), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), + }; private static Object interpreterProxyPointer = null; @@ -39,8 +59,7 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in this.frame = frame; this.numReceiverAndArguments = numReceiverAndArguments; if (interpreterProxyPointer == null) { - final TruffleExecutable[] truffleExecutables = getExecutables(); - final String truffleExecutablesSignatures = Arrays.stream(truffleExecutables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); + final String truffleExecutablesSignatures = Arrays.stream(executables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); final Object interpreterProxy = NFIUtils.loadLibrary( context, "InterpreterProxy.so", @@ -49,7 +68,7 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy,"createInterpreterProxy", (Object[]) truffleExecutables); + interpreterProxy,"createInterpreterProxy", (Object[]) executables); } } @@ -70,28 +89,6 @@ public Object getPointer() { return interpreterProxyPointer; } - public TruffleExecutable[] getExecutables() { - return new TruffleExecutable[] { - TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), - TruffleExecutable.wrap("():SINT64", this::classString), - TruffleExecutable.wrap("():SINT64", this::failed), - TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), - TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), - TruffleExecutable.wrap("():SINT64", this::majorVersion), - TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), - TruffleExecutable.wrap("():SINT64", this::minorVersion), - TruffleExecutable.wrap("():SINT64", this::nilObject), - TruffleExecutable.wrap("(SINT64):SINT64", this::pop), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), - TruffleExecutable.wrap("():SINT64", this::primitiveFail), - TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), - TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), - TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), - }; - } public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); postPrimitiveCleanups.clear(); From 0f5a24d005614b14b05fd2e3f0221e5492b7835e Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 29 Nov 2023 21:38:39 +0100 Subject: [PATCH 024/159] Make `ffi.native` use CMakeNinjaProject --- mx.trufflesqueak/mx_trufflesqueak.py | 5 +++- mx.trufflesqueak/suite.py | 25 +++++++------------ .../CMakeLists.txt | 22 ++++++++++++++++ 3 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt diff --git a/mx.trufflesqueak/mx_trufflesqueak.py b/mx.trufflesqueak/mx_trufflesqueak.py index a90a55dc7..729f73506 100644 --- a/mx.trufflesqueak/mx_trufflesqueak.py +++ b/mx.trufflesqueak/mx_trufflesqueak.py @@ -10,11 +10,14 @@ import mx import mx_gate +import mx_unittest + import mx_sdk import mx_sdk_vm import mx_sdk_vm_impl import mx_truffle -import mx_unittest + +# re-export custom mx project classes so they can be used from suite.py _SUITE = mx.suite('trufflesqueak') _COMPILER = mx.suite('compiler', fatalIfMissing=False) diff --git a/mx.trufflesqueak/suite.py b/mx.trufflesqueak/suite.py index 0cd8fe6ee..32ec06804 100644 --- a/mx.trufflesqueak/suite.py +++ b/mx.trufflesqueak/suite.py @@ -167,24 +167,17 @@ }, "de.hpi.swa.trufflesqueak.ffi.native": { "subDir": "src", - "native": "shared_lib", - "deliverable": "SqueakFFIPrims", + "class": "CMakeNinjaProject", + "vpath": True, + "ninja_targets": ["all"], "os_arch": { - "windows": { - "": { - "cflags": [] - } - }, - "linux": { - "": { - "cflags": ["-g", "-Wall", "-Werror", "-D_GNU_SOURCE"], - "ldlibs": ["-ldl"], - }, - }, "": { "": { - "cflags": ["-g", "-Wall", "-Werror"], - "ldlibs": ["-ldl"], + "cmakeConfig": {}, + "results": [ + "", + "", + ], }, }, }, @@ -277,7 +270,7 @@ "layout": { "LICENSE_TRUFFLESQUEAK.txt": "file:LICENSE", "README_TRUFFLESQUEAK.md": "file:README.md", - "lib/": "dependency:de.hpi.swa.trufflesqueak.ffi.native", + "lib/": "dependency:de.hpi.swa.trufflesqueak.ffi.native/*", }, "maven": False, }, diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt b/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt new file mode 100644 index 000000000..3aafb8798 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.22) +project(de.hpi.swa.trufflesqueak.ffi.native) + +if(NOT DEFINED SRC_DIR) + set(SRC_DIR "${CMAKE_SOURCE_DIR}") +endif() + +set(CMAKE_C_STANDARD 11) + +# don't install into the system but into the MX project's output dir +set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) + +set(CAPI_SRC "${SRC_DIR}/src") + +function(build_library LIB_NAME SOURCE_FILE) + add_library(${LIB_NAME} SHARED ${SOURCE_FILE}) + target_include_directories(${LIB_NAME} PUBLIC include) +endfunction() + + +build_library(InterpreterProxy "${CAPI_SRC}/InterpreterProxy.c") +build_library(SqueakFFIPrims "${CAPI_SRC}/SqueakFFIPrims.c") \ No newline at end of file From 44cffa8e81ec8439aa69c9111fd9f3bd7e7a2950 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 29 Nov 2023 21:40:58 +0100 Subject: [PATCH 025/159] Format --- .../nodes/plugins/ffi/InterpreterProxy.java | 88 +++++++++++-------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index e81822838..5764ab942 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -1,7 +1,6 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; import com.oracle.truffle.api.frame.MaterializedFrame; -import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnknownIdentifierException; @@ -31,25 +30,25 @@ public class InterpreterProxy { private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); - private final TruffleExecutable[] executables = new TruffleExecutable[] { - TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), - TruffleExecutable.wrap("():SINT64", this::classString), - TruffleExecutable.wrap("():SINT64", this::failed), - TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), - TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), - TruffleExecutable.wrap("():SINT64", this::majorVersion), - TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), - TruffleExecutable.wrap("():SINT64", this::minorVersion), - TruffleExecutable.wrap("():SINT64", this::nilObject), - TruffleExecutable.wrap("(SINT64):SINT64", this::pop), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), - TruffleExecutable.wrap("():SINT64", this::primitiveFail), - TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), - TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), - TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), + private final TruffleExecutable[] executables = new TruffleExecutable[]{ + TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), + TruffleExecutable.wrap("():SINT64", this::classString), + TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("():SINT64", this::majorVersion), + TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("():SINT64", this::minorVersion), + TruffleExecutable.wrap("():SINT64", this::nilObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::pop), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), }; private static Object interpreterProxyPointer = null; @@ -68,21 +67,21 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy,"createInterpreterProxy", (Object[]) executables); + interpreterProxy, "createInterpreterProxy", (Object[]) executables); } } public static InterpreterProxy instanceFor(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { - if (INSTANCE == null) { - INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); - return INSTANCE; - } - if (INSTANCE.context != context) { - throw new RuntimeException("InterpreterProxy does not support multiple SqueakImageContexts"); - } - INSTANCE.frame = frame; - INSTANCE.numReceiverAndArguments = numReceiverAndArguments; - return INSTANCE; + if (INSTANCE == null) { + INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); + return INSTANCE; + } + if (INSTANCE.context != context) { + throw new RuntimeException("InterpreterProxy does not support multiple SqueakImageContexts"); + } + INSTANCE.frame = frame; + INSTANCE.numReceiverAndArguments = numReceiverAndArguments; + return INSTANCE; } public Object getPointer() { @@ -93,6 +92,7 @@ public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); postPrimitiveCleanups.clear(); } + private Object objectRegistryGet(long oop) { System.out.println("Asked for oop " + oop); return objectRegistry.get((int) oop); @@ -149,23 +149,27 @@ private long objectToLong(Object object) { primitiveFail(); return 0; } - return (Long)object; + return (Long) object; } private int byteSizeOf(long oop) { return NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)).byteSizeOf(); } + private int classString() { return oopFor(context.byteStringClass); } + private int failed() { return 0; // TODO: when changing primitiveFail to continue executing, properly implement this } + private NativeObjectStorage firstIndexableField(long oop) { NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); return storage; } + private int instantiateClassindexableSize(long classPointer, long size) { Object classObject = objectRegistryGet(classPointer); if (!(classObject instanceof ClassObject)) { @@ -174,9 +178,10 @@ private int instantiateClassindexableSize(long classPointer, long size) { return -1; } SqueakObjectNewNode objectNewNode = SqueakObjectNewNode.create(); - AbstractSqueakObject newObject = objectNewNode.execute(context, (ClassObject) classObject, (int)size); + AbstractSqueakObject newObject = objectNewNode.execute(context, (ClassObject) classObject, (int) size); return oopFor(newObject); } + private int isBytes(long oop) { Object object = objectRegistryGet(oop); if (!(object instanceof NativeObject)) { @@ -184,49 +189,62 @@ private int isBytes(long oop) { } return ((NativeObject) object).isByteType() ? 1 : 0; } + private int majorVersion() { return 1; } + private int methodArgumentCount() { return numReceiverAndArguments - 1; } + private int minorVersion() { return 17; } + private int nilObject() { return oopFor(NilObject.SINGLETON); } + private int pop(long nItems) { - setStackPointer(getStackPointer() - (int)nItems); + setStackPointer(getStackPointer() - (int) nItems); return 1; } + private int popthenPush(long nItems, long oop) { pop(nItems); push(oop); return 1; } + private int primitiveFail() { // TODO: continue executing C code // TODO: adjust failed accordingly throw PrimitiveFailed.GENERIC_ERROR; } + private int pushInteger(long integerValue) { pushObject(integerValue); return 1; } + private int push(long oop) { pushObject(objectRegistryGet(oop)); return 1; } + private int signed32BitIntegerFor(long integerValue) { return oopFor(integerValue); } + private int signed32BitValueOf(long oop) { - return (int)objectToLong(objectRegistryGet(oop)); + return (int) objectToLong(objectRegistryGet(oop)); } + private long stackIntegerValue(long reverseStackIndex) { return objectToLong(getObjectOnStack(reverseStackIndex)); } + private int stackValue(long reverseStackIndex) { return oopFor(getObjectOnStack(reverseStackIndex)); } From 8a9252cb07ec4348039fc994082e27777ac886a7 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 29 Nov 2023 21:42:54 +0100 Subject: [PATCH 026/159] Load nfi libraries from image path --- .../nodes/plugins/ffi/InterpreterProxy.java | 4 +--- .../nodes/primitives/PrimitiveNodeFactory.java | 3 +-- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 11 ++++++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 5764ab942..e9f4d87df 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -59,9 +59,7 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in this.numReceiverAndArguments = numReceiverAndArguments; if (interpreterProxyPointer == null) { final String truffleExecutablesSignatures = Arrays.stream(executables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); - final Object interpreterProxy = NFIUtils.loadLibrary( - context, - "InterpreterProxy.so", + final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" ); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 3d8f1aaa8..861519238 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -7,7 +7,6 @@ package de.hpi.swa.trufflesqueak.nodes.primitives; import com.oracle.truffle.api.dsl.NodeFactory; -import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropLibrary; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; @@ -233,7 +232,7 @@ public NonExistentPrimitiveNode(String moduleName, String functionName, int numR @Override public Object execute(VirtualFrame frame) { final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> - NFIUtils.loadLibrary(getContext(), "SqueakSSL.so", "{ " + + NFIUtils.loadLibrary(getContext(), moduleName, "{ " + //"initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + //"shutdownModule():SINT64; " + diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 777a91de7..d57b61f08 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,5 +1,6 @@ package de.hpi.swa.trufflesqueak.util; +import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; @@ -9,8 +10,11 @@ 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; +import java.io.File; + public class NFIUtils { @ExportLibrary(InteropLibrary.class) @@ -85,7 +89,12 @@ public static Object executeNFI(SqueakImageContext context, String nfiCode) { } public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { - final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; + final String libName = System.mapLibraryName(moduleName); + final TruffleFile libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName); + if (!libPath.exists()) { + throw PrimitiveFailed.GENERIC_ERROR; + } + final String nfiCode = "load \"" + libPath.getAbsoluteFile().getPath() + "\" " + boundSymbols; return executeNFI(context, nfiCode); } From 5dae1865cb53d1b1e76b695ce4a7375372f770bd Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 29 Nov 2023 21:59:14 +0100 Subject: [PATCH 027/159] Import is not actually unused [skip ci] --- mx.trufflesqueak/mx_trufflesqueak.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mx.trufflesqueak/mx_trufflesqueak.py b/mx.trufflesqueak/mx_trufflesqueak.py index 729f73506..ef1c6d77b 100644 --- a/mx.trufflesqueak/mx_trufflesqueak.py +++ b/mx.trufflesqueak/mx_trufflesqueak.py @@ -18,6 +18,7 @@ import mx_truffle # re-export custom mx project classes so they can be used from suite.py +from mx_cmake import CMakeNinjaProject #pylint: disable=unused-import _SUITE = mx.suite('trufflesqueak') _COMPILER = mx.suite('compiler', fatalIfMissing=False) From d7025ecd576dc42f4b88fe4ba9fd68fa10b3da74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 4 Dec 2023 13:03:56 +0100 Subject: [PATCH 028/159] Prevent NFI closures from being freed [skip ci] --- .../nodes/plugins/ffi/InterpreterProxy.java | 10 ++++-- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 34 +++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index e9f4d87df..b8f2eb36b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -16,6 +16,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; +import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleClosure; import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; import java.util.ArrayList; @@ -50,6 +51,7 @@ public class InterpreterProxy { TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), }; + private final TruffleClosure[] closures; private static Object interpreterProxyPointer = null; @@ -57,15 +59,19 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in this.context = context; this.frame = frame; this.numReceiverAndArguments = numReceiverAndArguments; + closures = new TruffleClosure[executables.length]; + for (int i = 0; i < executables.length; i++) { + closures[i] = executables[i].createClosure(context); + } if (interpreterProxyPointer == null) { - final String truffleExecutablesSignatures = Arrays.stream(executables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); + final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" ); final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy, "createInterpreterProxy", (Object[]) executables); + interpreterProxy, "createInterpreterProxy", (Object[]) closures); } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index d57b61f08..a8f6da886 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -47,6 +47,22 @@ boolean isExecutable() { Object execute(Object... arguments) { return executable.execute(arguments); } + + public TruffleClosure createClosure(SqueakImageContext context) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + return new TruffleClosure(context, this); + } + } + + @ExportLibrary(value = InteropLibrary.class, delegateTo = "closure") + public static class TruffleClosure implements TruffleObject { + public final TruffleExecutable executable; + + final Object closure; + + public TruffleClosure(SqueakImageContext context, TruffleExecutable executable) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + this.executable = executable; + this.closure = createClosure(context, executable, executable.nfiSignature); + } } public interface ITruffleExecutable { @@ -98,12 +114,24 @@ public static Object loadLibrary(SqueakImageContext context, String moduleName, return executeNFI(context, nfiCode); } + public static Object createSignature(SqueakImageContext context, String signature) { + return executeNFI(context, signature); + } + + public static Object invokeSignatureMethod(SqueakImageContext context, String signature, String method, Object... args) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + Object nfiSignature = createSignature(context, signature); + InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); + return signatureInteropLibrary.invokeMember(nfiSignature, method, args); + } + + public static Object createClosure(SqueakImageContext context, Object executable, String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + return invokeSignatureMethod(context, signature, "createClosure", executable); + } + public static Object loadMember(SqueakImageContext context, Object library, String name, String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { InteropLibrary interopLibrary = getInteropLibrary(library); Object symbol = interopLibrary.readMember(library, name); - Object nfiSignature = executeNFI(context, signature); - InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); - return signatureInteropLibrary.invokeMember(nfiSignature, "bind", symbol); + return invokeSignatureMethod(context, signature, "bind", symbol); } public static InteropLibrary getInteropLibrary(Object loadedLibrary) { From b1cb5c2aa0545993e930f3ebffffbc2600b1b5a8 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 14 Dec 2023 17:51:47 +0100 Subject: [PATCH 029/159] Add missing stubs from BitBlt support [skip ci] --- .../src/InterpreterProxy.c | 54 ++++++++++- .../nodes/plugins/ffi/InterpreterProxy.java | 95 ++++++++++++++++--- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 39 ++++++++ 3 files changed, 174 insertions(+), 14 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index 7b219d965..3df8772f7 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -5,40 +5,92 @@ VirtualMachine* createInterpreterProxy( sqInt (*byteSizeOf)(sqInt oop), sqInt (*classString)(void), sqInt (*failed)(void), + sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer), + sqInt (*fetchLong32ofObject)(sqInt fieldIndex, sqInt oop), + sqInt (*fetchPointerofObject)(sqInt index, sqInt oop), void *(*firstIndexableField)(sqInt oop), + double (*floatValueOf)(sqInt oop), sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size), + sqInt (*integerObjectOf)(sqInt value), + sqInt (*integerValueOf)(sqInt oop), + void *(*ioLoadFunctionFrom)(char *functionName, char *moduleName), + sqInt (*isArray)(sqInt oop), sqInt (*isBytes)(sqInt oop), + sqInt (*isPointers)(sqInt oop), + sqInt (*isPositiveMachineIntegerObject)(sqInt oop), + sqInt (*isWords)(sqInt oop), + sqInt (*isWordsOrBytes)(sqInt oop), sqInt (*majorVersion)(void), sqInt (*methodArgumentCount)(void), + sqInt (*methodReturnInteger)(sqInt integer), + sqInt (*methodReturnReceiver)(void), + sqInt (*methodReturnValue)(sqInt oop), sqInt (*minorVersion)(void), sqInt (*nilObject)(void), sqInt (*pop)(sqInt nItems), sqInt (*popthenPush)(sqInt nItems, sqInt oop), + sqInt (*positive32BitIntegerFor)(unsigned int integerValue), + usqInt (*positive32BitValueOf)(sqInt oop), + usqLong (*positive64BitValueOf)(sqInt oop), sqInt (*primitiveFail)(void), + sqInt (*primitiveFailFor)(sqInt reasonCode), + sqInt (*showDisplayBitsLeftTopRightBottom)(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b), sqInt (*pushInteger)(sqInt integerValue), sqInt (*signed32BitIntegerFor)(sqInt integerValue), int (*signed32BitValueOf)(sqInt oop), + sqInt (*slotSizeOf)(sqInt oop), sqInt (*stackIntegerValue)(sqInt offset), - sqInt (*stackValue)(sqInt offset) + sqInt (*stackObjectValue)(sqInt offset), + sqInt (*stackValue)(sqInt offset), + sqInt (*statNumGCs)(void), + sqInt (*storeIntegerofObjectwithValue)(sqInt index, sqInt oop, sqInt integer), + usqInt (*storeLong32ofObjectwithValue)(sqInt fieldIndex, sqInt oop, usqInt anInteger) ) { VirtualMachine* interpreterProxy = (VirtualMachine*)calloc(1, sizeof(VirtualMachine)); + interpreterProxy->byteSizeOf = byteSizeOf; interpreterProxy->classString = classString; interpreterProxy->failed = failed; + interpreterProxy->fetchIntegerofObject = fetchIntegerofObject; + interpreterProxy->fetchLong32ofObject = fetchLong32ofObject; + interpreterProxy->fetchPointerofObject = fetchPointerofObject; interpreterProxy->firstIndexableField = firstIndexableField; + interpreterProxy->floatValueOf = floatValueOf; interpreterProxy->instantiateClassindexableSize = instantiateClassindexableSize; + interpreterProxy->integerObjectOf = integerObjectOf; + interpreterProxy->integerValueOf = integerValueOf; + interpreterProxy->ioLoadFunctionFrom = ioLoadFunctionFrom; + interpreterProxy->isArray = isArray; interpreterProxy->isBytes = isBytes; + interpreterProxy->isPointers = isPointers; + interpreterProxy->isPositiveMachineIntegerObject = isPositiveMachineIntegerObject; + interpreterProxy->isWords = isWords; + interpreterProxy->isWordsOrBytes = isWordsOrBytes; interpreterProxy->majorVersion = majorVersion; interpreterProxy->methodArgumentCount = methodArgumentCount; + interpreterProxy->methodReturnInteger = methodReturnInteger; + interpreterProxy->methodReturnReceiver = methodReturnReceiver; + interpreterProxy->methodReturnValue = methodReturnValue; interpreterProxy->minorVersion = minorVersion; interpreterProxy->nilObject = nilObject; interpreterProxy->pop = pop; interpreterProxy->popthenPush = popthenPush; + interpreterProxy->positive32BitIntegerFor = positive32BitIntegerFor; + interpreterProxy->positive32BitValueOf = positive32BitValueOf; + interpreterProxy->positive64BitValueOf = positive64BitValueOf; interpreterProxy->primitiveFail = primitiveFail; + interpreterProxy->primitiveFailFor = primitiveFailFor; interpreterProxy->pushInteger = pushInteger; + interpreterProxy->showDisplayBitsLeftTopRightBottom = showDisplayBitsLeftTopRightBottom; interpreterProxy->signed32BitIntegerFor = signed32BitIntegerFor; interpreterProxy->signed32BitValueOf = signed32BitValueOf; + interpreterProxy->slotSizeOf = slotSizeOf; interpreterProxy->stackIntegerValue = stackIntegerValue; + interpreterProxy->stackObjectValue = stackObjectValue; interpreterProxy->stackValue = stackValue; + interpreterProxy->statNumGCs = statNumGCs; + interpreterProxy->storeIntegerofObjectwithValue = storeIntegerofObjectwithValue; + interpreterProxy->storeLong32ofObjectwithValue = storeLong32ofObjectwithValue; + return interpreterProxy; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index b8f2eb36b..bfe21ab77 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -35,22 +35,49 @@ public class InterpreterProxy { TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), TruffleExecutable.wrap("():SINT64", this::classString), TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchIntegerofObject), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchLong32ofObject), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchPointerofObject), TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64):DOUBLE", this::floatValueOf), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::integerObjectOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::integerValueOf), + TruffleExecutable.wrap("(STRING,STRING):POINTER", this::ioLoadFunctionFrom), + TruffleExecutable.wrap("(SINT64):SINT64", this::isArray), TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("(SINT64):SINT64", this::isPointers), + TruffleExecutable.wrap("(SINT64):SINT64", this::isPositiveMachineIntegerObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::isWords), + TruffleExecutable.wrap("(SINT64):SINT64", this::isWordsOrBytes), TruffleExecutable.wrap("():SINT64", this::majorVersion), TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnInteger), + TruffleExecutable.wrap("():SINT64", this::methodReturnReceiver), + TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnValue), TruffleExecutable.wrap("():SINT64", this::minorVersion), TruffleExecutable.wrap("():SINT64", this::nilObject), TruffleExecutable.wrap("(SINT64):SINT64", this::pop), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("(UINT64):SINT64", this::positive32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):UINT64", this::positive32BitValueOf), + TruffleExecutable.wrap("(SINT64):UINT64", this::positive64BitValueOf), TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::primitiveFailFor), + TruffleExecutable.wrap("(SINT64,SINT64,SINT64,SINT64,SINT64):SINT64", this::showDisplayBitsLeftTopRightBottom), TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), - TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::slotSizeOf), TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackObjectValue), TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), + TruffleExecutable.wrap("():SINT64", this::statNumGCs), + TruffleExecutable.wrap("(SINT64,SINT64,SINT64):SINT64", this::storeIntegerofObjectwithValue), + TruffleExecutable.wrap("(SINT64,SINT64,UINT64):UINT64", this::storeLong32ofObjectwithValue), }; + + @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; private static Object interpreterProxyPointer = null; @@ -237,21 +264,63 @@ private int push(long oop) { return 1; } - private int signed32BitIntegerFor(long integerValue) { - return oopFor(integerValue); - } + private long fetchIntegerofObject(long fieldIndex, long objectPointer) {/* TODO */ System.out.println("Missing implementation for fetchIntegerofObject"); return 0;} - private int signed32BitValueOf(long oop) { - return (int) objectToLong(objectRegistryGet(oop)); - } + private long fetchLong32ofObject(long fieldIndex, long oop) {/* TODO */ System.out.println("Missing implementation for fetchLong32ofObject"); return 0;} - private long stackIntegerValue(long reverseStackIndex) { - return objectToLong(getObjectOnStack(reverseStackIndex)); - } + private long fetchPointerofObject(long index, long oop) {/* TODO */ System.out.println("Missing implementation for fetchPointerofObject"); return 0;} - private int stackValue(long reverseStackIndex) { - return oopFor(getObjectOnStack(reverseStackIndex)); - } + private double floatValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for floatValueOf"); return 0;} + + private long integerObjectOf(long value) {/* TODO */ System.out.println("Missing implementation for integerObjectOf"); return 0;} + + private long integerValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for integerValueOf"); return 0;} + + private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) {/* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); return null;} + + private long isArray(long oop) {/* TODO */ System.out.println("Missing implementation for isArray"); return 0;} + + private long isPointers(long oop) {/* TODO */ System.out.println("Missing implementation for isPointers"); return 0;} + + private long isPositiveMachineIntegerObject(long oop) {/* TODO */ System.out.println("Missing implementation for isPositiveMachineIntegerObject"); return 0;} + + private long isWords(long oop) {/* TODO */ System.out.println("Missing implementation for isWords"); return 0;} + + private long isWordsOrBytes(long oop) {/* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); return 0;} + + private long methodReturnInteger(long integer) {/* TODO */ System.out.println("Missing implementation for methodReturnInteger"); return 0;} + + private long methodReturnReceiver() {/* TODO */ System.out.println("Missing implementation for methodReturnReceiver"); return 0;} + + private long methodReturnValue(long oop) {/* TODO */ System.out.println("Missing implementation for methodReturnValue"); return 0;} + + private long positive32BitIntegerFor(long integerValue) {/* TODO */ System.out.println("Missing implementation for positive32BitIntegerFor"); return 0;} + + private long positive32BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for positive32BitValueOf"); return 0;} + + private long positive64BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for positive64BitValueOf"); return 0;} + + private long primitiveFailFor(long reasonCode) {/* TODO */ System.out.println("Missing implementation for primitiveFailFor"); return 0;} + + private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) {/* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); return 0;} + + private long signed32BitIntegerFor(long integerValue) {/* TODO */ System.out.println("Missing implementation for signed32BitIntegerFor"); return 0;} + + private long signed32BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for signed32BitValueOf"); return 0;} + + private long slotSizeOf(long oop) {/* TODO */ System.out.println("Missing implementation for slotSizeOf"); return 0;} + + private long stackIntegerValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackIntegerValue"); return 0;} + + private long stackObjectValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackObjectValue"); return 0;} + + private long stackValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackValue"); return 0;} + + private long statNumGCs() {/* TODO */ System.out.println("Missing implementation for statNumGCs"); return 0;} + + private long storeIntegerofObjectwithValue(long index, long oop, long integer) {/* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); return 0;} + + private long storeLong32ofObjectwithValue(long fieldIndex, long oop, long anInteger) {/* TODO */ System.out.println("Missing implementation for storeLong32ofObjectwithValue"); return 0;} public interface PostPrimitiveCleanup { void cleanup(); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index a8f6da886..f7fce949d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -33,6 +33,15 @@ public static TruffleExecutable wrap(String nfiSignature, TruffleFunction< public static TruffleExecutable wrap(String nfiSignature, TruffleBiFunction function) { return new TruffleExecutable(nfiSignature, function); } + public static TruffleExecutable wrap(String nfiSignature, TruffleTriFunction function) { + return new TruffleExecutable(nfiSignature, function); + } + public static TruffleExecutable wrap(String nfiSignature, TruffleQuadFunction function) { + return new TruffleExecutable(nfiSignature, function); + } + public static TruffleExecutable wrap(String nfiSignature, TruffleQuintFunction function) { + return new TruffleExecutable(nfiSignature, function); + } public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { return new TruffleExecutable(nfiSignature, supplier); @@ -89,6 +98,36 @@ default Object execute(Object... arguments) { } } + @FunctionalInterface + public interface TruffleTriFunction extends ITruffleExecutable { + R run(S argument1, T argument2, U argument3); + + default Object execute(Object... arguments) { + assert arguments.length == 3; + return run((S) arguments[0], (T) arguments[1], (U) arguments[2]); + } + } + + @FunctionalInterface + public interface TruffleQuadFunction extends ITruffleExecutable { + R run(S argument1, T argument2, U argument3, V argument4); + + default Object execute(Object... arguments) { + assert arguments.length == 4; + return run((S) arguments[0], (T) arguments[1], (U) arguments[2], (V) arguments[3]); + } + } + + @FunctionalInterface + public interface TruffleQuintFunction extends ITruffleExecutable { + R run(S argument1, T argument2, U argument3, V argument4, W argument5); + + default Object execute(Object... arguments) { + assert arguments.length == 5; + return run((S) arguments[0], (T) arguments[1], (U) arguments[2], (V) arguments[3], (W) arguments[4]); + } + } + @FunctionalInterface public interface TruffleSupplier extends ITruffleExecutable { R run(); From fd3453b9f96e98699f4dea1e7af3fa730c7d0530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 18 Dec 2023 14:55:25 +0100 Subject: [PATCH 030/159] Implement some stubs and refactor --- .../nodes/plugins/ffi/InterpreterProxy.java | 107 ++++++++++++++---- 1 file changed, 83 insertions(+), 24 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index bfe21ab77..0a5296d7f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -8,10 +8,16 @@ import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject; +import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.ClassObject; +import de.hpi.swa.trufflesqueak.model.FloatObject; +import de.hpi.swa.trufflesqueak.model.LargeIntegerObject; import de.hpi.swa.trufflesqueak.model.NativeObject; import de.hpi.swa.trufflesqueak.model.NilObject; +import de.hpi.swa.trufflesqueak.model.PointersObject; +import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; @@ -21,6 +27,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.function.Function; import java.util.stream.Collectors; public class InterpreterProxy { @@ -175,12 +182,29 @@ private Object getObjectOnStack(long reverseStackIndex) { } private long objectToLong(Object object) { - if (!(object instanceof Long)) { - System.out.println("Object to long called with non-Long: " + object); - primitiveFail(); - return 0; + if (object instanceof Long longObject) { + return longObject; + } + System.out.println("Object to long called with non-Long: " + object); + primitiveFail(); + return 0; + } + + private double objectToDouble(Object object) { + if (object instanceof FloatObject floatObject) { + return floatObject.getValue(); + } + System.out.println("Object to double called with non-FloatObject: " + object); + primitiveFail(); + return 0; + } + + private int nativeObjectCheck(long oop, Function check) { + Object object = objectRegistryGet(oop); + if (object instanceof NativeObject nativeObject) { + return check.apply(nativeObject) ? 1 : 0; } - return (Long) object; + return 0; } private int byteSizeOf(long oop) { @@ -195,6 +219,10 @@ private int failed() { return 0; // TODO: when changing primitiveFail to continue executing, properly implement this } + private Object objectAt0(Object object, long index) { + return SqueakObjectAt0Node.getUncached().execute(object, index); + } + private NativeObjectStorage firstIndexableField(long oop) { NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); @@ -214,11 +242,7 @@ private int instantiateClassindexableSize(long classPointer, long size) { } private int isBytes(long oop) { - Object object = objectRegistryGet(oop); - if (!(object instanceof NativeObject)) { - return 0; - } - return ((NativeObject) object).isByteType() ? 1 : 0; + return nativeObjectCheck(oop, NativeObject::isByteType); } private int majorVersion() { @@ -264,27 +288,54 @@ private int push(long oop) { return 1; } - private long fetchIntegerofObject(long fieldIndex, long objectPointer) {/* TODO */ System.out.println("Missing implementation for fetchIntegerofObject"); return 0;} + private long fetchIntegerofObject(long fieldIndex, long objectPointer) { + return objectToLong(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); + } - private long fetchLong32ofObject(long fieldIndex, long oop) {/* TODO */ System.out.println("Missing implementation for fetchLong32ofObject"); return 0;} + private long fetchLong32ofObject(long fieldIndex, long oop) { + return fetchIntegerofObject(fieldIndex, oop); + } - private long fetchPointerofObject(long index, long oop) {/* TODO */ System.out.println("Missing implementation for fetchPointerofObject"); return 0;} + private long fetchPointerofObject(long index, long oop) { + return oopFor(objectAt0(objectRegistryGet(oop), index)); + } - private double floatValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for floatValueOf"); return 0;} + private double floatValueOf(long oop) { + return objectToDouble(objectRegistryGet(oop)); + } - private long integerObjectOf(long value) {/* TODO */ System.out.println("Missing implementation for integerObjectOf"); return 0;} + private long integerObjectOf(long value) { + return oopFor(value); + } - private long integerValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for integerValueOf"); return 0;} + private long integerValueOf(long oop) { + return objectToLong(objectRegistryGet(oop)); + } private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) {/* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); return null;} - private long isArray(long oop) {/* TODO */ System.out.println("Missing implementation for isArray"); return 0;} + private long isArray(long oop) { + return objectRegistryGet(oop) instanceof ArrayObject ? 1 : 0; + } - private long isPointers(long oop) {/* TODO */ System.out.println("Missing implementation for isPointers"); return 0;} + private long isPointers(long oop) { + return objectRegistryGet(oop) instanceof AbstractPointersObject ? 1 : 0; + } - private long isPositiveMachineIntegerObject(long oop) {/* TODO */ System.out.println("Missing implementation for isPositiveMachineIntegerObject"); return 0;} + private long isPositiveMachineIntegerObject(long oop) { + Object object = objectRegistryGet(oop); + if (object instanceof Long integer) { + return integer >= 0 ? 1 : 0; + } + if (object instanceof LargeIntegerObject largeInteger) { + return largeInteger.isZeroOrPositive() && largeInteger.fitsIntoLong() ? 1 : 0; + } + return 0; + } - private long isWords(long oop) {/* TODO */ System.out.println("Missing implementation for isWords"); return 0;} + private long isWords(long oop) { + return nativeObjectCheck(oop, NativeObject::isLongType); + } private long isWordsOrBytes(long oop) {/* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); return 0;} @@ -304,17 +355,25 @@ private int push(long oop) { private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) {/* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); return 0;} - private long signed32BitIntegerFor(long integerValue) {/* TODO */ System.out.println("Missing implementation for signed32BitIntegerFor"); return 0;} + private long signed32BitIntegerFor(long integerValue) { + return integerObjectOf(integerValue); + } - private long signed32BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for signed32BitValueOf"); return 0;} + private long signed32BitValueOf(long oop) { + return integerValueOf(oop); + } private long slotSizeOf(long oop) {/* TODO */ System.out.println("Missing implementation for slotSizeOf"); return 0;} - private long stackIntegerValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackIntegerValue"); return 0;} + private long stackIntegerValue(long offset) { + return objectToLong(getObjectOnStack(offset)); + } private long stackObjectValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackObjectValue"); return 0;} - private long stackValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackValue"); return 0;} + private long stackValue(long offset) { + return oopFor(getObjectOnStack(offset)); + } private long statNumGCs() {/* TODO */ System.out.println("Missing implementation for statNumGCs"); return 0;} From b7a18b121c0e809d864293403db46ef3894670fd Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sun, 5 Nov 2023 22:08:30 +0100 Subject: [PATCH 031/159] [skip ci] Test NFI for non-existent named primitives --- .../primitives/PrimitiveNodeFactory.java | 117 ++++++++++++------ 1 file changed, 79 insertions(+), 38 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 941bec3f0..120a42ea7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -10,6 +10,16 @@ import java.util.List; import java.util.Set; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; +import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.nfi.backend.spi.NFIBackend; +import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.nodes.AbstractNode; import org.graalvm.collections.EconomicMap; import com.oracle.truffle.api.dsl.NodeFactory; @@ -77,45 +87,45 @@ public final class PrimitiveNodeFactory { static { final AbstractPrimitiveFactoryHolder[] indexPrimitives = { - new ArithmeticPrimitives(), - new ArrayStreamPrimitives(), - new BlockClosurePrimitives(), - new ContextPrimitives(), - new ControlPrimitives(), - new IOPrimitives(), - new MiscellaneousPrimitives(), - new StoragePrimitives()}; + new ArithmeticPrimitives(), + new ArrayStreamPrimitives(), + new BlockClosurePrimitives(), + new ContextPrimitives(), + new ControlPrimitives(), + new IOPrimitives(), + new MiscellaneousPrimitives(), + new StoragePrimitives()}; fillPrimitiveTable(indexPrimitives); final AbstractPrimitiveFactoryHolder[] plugins = { - new B2DPlugin(), - new BitBltPlugin(), - new BMPReadWriterPlugin(), - new ClipboardExtendedPlugin(), - new CroquetPlugin(), - new DropPlugin(), - new DSAPrims(), - new FilePlugin(), - new FloatArrayPlugin(), - new Float64ArrayPlugin(), - new TruffleSqueakPlugin(), - new HostWindowPlugin(), - new JPEGReaderPlugin(), - new JPEGReadWriter2Plugin(), - new LargeIntegers(), - new LocalePlugin(), - new Matrix2x3Plugin(), - new MiscPrimitivePlugin(), - new NullPlugin(), - new PolyglotPlugin(), - new SecurityPlugin(), - new SocketPlugin(), - new SoundCodecPrims(), - new SqueakFFIPrims(), - new SqueakSSL(), - new UUIDPlugin(), - new ZipPlugin(), - OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; + new B2DPlugin(), + new BitBltPlugin(), + new BMPReadWriterPlugin(), + new ClipboardExtendedPlugin(), + new CroquetPlugin(), + new DropPlugin(), + new DSAPrims(), + new FilePlugin(), + new FloatArrayPlugin(), + new Float64ArrayPlugin(), + new TruffleSqueakPlugin(), + new HostWindowPlugin(), + new JPEGReaderPlugin(), + new JPEGReadWriter2Plugin(), + new LargeIntegers(), + new LocalePlugin(), + new Matrix2x3Plugin(), + new MiscPrimitivePlugin(), + new NullPlugin(), + new PolyglotPlugin(), + new SecurityPlugin(), + new SocketPlugin(), + new SoundCodecPrims(), + new SqueakFFIPrims(), + new SqueakSSL(), + new UUIDPlugin(), + new ZipPlugin(), + OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; fillPrimitiveTable(plugins); fillPluginMap(plugins); } @@ -203,7 +213,38 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (nodeFactory != null) { return createNode(nodeFactory, location, numReceiverAndArguments); } else { - return null; + System.out.println("trying to execute " + moduleName + ":" + functionName); + + if (functionName.equals("primitivePluginVersion")) { + return null; + } + return new NonExistentPrimitiveNode(); + } + } + + static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { + @Override + public Object execute(VirtualFrame frame) { + final String nfiCode = "load \"UUIDPlugin.so\" { getModuleName():STRING; }"; + final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); + final SqueakImageContext image = getContext(); + final Object ffiTest = image.env.parseInternal(source).call(); + final InteropLibrary interopLib = InteropLibrary.getFactory().getUncached(ffiTest); + + final String name = "getModuleName"; + try { + Object returnValue = interopLib.invokeMember(ffiTest, name); + return returnValue; + + } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException | ArityException e) { + e.printStackTrace(); + return null; + } + } + + @Override + public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { + return execute(frame); } } @@ -295,4 +336,4 @@ private static void addEntryToPrimitiveTable(final int index, final NodeFactory< assert !map.containsKey(numReceiverAndArguments) : "primitives are not allowed to override others (#" + index + ")"; map.put(nodeFactory.getExecutionSignature().size(), nodeFactory); } -} +} \ No newline at end of file From e56b723e0ddb0205e7d3fbf730905b77046b7164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sun, 5 Nov 2023 22:13:39 +0100 Subject: [PATCH 032/159] [skip ci] Add initial createInterpreterProxy function in C --- .../include/sqMemoryAccess.h | 108 +++++ .../include/sqVirtualMachine.h | 379 ++++++++++++++++++ .../include/vmCallback.h | 33 ++ .../src/InterpreterProxy.c | 24 ++ 4 files changed, 544 insertions(+) create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h new file mode 100644 index 000000000..43f3e4de1 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h @@ -0,0 +1,108 @@ +#define SIZEOF_VOID_P 8 + +//////////// from here on: copied from +//////////// https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/ec421b99cf41fc5f2f5fb734b536d6233cdde809/platforms/Cross/vm/sqMemoryAccess.h + +#ifndef SIZEOF_LONG +# if LLP64 +# define SIZEOF_LONG 4 +# else +# define SIZEOF_LONG SIZEOF_VOID_P /* default is sizeof(long)==sizeof(void *) */ +# endif +#endif + +#if (SQ_VI_BYTES_PER_WORD == 4) +# define SQ_IMAGE32 1 +# define SQ_IMAGE64 0 +#else +# define SQ_IMAGE64 1 +# define SQ_IMAGE32 0 +#endif + +#if (SQ_IMAGE64 || SPURVM) +# define OBJECTS_64BIT_ALIGNED 1 +# define OBJECTS_32BIT_ALIGNED 0 +#else +# define OBJECTS_32BIT_ALIGNED 1 +# define OBJECTS_64BIT_ALIGNED 0 +#endif + +#if (SIZEOF_VOID_P == 4) +# define SQ_HOST32 1 +#elif (SIZEOF_VOID_P == 8) +# define SQ_HOST64 1 +#else +# error host is neither 32- nor 64-bit? +#endif + +/* sqInt is a signed integer with size adequate for holding an Object Oriented Pointer (or immediate value) + - that is 32bits long on a 32bits image or 64bits long on a 64bits image + we could use C99 int32_t and int64_t once retiring legacy compiler support this time has not yet come + usqInt is the unsigned flavour + SQABS is a macro for taking absolute value of an sqInt */ +#if SQ_IMAGE32 + typedef int sqInt; + typedef unsigned int usqInt; +#define PRIdSQINT "d" +#define PRIuSQINT "u" +#define PRIxSQINT "x" +#define PRIXSQINT "X" +# define SQABS abs +#elif SQ_HOST64 && (SIZEOF_LONG == 8) + typedef long sqInt; + typedef unsigned long usqInt; +#define PRIdSQINT "ld" +#define PRIuSQINT "lu" +#define PRIxSQINT "lx" +#define PRIXSQINT "lX" +# define SQABS labs +#elif (SIZEOF_LONG_LONG != 8) +# error long long integers are not 64-bits wide? +#else + typedef long long sqInt; + typedef unsigned long long usqInt; +#define PRIdSQINT "lld" +#define PRIuSQINT "llu" +#define PRIxSQINT "llx" +#define PRIXSQINT "llX" +# define SQABS llabs +#endif + +/* sqLong is a signed integer with at least 64bits on both 32 and 64 bits images + usqLong is the unsigned flavour + SQLABS is a macro for taking absolute value of a sqLong */ +#if !defined(sqLong) +# if SIZEOF_LONG == 8 +# define sqLong long +# define usqLong unsigned long +# define SQLABS labs +# elif _MSC_VER +# define sqLong __int64 +# define usqLong unsigned __int64 +# define SQLABS llabs +# else +# define sqLong long long +# define usqLong unsigned long long +# define SQLABS llabs +# endif +#endif /* !defined(sqLong) */ + +/* sqIntptr_t is a signed integer with enough bits to hold a pointer + usqIntptr_t is the unsigned flavour + this is essentially C99 intptr_t and uintptr_t but we support legacy compilers + the C99 printf formats macros are also defined with SQ prefix */ +#if SIZEOF_LONG == SIZEOF_VOID_P +typedef long sqIntptr_t; +typedef unsigned long usqIntptr_t; +#define PRIdSQPTR "ld" +#define PRIuSQPTR "lu" +#define PRIxSQPTR "lx" +#define PRIXSQPTR "lX" +#else +typedef long long sqIntptr_t; +typedef unsigned long long usqIntptr_t; +#define PRIdSQPTR "lld" +#define PRIuSQPTR "llu" +#define PRIxSQPTR "llx" +#define PRIXSQPTR "llX" +#endif diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h new file mode 100644 index 000000000..63143b70c --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h @@ -0,0 +1,379 @@ +#include "vmCallback.h" + +//////////// from here on: copied from +//////////// https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/ec421b99cf41fc5f2f5fb734b536d6233cdde809/platforms/Cross/vm/sqVirtualMachine.h + +#if SPURVM +# define VM_VERSION "5.0" +#else +# define VM_VERSION "4.5" +#endif + +#ifndef VM_PROXY_MAJOR +/* Increment the following number if you change the order of + functions listed or if you remove functions */ +# define VM_PROXY_MAJOR 1 +#endif + +#ifndef VM_PROXY_MINOR +/* Increment the following number if you add functions at the end */ +# if SPURVM +# define VM_PROXY_MINOR 13 +# else +# define VM_PROXY_MINOR 12 +# endif +#endif + +#include "sqMemoryAccess.h" + +#if VM_PROXY_MINOR > 8 +// Primitive error codes; see interp.h +# define PrimNoErr 0 + +/* VMCallbackContext opaque type avoids all including setjmp.h & vmCallback.h */ +typedef struct _VMCallbackContext *vmccp; +#endif + +typedef sqInt (*CompilerHook)(void); + +typedef struct VirtualMachine { + sqInt (*minorVersion)(void); + sqInt (*majorVersion)(void); + + /* InterpreterProxy methodsFor: 'stack access' */ + + sqInt (*pop)(sqInt nItems); + sqInt (*popthenPush)(sqInt nItems, sqInt oop); + sqInt (*push)(sqInt object); + sqInt (*pushBool)(sqInt trueOrFalse); + sqInt (*pushFloat)(double f); + sqInt (*pushInteger)(sqInt integerValue); + double (*stackFloatValue)(sqInt offset); + sqInt (*stackIntegerValue)(sqInt offset); + sqInt (*stackObjectValue)(sqInt offset); + sqInt (*stackValue)(sqInt offset); + + /* InterpreterProxy methodsFor: 'object access' */ + + sqInt (*argumentCountOf)(sqInt methodPointer); + void *(*arrayValueOf)(sqInt oop); + sqInt (*byteSizeOf)(sqInt oop); + void *(*fetchArrayofObject)(sqInt fieldIndex, sqInt objectPointer); + sqInt (*fetchClassOf)(sqInt oop); + double (*fetchFloatofObject)(sqInt fieldIndex, sqInt objectPointer); + sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer); + sqInt (*fetchPointerofObject)(sqInt fieldIndex, sqInt oop); +#if OLD_FOR_REFERENCE +/* sqInt (*fetchWordofObject)(sqInt fieldFieldIndex, sqInt oop); * + * has been rescinded as of VMMaker 3.8 and the 64bitclean VM * + * work. To support old plugins we keep a valid function in * + * the same location in the VM struct but rename it to * + * something utterly horrible to scare off the natives. A new * + * equivalent but 64 bit valid function is added as * + * 'fetchLong32OfObject' */ + sqInt (*obsoleteDontUseThisFetchWordofObject)(sqInt fieldFieldIndex, sqInt oop); +#else /* since there is no legacy plugin problem back to 3.8 we repurpose... */ + void (*error)(const char *); +#endif + void *(*firstFixedField)(sqInt oop); + void *(*firstIndexableField)(sqInt oop); + sqInt (*literalofMethod)(sqInt offset, sqInt methodPointer); + sqInt (*literalCountOf)(sqInt methodPointer); + sqInt (*methodArgumentCount)(void); + sqInt (*methodPrimitiveIndex)(void); + sqInt (*primitiveIndexOf)(sqInt methodPointer); + sqInt (*sizeOfSTArrayFromCPrimitive)(void *cPtr); + sqInt (*slotSizeOf)(sqInt oop); + sqInt (*stObjectat)(sqInt array, sqInt fieldIndex); + sqInt (*stObjectatput)(sqInt array, sqInt fieldIndex, sqInt value); + sqInt (*stSizeOf)(sqInt oop); + sqInt (*storeIntegerofObjectwithValue)(sqInt fieldIndex, sqInt oop, sqInt integer); + sqInt (*storePointerofObjectwithValue)(sqInt fieldIndex, sqInt oop, sqInt valuePointer); + + /* InterpreterProxy methodsFor: 'testing' */ + + sqInt (*isKindOf)(sqInt oop, char *aString); + sqInt (*isMemberOf)(sqInt oop, char *aString); + sqInt (*isBytes)(sqInt oop); + sqInt (*isFloatObject)(sqInt oop); + sqInt (*isIndexable)(sqInt oop); + sqInt (*isIntegerObject)(sqInt oop); + sqInt (*isIntegerValue)(sqInt intValue); + sqInt (*isPointers)(sqInt oop); + sqInt (*isWeak)(sqInt oop); + sqInt (*isWords)(sqInt oop); + sqInt (*isWordsOrBytes)(sqInt oop); + + /* InterpreterProxy methodsFor: 'converting' */ + + sqInt (*booleanValueOf)(sqInt obj); + sqInt (*checkedIntegerValueOf)(sqInt intOop); + sqInt (*floatObjectOf)(double aFloat); + double (*floatValueOf)(sqInt oop); + sqInt (*integerObjectOf)(sqInt value); + sqInt (*integerValueOf)(sqInt oop); + sqInt (*positive32BitIntegerFor)(unsigned int integerValue); + usqInt (*positive32BitValueOf)(sqInt oop); + + /* InterpreterProxy methodsFor: 'special objects' */ + + sqInt (*characterTable)(void); + sqInt (*displayObject)(void); + sqInt (*falseObject)(void); + sqInt (*nilObject)(void); + sqInt (*trueObject)(void); + + /* InterpreterProxy methodsFor: 'special classes' */ + + sqInt (*classArray)(void); + sqInt (*classBitmap)(void); + sqInt (*classByteArray)(void); + sqInt (*classCharacter)(void); + sqInt (*classFloat)(void); + sqInt (*classLargePositiveInteger)(void); + sqInt (*classPoint)(void); + sqInt (*classSemaphore)(void); + sqInt (*classSmallInteger)(void); + sqInt (*classString)(void); + + /* InterpreterProxy methodsFor: 'instance creation' */ + + sqInt (*cloneObject)(sqInt oop); + sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size); + sqInt (*makePointwithxValueyValue)(sqInt xValue, sqInt yValue); + sqInt (*popRemappableOop)(void); + sqInt (*pushRemappableOop)(sqInt oop); + + /* InterpreterProxy methodsFor: 'other' */ + + sqInt (*becomewith)(sqInt array1, sqInt array2); + sqInt (*byteSwapped)(sqInt w); + sqInt (*failed)(void); + sqInt (*fullDisplayUpdate)(void); + void (*fullGC)(void); + void (*incrementalGC)(void); + sqInt (*primitiveFail)(void); + sqInt (*showDisplayBitsLeftTopRightBottom)(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b); + sqInt (*signalSemaphoreWithIndex)(sqInt semaIndex); + sqInt (*success)(sqInt aBoolean); + sqInt (*superclassOf)(sqInt classPointer); + +# if VM_PROXY_MINOR > 13 + /* Reuse these now that Cog provides a production JIT. */ + sqInt (*statNumGCs)(void); + sqInt (*stringForCString)(char *nullTerminatedCString); +# else + /* InterpreterProxy methodsFor: 'compiler' */ + + CompilerHook *(*compilerHookVector)(void); + sqInt (*setCompilerInitialized)(sqInt initFlag); +# endif + +#if VM_PROXY_MINOR > 1 + + /* InterpreterProxy methodsFor: 'BitBlt support' */ + + sqInt (*loadBitBltFrom)(sqInt bbOop); + sqInt (*copyBits)(void); + sqInt (*copyBitsFromtoat)(sqInt leftX, sqInt rightX, sqInt yValue); + +#endif + +#if VM_PROXY_MINOR > 2 + + sqInt (*classLargeNegativeInteger)(void); + sqInt (*signed32BitIntegerFor)(sqInt integerValue); + int (*signed32BitValueOf)(sqInt oop); + sqInt (*includesBehaviorThatOf)(sqInt aClass, sqInt aSuperClass); + sqInt (*primitiveMethod)(void); + + /* InterpreterProxy methodsFor: 'FFI support' */ + + sqInt (*classExternalAddress)(void); + sqInt (*classExternalData)(void); + sqInt (*classExternalFunction)(void); + sqInt (*classExternalLibrary)(void); + sqInt (*classExternalStructure)(void); + void *(*ioLoadModuleOfLength)(sqInt modIndex, sqInt modLength); + void *(*ioLoadSymbolOfLengthFromModule)(sqInt fnIndex, sqInt fnLength, void *handle); + sqInt (*isInMemory)(sqInt address); + +#endif + +#if VM_PROXY_MINOR > 3 + + void *(*ioLoadFunctionFrom)(char *fnName, char *modName); + unsigned int (*ioMicroMSecs)(void); + +#endif + +#if VM_PROXY_MINOR > 4 + +# if !defined(sqLong) +# if _MSC_VER +# define sqLong __int64 +# define usqLong unsigned __int64 +# else +# define sqLong long long +# define usqLong unsigned long long +# endif +# endif + + sqInt (*positive64BitIntegerFor)(usqLong integerValue); + usqLong(*positive64BitValueOf)(sqInt oop); + sqInt (*signed64BitIntegerFor)(sqLong integerValue); + sqLong (*signed64BitValueOf)(sqInt oop); + +#endif + +#if VM_PROXY_MINOR > 5 + sqInt (*isArray)(sqInt oop); + void (*forceInterruptCheck)(void); +#endif + +#if VM_PROXY_MINOR > 6 + sqInt (*fetchLong32ofObject)(sqInt fieldFieldIndex, sqInt oop); + sqInt (*getThisSessionID)(void); + sqInt (*ioFilenamefromStringofLengthresolveAliases)(char* aCharBuffer, char* filenameIndex, sqInt filenameLength, sqInt resolveFlag); + sqInt (*vmEndianness)(void); +#endif + +#if VM_PROXY_MINOR > 7 + /* New methods for proxy version 1.8 */ + + /* callbackEnter: Re-enter the interpreter loop for a callback. + Arguments: + callbackID: Pointer to a location receiving the callback ID + used in callbackLeave + Returns: True if successful, false otherwise */ + sqInt (*callbackEnter)(sqInt *callbackID); + +#if OLD_FOR_REFERENCE + /* N.B. callbackLeave is only ever called from the interpreter. Further, it + * and callbackEnter are obsoleted by Alien/FFI callbacks that are simpler + * and faster. + */ + /* callbackLeave: Leave the interpreter from a previous callback + Arguments: + callbackID: The ID of the callback received from callbackEnter() + Returns: True if succcessful, false otherwise. */ + sqInt (*callbackLeave)(sqInt callbackID); +#else + sqInt (*primitiveFailForwithSecondary)(sqInt failCode, sqLong secondaryCode); +#endif + + /* addGCRoot: Add a variable location to the garbage collector. + The contents of the variable location will be updated accordingly. + Arguments: + varLoc: Pointer to the variable location + Returns: True if successful, false otherwise. */ + sqInt (*addGCRoot)(sqInt *varLoc); + + /* removeGCRoot: Remove a variable location from the garbage collector. + Arguments: + varLoc: Pointer to the variable location + Returns: True if successful, false otherwise. + */ + sqInt (*removeGCRoot)(sqInt *varLoc); +#endif + +#if VM_PROXY_MINOR > 8 + /* See interp.h and above for standard error codes. */ + sqInt (*primitiveFailFor)(sqInt code); + void *(*setInterruptCheckChain)(void (*aFunction)(void)); + sqInt (*classAlien)(void); + sqInt (*classUnsafeAlien)(void); +# if OLD_FOR_REFERENCE /* slot repurposed for storeLong32ofObjectwithValue */ + sqInt (*sendInvokeCallbackStackRegistersJmpbuf)(sqInt thunkPtrAsInt, sqInt stackPtrAsInt, sqInt regsPtrAsInt, sqInt jmpBufPtrAsInt); +# else + usqInt (*storeLong32ofObjectwithValue)(sqInt index, sqInt oop, usqInt); +# endif + sqInt (*reestablishContextPriorToCallback)(sqInt callbackContext); + sqInt *(*getStackPointer)(void); + sqInt (*isOopImmutable)(sqInt oop); + sqInt (*isOopMutable)(sqInt oop); +#endif + +#if VM_PROXY_MINOR > 9 +# if VM_PROXY_MINOR > 13 /* OS Errors available in primitives; easy return forms */ + sqInt (*methodReturnBool)(sqInt); + sqInt (*methodReturnFloat)(double); + sqInt (*methodReturnInteger)(sqInt); + sqInt (*methodReturnString)(char *); +# define returnSelf() methodReturnValue(0) +# else + sqInt (*methodArg) (sqInt index); /* These ended up never being used. */ + sqInt (*objectArg) (sqInt index); + sqInt (*integerArg) (sqInt index); + double (*floatArg) (sqInt index); +# endif + sqInt (*methodReturnValue) (sqInt oop); + sqInt (*topRemappableOop) (void); +#endif + +#if VM_PROXY_MINOR > 10 + sqInt (*disownVM)(sqInt flags); + sqInt (*ownVM) (sqInt threadIdAndFlags); + void (*addHighPriorityTickee)(void (*ticker)(void), unsigned periodms); + void (*addSynchronousTickee)(void (*ticker)(void), unsigned periodms, unsigned roundms); + usqLong (*utcMicroseconds)(void); + void (*tenuringIncrementalGC)(void); + sqInt (*isYoung) (sqInt anOop); + sqInt (*isKindOfClass)(sqInt oop, sqInt aClass); + sqInt (*primitiveErrorTable)(void); + sqInt (*primitiveFailureCode)(void); + sqInt (*instanceSizeOf)(sqInt aClass); +#endif + +#if VM_PROXY_MINOR > 11 +/* VMCallbackContext opaque type avoids all including setjmp.h & vmCallback.h */ + sqInt (*sendInvokeCallbackContext)(vmccp); + sqInt (*returnAsThroughCallbackContext)(sqInt, vmccp, sqInt); + sqIntptr_t (*signedMachineIntegerValueOf)(sqInt); + sqIntptr_t (*stackSignedMachineIntegerValue)(sqInt); + usqIntptr_t (*positiveMachineIntegerValueOf)(sqInt); + usqIntptr_t (*stackPositiveMachineIntegerValue)(sqInt); + sqInt (*getInterruptPending)(void); + char *(*cStringOrNullFor)(sqInt); + void *(*startOfAlienData)(sqInt); + usqInt (*sizeOfAlienData)(sqInt); + sqInt (*signalNoResume)(sqInt); +#endif + +#if VM_PROXY_MINOR > 12 /* Spur */ + sqInt (*isImmediate)(sqInt objOop); + sqInt (*characterObjectOf)(int charCode); + sqInt (*characterValueOf)(sqInt objOop); + sqInt (*isCharacterObject)(sqInt objOop); + sqInt (*isCharacterValue)(int charCode); + sqInt (*isPinned)(sqInt objOop); + sqInt (*pinObject)(sqInt objOop); + sqInt (*unpinObject)(sqInt objOop); +#endif + +#if VM_PROXY_MINOR > 13 /* OS Errors available in primitives; easy return forms (see above) */ + sqInt (*primitiveFailForOSError)(sqLong osErrorCode); + sqInt (*methodReturnReceiver)(void); + sqInt (*primitiveFailForFFIExceptionat)(usqLong exceptionCode, usqInt pc); +#endif + +#if VM_PROXY_MINOR > 14 /* SmartSyntaxPlugin validation rewrite support */ + sqInt (*isBooleanObject)(sqInt oop); + sqInt (*isPositiveMachineIntegerObject)(sqInt); +#endif +#if VM_PROXY_MINOR > 15 /* Spur integer and float array classes */ + sqInt (*classDoubleByteArray)(void); + sqInt (*classWordArray)(void); + sqInt (*classDoubleWordArray)(void); + sqInt (*classFloat32Array)(void); + sqInt (*classFloat64Array)(void); +#endif +#if VM_PROXY_MINOR > 16 /* Spur isShorts, isLong64s testing, hash etc */ + sqInt (*isShorts)(sqInt oop); + sqInt (*isLong64s)(sqInt oop); + sqInt (*identityHashOf)(sqInt oop); + sqInt (*isWordsOrShorts)(sqInt oop); /* for SoundPlugin et al */ + sqInt (*bytesPerElement)(sqInt oop); /* for SocketPugin et al */ + sqInt (*fileTimesInUTC)(void); /* for FilePlugin et al */ +#endif +} VirtualMachine; diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h new file mode 100644 index 000000000..2ee037cf6 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h @@ -0,0 +1,33 @@ +#include +#include "sqMemoryAccess.h" + +/* Automatically generated by + CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3150 uuid: 832f44e4-6d22-4545-ae94-d8453b49d54f + */ + +#define VM_CALLBACK_INC 1 + +typedef struct _VMCallbackContext { + void *thunkp; + sqIntptr_t *stackp; + sqIntptr_t *intregargsp; + double *floatregargsp; + void *savedCStackPointer; + void *savedCFramePointer; + union { + sqIntptr_t valword; + struct { int low, high; } valleint64; + struct { int high, low; } valbeint64; + double valflt64; + struct { void *addr; sqIntptr_t size; } valstruct; + }rvs; + void *savedMostRecentCallbackContext; + jmp_buf trampoline; + jmp_buf savedReenterInterpreter; + } VMCallbackContext; + +/* The callback return type codes */ +#define retword 1 +#define retword64 2 +#define retdouble 3 +#define retstruct 4 diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c new file mode 100644 index 000000000..bdc0adde5 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -0,0 +1,24 @@ +#include +#include "sqVirtualMachine.h" + +VirtualMachine* createInterpreterProxy( + sqInt (*byteSizeOf)(sqInt oop), + void *(*firstIndexableField)(sqInt oop), + sqInt (*isBytes)(sqInt oop), + sqInt (*majorVersion)(void), + sqInt (*methodArgumentCount)(void), + sqInt (*minorVersion)(void), + sqInt (*primitiveFail)(void), + sqInt (*stackValue)(sqInt offset) +) { + VirtualMachine* interpreterProxy = (VirtualMachine*)calloc(1, sizeof(VirtualMachine)); + interpreterProxy->byteSizeOf = byteSizeOf; + interpreterProxy->firstIndexableField = firstIndexableField; + interpreterProxy->isBytes = isBytes; + interpreterProxy->majorVersion = majorVersion; + interpreterProxy->methodArgumentCount = methodArgumentCount; + interpreterProxy->minorVersion = minorVersion; + interpreterProxy->primitiveFail = primitiveFail; + interpreterProxy->stackValue = stackValue; + return interpreterProxy; +} From bec7a02390c331ba1d3040155c9296f4e3185ad8 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Fri, 10 Nov 2023 11:08:23 +0100 Subject: [PATCH 033/159] Add stub methods for interpreter proxy [skip ci] --- .../primitives/PrimitiveNodeFactory.java | 117 +++++++++++++----- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 120a42ea7..1b203314d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -6,24 +6,13 @@ */ package de.hpi.swa.trufflesqueak.nodes.primitives; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - +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.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnknownIdentifierException; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.interop.UnsupportedTypeException; import com.oracle.truffle.api.source.Source; -import com.oracle.truffle.nfi.backend.spi.NFIBackend; +import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; -import de.hpi.swa.trufflesqueak.nodes.AbstractNode; -import org.graalvm.collections.EconomicMap; - -import com.oracle.truffle.api.dsl.NodeFactory; - import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.NativeObject; @@ -53,7 +42,6 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakFFIPrims; import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakSSL; import de.hpi.swa.trufflesqueak.nodes.plugins.TruffleSqueakPlugin; -import de.hpi.swa.trufflesqueak.nodes.plugins.UUIDPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.UnixOSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.Win32OSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ZipPlugin; @@ -66,7 +54,17 @@ import de.hpi.swa.trufflesqueak.nodes.primitives.impl.IOPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.MiscellaneousPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.StoragePrimitives; +import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.OS; +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; @@ -123,7 +121,7 @@ public final class PrimitiveNodeFactory { new SoundCodecPrims(), new SqueakFFIPrims(), new SqueakSSL(), - new UUIDPlugin(), + //new UUIDPlugin(), new ZipPlugin(), OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; fillPrimitiveTable(plugins); @@ -218,30 +216,93 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (functionName.equals("primitivePluginVersion")) { return null; } - return new NonExistentPrimitiveNode(); + return new NonExistentPrimitiveNode(moduleName, functionName); } } static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { + final String moduleName; + final String functionName; + + public NonExistentPrimitiveNode(String moduleName, String functionName) { + this.moduleName = moduleName; + this.functionName = functionName; + } + @Override public Object execute(VirtualFrame frame) { - final String nfiCode = "load \"UUIDPlugin.so\" { getModuleName():STRING; }"; - final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); - final SqueakImageContext image = getContext(); - final Object ffiTest = image.env.parseInternal(source).call(); - final InteropLibrary interopLib = InteropLibrary.getFactory().getUncached(ffiTest); - - final String name = "getModuleName"; + final Object interpreterProxy = loadLibrary("libInterpreterProxy", + "{ createInterpreterProxy((SINT64):SINT64,(SINT64):[UINT8],(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }"); + final Object uuidPlugin = loadLibrary("UUIDPlugin", "{ " + + "initialiseModule():VOID; " + + "setInterpreter(POINTER):VOID; " + + "shutdownModule():VOID; " + + functionName + "():STRING; " + + " }"); + final InteropLibrary interpreterProxyLibrary = getInteropLibrary(interpreterProxy); + final InteropLibrary uuidPluginLibrary = getInteropLibrary(uuidPlugin); try { - Object returnValue = interopLib.invokeMember(ffiTest, name); - return returnValue; - } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException | ArityException e) { - e.printStackTrace(); + ArrayList objectRegistry = new ArrayList<>(); + Function byteSizeOf = (index) -> 16; + Function firstIndexableField = (index) -> ((NativeObject)objectRegistry.get(index)).getByteStorage(); + Function isBytes = (integer) -> true; + Supplier majorVersion = () -> 1; + Supplier methodArgumentCount = () -> 0; + Supplier minorVersion = () -> 17; + Supplier primitiveFail = () -> { assert false; return -1; }; + Function stackValue = (stackIndex) -> { + Object objectOnStack = FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); + int objectIndex = objectRegistry.size(); + objectRegistry.add(objectOnStack); + return objectIndex; + }; + final Object interpreterProxyPointer = interpreterProxyLibrary.invokeMember( + interpreterProxy, + "createInterpreterProxy", + byteSizeOf, + firstIndexableField, + isBytes, + majorVersion, + methodArgumentCount, + minorVersion, + 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); + System.out.println("setInterpreterOk = " + setInterpreterOk); + final Object result = uuidPluginLibrary.invokeMember(uuidPlugin, functionName); + System.out.println("result = " + result); + final Object shutdownOk = uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); + System.out.println("shutdownOk = " + shutdownOk); + return result; + } catch (Exception e) { + System.out.println("error"); + e.printStackTrace(System.err); return null; } } + private Object loadLibrary(String moduleName, String boundSymbols) { + final SqueakImageContext image = getContext(); + final String libName = System.mapLibraryName(moduleName); + final TruffleFile libPath = image.getHomePath().resolve("lib" + File.separatorChar + libName); + if (!libPath.exists()) { + throw PrimitiveFailed.GENERIC_ERROR; + } + + final String nfiCode = "load \"" + libPath.getPath() + "\" " + boundSymbols; + final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); + return image.env.parseInternal(source).call(); + } + + private InteropLibrary getInteropLibrary(Object loadedLibrary) { + return InteropLibrary.getFactory().getUncached(loadedLibrary); + } + @Override public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { return execute(frame); From 0cd1f04be0cd67b0a5cb55fa2dd7985d4826b240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 11 Nov 2023 16:25:36 +0100 Subject: [PATCH 034/159] Implement ByteStorage using extended UnsafeUtils and add TruffleExecutable --- .../primitives/PrimitiveNodeFactory.java | 135 +++++++++++++++--- .../swa/trufflesqueak/util/UnsafeUtils.java | 11 ++ 2 files changed, 124 insertions(+), 22 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 1b203314d..80b8b5dcc 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -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; @@ -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; @@ -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 TruffleExecutable wrapFunction(TruffleFunction function) { + return new TruffleExecutable(function); + } + + static TruffleExecutable wrapSupplier(TruffleSupplier 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 extends ITruffleExecutable { + R run(T argument); + + default Object execute(Object... arguments) { + assert arguments.length == 1; + return run((T) arguments[0]); + } + } + + @FunctionalInterface + interface TruffleSupplier 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; @@ -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 postPrimitiveCleanups = new ArrayList<>(); try { ArrayList objectRegistry = new ArrayList<>(); - Function byteSizeOf = (index) -> 16; - Function firstIndexableField = (index) -> ((NativeObject)objectRegistry.get(index)).getByteStorage(); - Function isBytes = (integer) -> true; - Supplier majorVersion = () -> 1; - Supplier methodArgumentCount = () -> 0; - Supplier minorVersion = () -> 17; - Supplier primitiveFail = () -> { assert false; return -1; }; - Function 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", @@ -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); @@ -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(); + } } } @@ -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; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java index 324f0f31d..aea73e632 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java @@ -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; } From 71d775a04ee8e7f7694ad620954fb8f13e8d7350 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 15 Nov 2023 14:50:25 +0100 Subject: [PATCH 035/159] Set absolute library path (for now) [skip ci] --- .../nodes/primitives/PrimitiveNodeFactory.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 80b8b5dcc..c90332892 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -10,12 +10,10 @@ 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; import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.NativeObject; @@ -306,15 +304,16 @@ public Object execute(VirtualFrame frame) { }); TruffleExecutable isBytes = TruffleExecutable.wrapFunction((integer) -> 1L); // true TruffleExecutable majorVersion = TruffleExecutable.wrapSupplier(() -> 1L); - TruffleExecutable methodArgumentCount = TruffleExecutable.wrapSupplier(() -> 0L); + TruffleExecutable methodArgumentCount = TruffleExecutable.wrapSupplier(() -> 0L) ; TruffleExecutable minorVersion = TruffleExecutable.wrapSupplier(() -> 17L); - TruffleExecutable primitiveFail = TruffleExecutable.wrapSupplier(() -> { assert false; return -1L; }); + TruffleExecutable primitiveFail = TruffleExecutable.wrapSupplier(() -> { throw PrimitiveFailed.GENERIC_ERROR; }); TruffleExecutable stackValue = TruffleExecutable.wrapFunction((stackIndex) -> { Object objectOnStack = FrameAccess.getStackValue(frame, (int)(long)stackIndex, FrameAccess.getNumArguments(frame)); int objectIndex = objectRegistry.size(); objectRegistry.add(objectOnStack); return (long)objectIndex; }); + final Object interpreterProxyPointer = interpreterProxyLibrary.invokeMember( interpreterProxy, "createInterpreterProxy", @@ -348,16 +347,9 @@ public Object execute(VirtualFrame frame) { } private Object loadLibrary(String moduleName, String boundSymbols) { - final SqueakImageContext image = getContext(); - final String libName = System.mapLibraryName(moduleName); - final TruffleFile libPath = image.getHomePath().resolve("lib" + File.separatorChar + libName); - if (!libPath.exists()) { - throw PrimitiveFailed.GENERIC_ERROR; - } - - final String nfiCode = "load \"" + libPath.getPath() + "\" " + boundSymbols; + final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); - return image.env.parseInternal(source).call(); + return getContext().env.parseInternal(source).call(); } private InteropLibrary getInteropLibrary(Object loadedLibrary) { From e5340bc32670bcbd5f2db662d4e720d6d391459d Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 15 Nov 2023 16:39:26 +0100 Subject: [PATCH 036/159] Create InterpreterProxy and extract inner classes --- .../nodes/plugins/ffi/InterpreterProxy.java | 94 +++++++++++ .../plugins/ffi/wrappers/ByteStorage.java | 34 ++++ .../primitives/PrimitiveNodeFactory.java | 157 ++---------------- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 85 ++++++++++ 4 files changed, 225 insertions(+), 145 deletions(-) create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java new file mode 100644 index 000000000..5dc516cb4 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -0,0 +1,94 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; + +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; +import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; +import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.model.NativeObject; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.ByteStorage; +import de.hpi.swa.trufflesqueak.util.FrameAccess; +import de.hpi.swa.trufflesqueak.util.NFIUtils; + +import java.util.ArrayList; + +public class InterpreterProxy { + + private final VirtualFrame frame; + private final ArrayList objectRegistry = new ArrayList<>(); + private final ArrayList postPrimitiveCleanups = new ArrayList<>(); + + private static Object interpreterProxyPointer = null; + + public InterpreterProxy(SqueakImageContext context, VirtualFrame frame) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + this.frame = frame; + if (interpreterProxyPointer == null) { + final Object interpreterProxy = NFIUtils.loadLibrary( + context, + "InterpreterProxy.so", + "{ createInterpreterProxy((SINT64):SINT64,(SINT64):POINTER,(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }" + ); + + final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); + interpreterProxyPointer = interpreterProxyLibrary.invokeMember( + interpreterProxy,"createInterpreterProxy", (Object[]) getExecutables()); + } + } + public Object getPointer() { + return interpreterProxyPointer; + } + + public NFIUtils.TruffleExecutable[] getExecutables() { + return new NFIUtils.TruffleExecutable[] { + NFIUtils.TruffleExecutable.wrap(this::byteSizeOf), + NFIUtils.TruffleExecutable.wrap(this::firstIndexableField), + NFIUtils.TruffleExecutable.wrap(this::isBytes), + NFIUtils.TruffleExecutable.wrap(this::majorVersion), + NFIUtils.TruffleExecutable.wrap(this::methodArgumentCount), + NFIUtils.TruffleExecutable.wrap(this::minorVersion), + NFIUtils.TruffleExecutable.wrap(this::primitiveFail), + NFIUtils.TruffleExecutable.wrap(this::stackValue), + }; + } + public void postPrimitiveCleanups() { + postPrimitiveCleanups.forEach(de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup::cleanup); + } + + private int byteSizeOf() { + return 16; + } + private ByteStorage firstIndexableField(long index) { + byte[] storage = ((NativeObject) objectRegistry.get((int) index)).getByteStorage(); + ByteStorage byteStorage = new ByteStorage(storage); + postPrimitiveCleanups.add(byteStorage); + return byteStorage; + } + private int isBytes(long oop) { + return 1; + } + private int majorVersion() { + return 1; + } + private int methodArgumentCount() { + return FrameAccess.getNumArguments(frame); + } + private int minorVersion() { + return 17; + } + private int primitiveFail() { + throw PrimitiveFailed.GENERIC_ERROR; + } + private int stackValue(long stackIndex) { + Object objectOnStack = FrameAccess.getStackValue(frame, (int) stackIndex, FrameAccess.getNumArguments(frame)); + int objectIndex = objectRegistry.size(); + objectRegistry.add(objectOnStack); + return objectIndex; + } + + public interface PostPrimitiveCleanup { + void cleanup(); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java new file mode 100644 index 000000000..df2703dac --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -0,0 +1,34 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public 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); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index c90332892..df9553a79 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -9,10 +9,6 @@ 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.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.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; @@ -46,6 +42,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.UnixOSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.Win32OSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ZipPlugin; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy; import de.hpi.swa.trufflesqueak.nodes.plugins.network.SocketPlugin; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArithmeticPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArrayStreamPrimitives; @@ -55,12 +52,10 @@ import de.hpi.swa.trufflesqueak.nodes.primitives.impl.IOPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.MiscellaneousPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.StoragePrimitives; -import de.hpi.swa.trufflesqueak.util.FrameAccess; +import de.hpi.swa.trufflesqueak.util.NFIUtils; import de.hpi.swa.trufflesqueak.util.OS; -import de.hpi.swa.trufflesqueak.util.UnsafeUtils; import org.graalvm.collections.EconomicMap; -import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -219,57 +214,6 @@ 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 TruffleExecutable wrapFunction(TruffleFunction function) { - return new TruffleExecutable(function); - } - - static TruffleExecutable wrapSupplier(TruffleSupplier 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 extends ITruffleExecutable { - R run(T argument); - - default Object execute(Object... arguments) { - assert arguments.length == 1; - return run((T) arguments[0]); - } - } - - @FunctionalInterface - interface TruffleSupplier 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; @@ -281,117 +225,40 @@ public NonExistentPrimitiveNode(String moduleName, String functionName) { @Override public Object execute(VirtualFrame frame) { - final Object interpreterProxy = loadLibrary("libInterpreterProxy", - "{ createInterpreterProxy((SINT64):SINT64,(SINT64):POINTER,(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }"); - final Object uuidPlugin = loadLibrary("UUIDPlugin", "{ " + + final Object uuidPlugin = NFIUtils.loadLibrary(getContext(), "UUIDPlugin.so", "{ " + "initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + "shutdownModule():SINT64; " + functionName + "():SINT64; " + " }"); - final InteropLibrary interpreterProxyLibrary = getInteropLibrary(interpreterProxy); - final InteropLibrary uuidPluginLibrary = getInteropLibrary(uuidPlugin); - ArrayList postPrimitiveCleanups = new ArrayList<>(); + final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); + InterpreterProxy interpreterProxy = null; try { + interpreterProxy = new InterpreterProxy(getContext(), frame); - ArrayList objectRegistry = new ArrayList<>(); - 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(() -> { throw PrimitiveFailed.GENERIC_ERROR; }); - TruffleExecutable stackValue = TruffleExecutable.wrapFunction((stackIndex) -> { - Object objectOnStack = FrameAccess.getStackValue(frame, (int)(long)stackIndex, FrameAccess.getNumArguments(frame)); - int objectIndex = objectRegistry.size(); - objectRegistry.add(objectOnStack); - return (long)objectIndex; - }); - - final Object interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy, - "createInterpreterProxy", - byteSizeOf, - firstIndexableField, - isBytes, - majorVersion, - methodArgumentCount, - minorVersion, - 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); - System.out.println("setInterpreterOk = " + setInterpreterOk); + uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); + uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); final Object result = uuidPluginLibrary.invokeMember(uuidPlugin, functionName); - System.out.println("result = " + result); - final Object shutdownOk = uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); - System.out.println("shutdownOk = " + shutdownOk); + uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); + return result; } catch (Exception e) { System.out.println("error"); e.printStackTrace(System.err); throw PrimitiveFailed.GENERIC_ERROR; } finally { - for (var postPrimitiveCleanup : postPrimitiveCleanups) { - postPrimitiveCleanup.cleanup(); + if (interpreterProxy != null) { + interpreterProxy.postPrimitiveCleanups(); } } } - private Object loadLibrary(String moduleName, String boundSymbols) { - final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; - final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); - return getContext().env.parseInternal(source).call(); - } - - private InteropLibrary getInteropLibrary(Object loadedLibrary) { - return InteropLibrary.getFactory().getUncached(loadedLibrary); - } - @Override public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { return execute(frame); } } - 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; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java new file mode 100644 index 000000000..c5e11832d --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -0,0 +1,85 @@ +package de.hpi.swa.trufflesqueak.util; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +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.image.SqueakImageContext; + +public class NFIUtils { + + @ExportLibrary(InteropLibrary.class) + public static class TruffleExecutable implements TruffleObject { + ITruffleExecutable executable; + + public TruffleExecutable(ITruffleExecutable executable) { + this.executable = executable; + } + + public static TruffleExecutable wrap(TruffleFunction function) { + return new TruffleExecutable(function); + } + static TruffleExecutable wrap(TruffleBiFunction function) { + return new TruffleExecutable(function); + } + + public static TruffleExecutable wrap(TruffleSupplier supplier) { + return new TruffleExecutable(supplier); + } + + @ExportMessage + boolean isExecutable() { + return true; + } + + @ExportMessage + Object execute(Object... arguments) { + return executable.execute(arguments); + } + } + + public interface ITruffleExecutable { + Object execute(Object... arguments); + } + + @FunctionalInterface + public interface TruffleFunction extends ITruffleExecutable { + R run(T argument); + + default Object execute(Object... arguments) { + assert arguments.length == 1; + return run((T) arguments[0]); + } + } + + @FunctionalInterface + public interface TruffleBiFunction extends ITruffleExecutable { + R run(S argument1, T argument2); + + default Object execute(Object... arguments) { + assert arguments.length == 2; + return run((S) arguments[0], (T) arguments[1]); + } + } + + @FunctionalInterface + public interface TruffleSupplier extends ITruffleExecutable { + R run(); + + default Object execute(Object... arguments) { + assert arguments.length == 0; + return run(); + } + } + + public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { + final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; + final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); + return context.env.parseInternal(source).call(); + } + + public static InteropLibrary getInteropLibrary(Object loadedLibrary) { + return InteropLibrary.getFactory().getUncached(loadedLibrary); + } +} From 3f75e6a1bf8987b5089141bfbb38e05e2adfce82 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 15 Nov 2023 16:41:05 +0100 Subject: [PATCH 037/159] Fix argument --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 5dc516cb4..620df1f50 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -57,11 +57,11 @@ public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup::cleanup); } - private int byteSizeOf() { + private int byteSizeOf(long oop) { return 16; } - private ByteStorage firstIndexableField(long index) { - byte[] storage = ((NativeObject) objectRegistry.get((int) index)).getByteStorage(); + private ByteStorage firstIndexableField(long oop) { + byte[] storage = ((NativeObject) objectRegistry.get((int) oop)).getByteStorage(); ByteStorage byteStorage = new ByteStorage(storage); postPrimitiveCleanups.add(byteStorage); return byteStorage; From 182f756162eb1a3f4de1235d87628622e10ad0f0 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 15 Nov 2023 16:59:02 +0100 Subject: [PATCH 038/159] Generalize ByteStorage --- .../plugins/ffi/wrappers/ByteStorage.java | 18 +++------- .../plugins/ffi/wrappers/IntStorage.java | 24 +++++++++++++ .../plugins/ffi/wrappers/LongStorage.java | 24 +++++++++++++ .../ffi/wrappers/NativeObjectStorage.java | 33 +++++++++++++++++ .../plugins/ffi/wrappers/ShortStorage.java | 24 +++++++++++++ .../swa/trufflesqueak/util/UnsafeUtils.java | 35 ++++++++++++++++++- 6 files changed, 143 insertions(+), 15 deletions(-) create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index df2703dac..9cc63ee32 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -1,30 +1,20 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; -import com.oracle.truffle.api.library.ExportMessage; -import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; @ExportLibrary(InteropLibrary.class) -public class ByteStorage implements PostPrimitiveCleanup, TruffleObject { +public class ByteStorage extends NativeObjectStorage { 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 + protected void allocate() { + nativeAddress = UnsafeUtils.allocateNativeBytes(storage); } @Override diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java new file mode 100644 index 000000000..fc904a805 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -0,0 +1,24 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public class IntStorage extends NativeObjectStorage { + int[] storage; + + public IntStorage(int[] storage) { + this.storage = storage; + } + + @Override + protected void allocate() { + nativeAddress = UnsafeUtils.allocateNativeInts(storage); + } + + @Override + public void cleanup() { + UnsafeUtils.copyNativeIntsBackAndFree(nativeAddress, storage); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java new file mode 100644 index 000000000..3d8955f4c --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -0,0 +1,24 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public class LongStorage extends NativeObjectStorage { + long[] storage; + + public LongStorage(long[] storage) { + this.storage = storage; + } + + @Override + protected void allocate() { + nativeAddress = UnsafeUtils.allocateNativeLongs(storage); + } + + @Override + public void cleanup() { + UnsafeUtils.copyNativeLongsBackAndFree(nativeAddress, storage); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java new file mode 100644 index 000000000..73199e579 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -0,0 +1,33 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public abstract class NativeObjectStorage implements PostPrimitiveCleanup, TruffleObject { + protected long nativeAddress; + private boolean isAllocated = false; + + @ExportMessage + public boolean isPointer() { + return isAllocated; + } + + @ExportMessage + public long asPointer() { + return nativeAddress; + } + + @ExportMessage + public void toNative() { + if (isAllocated) return; + allocate(); + isAllocated = true; + } + + protected abstract void allocate(); +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java new file mode 100644 index 000000000..8ad6a2cf2 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -0,0 +1,24 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import de.hpi.swa.trufflesqueak.util.UnsafeUtils; + +@ExportLibrary(InteropLibrary.class) +public class ShortStorage extends NativeObjectStorage { + short[] storage; + + public ShortStorage(short[] storage) { + this.storage = storage; + } + + @Override + protected void allocate() { + nativeAddress = UnsafeUtils.allocateNativeShorts(storage); + } + + @Override + public void cleanup() { + UnsafeUtils.copyNativeShortsBackAndFree(nativeAddress, storage); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java index aea73e632..640ba9ac7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java @@ -67,16 +67,49 @@ public static void copyShorts(final short[] src, final long srcPos, final short[ } public static long allocateNativeBytes(final byte[] src) { - final long address = UNSAFE.allocateMemory(src.length); + final long address = UNSAFE.allocateMemory((long) src.length * Byte.BYTES); UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length * Byte.BYTES); return address; } + public static long allocateNativeShorts(final short[] src) { + final long address = UNSAFE.allocateMemory((long) src.length * Short.BYTES); + UNSAFE.copyMemory(src, Unsafe.ARRAY_SHORT_BASE_OFFSET, null, address, (long) src.length * Short.BYTES); + return address; + } + + public static long allocateNativeInts(final int[] src) { + final long address = UNSAFE.allocateMemory((long) src.length * Integer.BYTES); + UNSAFE.copyMemory(src, Unsafe.ARRAY_INT_BASE_OFFSET, null, address, (long) src.length * Integer.BYTES); + return address; + } + + public static long allocateNativeLongs(final long[] src) { + final long address = UNSAFE.allocateMemory((long) src.length * Long.BYTES); + UNSAFE.copyMemory(src, Unsafe.ARRAY_LONG_BASE_OFFSET, null, address, (long) src.length * Long.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 void copyNativeShortsBackAndFree(final long address, short[] dest) { + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_SHORT_BASE_OFFSET, (long) dest.length * Short.BYTES); + UNSAFE.freeMemory(address); + } + + public static void copyNativeIntsBackAndFree(final long address, int[] dest) { + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_INT_BASE_OFFSET, (long) dest.length * Integer.BYTES); + UNSAFE.freeMemory(address); + } + + public static void copyNativeLongsBackAndFree(final long address, long[] dest) { + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_LONG_BASE_OFFSET, (long) dest.length * Long.BYTES); + UNSAFE.freeMemory(address); + } + public static long fromLongsOffset(final long offset) { return (offset - Unsafe.ARRAY_LONG_BASE_OFFSET) / Unsafe.ARRAY_LONG_INDEX_SCALE; } From 88a397297a2c1b60597437fcb7b7df9070646f38 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 14:09:06 +0100 Subject: [PATCH 039/159] Remove redundant fully-qualified class name --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 620df1f50..ad44af54e 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -19,7 +19,7 @@ public class InterpreterProxy { private final VirtualFrame frame; private final ArrayList objectRegistry = new ArrayList<>(); - private final ArrayList postPrimitiveCleanups = new ArrayList<>(); + private final ArrayList postPrimitiveCleanups = new ArrayList<>(); private static Object interpreterProxyPointer = null; @@ -54,7 +54,7 @@ public NFIUtils.TruffleExecutable[] getExecutables() { }; } public void postPrimitiveCleanups() { - postPrimitiveCleanups.forEach(de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup::cleanup); + postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); } private int byteSizeOf(long oop) { From 8c9b050cb24c139293adb451cd4154fbc6316e89 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 14:15:49 +0100 Subject: [PATCH 040/159] Do not assume ByteStorage --- .../nodes/plugins/ffi/InterpreterProxy.java | 11 +++++------ .../ffi/wrappers/NativeObjectStorage.java | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index ad44af54e..7773d0e02 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -9,7 +9,7 @@ import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.model.NativeObject; -import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.ByteStorage; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; @@ -60,11 +60,10 @@ public void postPrimitiveCleanups() { private int byteSizeOf(long oop) { return 16; } - private ByteStorage firstIndexableField(long oop) { - byte[] storage = ((NativeObject) objectRegistry.get((int) oop)).getByteStorage(); - ByteStorage byteStorage = new ByteStorage(storage); - postPrimitiveCleanups.add(byteStorage); - return byteStorage; + private NativeObjectStorage firstIndexableField(long oop) { + NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistry.get((int) oop)); + postPrimitiveCleanups.add(storage); + return storage; } private int isBytes(long oop) { return 1; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index 73199e579..ae0a6fefb 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -4,14 +4,29 @@ import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; +import de.hpi.swa.trufflesqueak.model.NativeObject; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; -import de.hpi.swa.trufflesqueak.util.UnsafeUtils; @ExportLibrary(InteropLibrary.class) public abstract class NativeObjectStorage implements PostPrimitiveCleanup, TruffleObject { protected long nativeAddress; private boolean isAllocated = false; + public static NativeObjectStorage from(NativeObject object) { + if (object.isByteType()) { + return new ByteStorage(object.getByteStorage()); + } else if (object.isIntType()) { + return new IntStorage(object.getIntStorage()); + } else if (object.isLongType()) { + return new LongStorage(object.getLongStorage()); + } else if (object.isShortType()) { + return new ShortStorage(object.getShortStorage()); + } else { + throw new IllegalArgumentException("Object storage type is not supported."); + } + } + + @ExportMessage public boolean isPointer() { return isAllocated; From 4e3d7d6afc4ab9b4f6ea03ebb7b82cbeeee54649 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 14:33:25 +0100 Subject: [PATCH 041/159] Get correct byteSize for storage type --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 7 +++++-- .../nodes/plugins/ffi/wrappers/ByteStorage.java | 5 +++++ .../nodes/plugins/ffi/wrappers/IntStorage.java | 5 +++++ .../nodes/plugins/ffi/wrappers/LongStorage.java | 5 +++++ .../nodes/plugins/ffi/wrappers/NativeObjectStorage.java | 2 ++ .../nodes/plugins/ffi/wrappers/ShortStorage.java | 5 +++++ 6 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 7773d0e02..df2de931d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -56,12 +56,15 @@ public NFIUtils.TruffleExecutable[] getExecutables() { public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); } + private NativeObject objectRegistryGet(long oop) { + return (NativeObject) objectRegistry.get((int) oop); + } private int byteSizeOf(long oop) { - return 16; + return NativeObjectStorage.from(objectRegistryGet(oop)).byteSizeOf(); } private NativeObjectStorage firstIndexableField(long oop) { - NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistry.get((int) oop)); + NativeObjectStorage storage = NativeObjectStorage.from(objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); return storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index 9cc63ee32..8da40a8d8 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -12,6 +12,11 @@ public ByteStorage(byte[] storage) { this.storage = storage; } + @Override + public int byteSizeOf() { + return storage.length * Byte.BYTES; + } + @Override protected void allocate() { nativeAddress = UnsafeUtils.allocateNativeBytes(storage); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index fc904a805..170f3735c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -12,6 +12,11 @@ public IntStorage(int[] storage) { this.storage = storage; } + @Override + public int byteSizeOf() { + return storage.length * Integer.BYTES; + } + @Override protected void allocate() { nativeAddress = UnsafeUtils.allocateNativeInts(storage); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index 3d8955f4c..8a923c123 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -12,6 +12,11 @@ public LongStorage(long[] storage) { this.storage = storage; } + @Override + public int byteSizeOf() { + return storage.length * Long.BYTES; + } + @Override protected void allocate() { nativeAddress = UnsafeUtils.allocateNativeLongs(storage); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index ae0a6fefb..9b68e2a00 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -44,5 +44,7 @@ public void toNative() { isAllocated = true; } + public abstract int byteSizeOf(); + protected abstract void allocate(); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 8ad6a2cf2..9f7a9d58f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -12,6 +12,11 @@ public ShortStorage(short[] storage) { this.storage = storage; } + @Override + public int byteSizeOf() { + return storage.length * Short.BYTES; + } + @Override protected void allocate() { nativeAddress = UnsafeUtils.allocateNativeShorts(storage); From b64f5fb77fe8ad61bfd5effef71cb559067ae2b2 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 14:38:11 +0100 Subject: [PATCH 042/159] Return isBytes by storage type --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index df2de931d..88159a372 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -69,7 +69,7 @@ private NativeObjectStorage firstIndexableField(long oop) { return storage; } private int isBytes(long oop) { - return 1; + return objectRegistryGet(oop).isByteType() ? 1 : 0; } private int majorVersion() { return 1; From fd1207c7003c74a01dfe4b5c9b3bde727a133130 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 16 Nov 2023 15:27:22 +0100 Subject: [PATCH 043/159] Stub symbols needed to support SqueakSSL [skip ci] --- .../src/InterpreterProxy.c | 20 ++++++ .../nodes/plugins/ffi/InterpreterProxy.java | 69 +++++++++++++++---- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 16 +++-- 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index bdc0adde5..7b219d965 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -3,22 +3,42 @@ VirtualMachine* createInterpreterProxy( sqInt (*byteSizeOf)(sqInt oop), + sqInt (*classString)(void), + sqInt (*failed)(void), void *(*firstIndexableField)(sqInt oop), + sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size), sqInt (*isBytes)(sqInt oop), sqInt (*majorVersion)(void), sqInt (*methodArgumentCount)(void), sqInt (*minorVersion)(void), + sqInt (*nilObject)(void), + sqInt (*pop)(sqInt nItems), + sqInt (*popthenPush)(sqInt nItems, sqInt oop), sqInt (*primitiveFail)(void), + sqInt (*pushInteger)(sqInt integerValue), + sqInt (*signed32BitIntegerFor)(sqInt integerValue), + int (*signed32BitValueOf)(sqInt oop), + sqInt (*stackIntegerValue)(sqInt offset), sqInt (*stackValue)(sqInt offset) ) { VirtualMachine* interpreterProxy = (VirtualMachine*)calloc(1, sizeof(VirtualMachine)); interpreterProxy->byteSizeOf = byteSizeOf; + interpreterProxy->classString = classString; + interpreterProxy->failed = failed; interpreterProxy->firstIndexableField = firstIndexableField; + interpreterProxy->instantiateClassindexableSize = instantiateClassindexableSize; interpreterProxy->isBytes = isBytes; interpreterProxy->majorVersion = majorVersion; interpreterProxy->methodArgumentCount = methodArgumentCount; interpreterProxy->minorVersion = minorVersion; + interpreterProxy->nilObject = nilObject; + interpreterProxy->pop = pop; + interpreterProxy->popthenPush = popthenPush; interpreterProxy->primitiveFail = primitiveFail; + interpreterProxy->pushInteger = pushInteger; + interpreterProxy->signed32BitIntegerFor = signed32BitIntegerFor; + interpreterProxy->signed32BitValueOf = signed32BitValueOf; + interpreterProxy->stackIntegerValue = stackIntegerValue; interpreterProxy->stackValue = stackValue; return interpreterProxy; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 88159a372..0e21633b4 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -12,8 +12,11 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; +import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.Collectors; public class InterpreterProxy { @@ -26,31 +29,43 @@ public class InterpreterProxy { public InterpreterProxy(SqueakImageContext context, VirtualFrame frame) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { this.frame = frame; if (interpreterProxyPointer == null) { + final TruffleExecutable[] truffleExecutables = getExecutables(); + final String truffleExecutablesSignatures = Arrays.stream(truffleExecutables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); final Object interpreterProxy = NFIUtils.loadLibrary( context, "InterpreterProxy.so", - "{ createInterpreterProxy((SINT64):SINT64,(SINT64):POINTER,(SINT64):SINT64,():SINT64,():SINT64,():SINT64,():SINT64,(SINT64):SINT64):POINTER; }" + "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" ); final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy,"createInterpreterProxy", (Object[]) getExecutables()); + interpreterProxy,"createInterpreterProxy", (Object[]) truffleExecutables); } } public Object getPointer() { return interpreterProxyPointer; } - public NFIUtils.TruffleExecutable[] getExecutables() { - return new NFIUtils.TruffleExecutable[] { - NFIUtils.TruffleExecutable.wrap(this::byteSizeOf), - NFIUtils.TruffleExecutable.wrap(this::firstIndexableField), - NFIUtils.TruffleExecutable.wrap(this::isBytes), - NFIUtils.TruffleExecutable.wrap(this::majorVersion), - NFIUtils.TruffleExecutable.wrap(this::methodArgumentCount), - NFIUtils.TruffleExecutable.wrap(this::minorVersion), - NFIUtils.TruffleExecutable.wrap(this::primitiveFail), - NFIUtils.TruffleExecutable.wrap(this::stackValue), + public TruffleExecutable[] getExecutables() { + return new TruffleExecutable[] { + TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), + TruffleExecutable.wrap("():SINT64", this::classString), + TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("():SINT64", this::majorVersion), + TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("():SINT64", this::minorVersion), + TruffleExecutable.wrap("():SINT64", this::nilObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::pop), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), }; } public void postPrimitiveCleanups() { @@ -63,11 +78,20 @@ private NativeObject objectRegistryGet(long oop) { private int byteSizeOf(long oop) { return NativeObjectStorage.from(objectRegistryGet(oop)).byteSizeOf(); } + private int classString() { + return 1;// TODO + } + private int failed() { + return 1;// TODO + } private NativeObjectStorage firstIndexableField(long oop) { NativeObjectStorage storage = NativeObjectStorage.from(objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); return storage; } + private int instantiateClassindexableSize(long classPointer, long size) { + return 1;// TODO + } private int isBytes(long oop) { return objectRegistryGet(oop).isByteType() ? 1 : 0; } @@ -80,9 +104,30 @@ private int methodArgumentCount() { private int minorVersion() { return 17; } + private int nilObject() { + return 1;// TODO + } + private int pop(long nItems) { + return 1;// TODO + } + private int popthenPush(long nItems, long oop) { + return 1;// TODO + } private int primitiveFail() { throw PrimitiveFailed.GENERIC_ERROR; } + private int pushInteger(long integerValue) { + return 1;// TODO + } + private int signed32BitIntegerFor(long integerValue) { + return 1;// TODO + } + private int signed32BitValueOf(long oop) { + return 1;// TODO + } + private int stackIntegerValue(long stackIndex) { + return 1;// TODO + } private int stackValue(long stackIndex) { Object objectOnStack = FrameAccess.getStackValue(frame, (int) stackIndex, FrameAccess.getNumArguments(frame)); int objectIndex = objectRegistry.size(); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index c5e11832d..6ace8f37b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -11,21 +11,23 @@ public class NFIUtils { @ExportLibrary(InteropLibrary.class) public static class TruffleExecutable implements TruffleObject { + public String nfiSignature; ITruffleExecutable executable; - public TruffleExecutable(ITruffleExecutable executable) { + public TruffleExecutable(String nfiSignature, ITruffleExecutable executable) { + this.nfiSignature = nfiSignature; this.executable = executable; } - public static TruffleExecutable wrap(TruffleFunction function) { - return new TruffleExecutable(function); + public static TruffleExecutable wrap(String nfiSignature, TruffleFunction function) { + return new TruffleExecutable(nfiSignature, function); } - static TruffleExecutable wrap(TruffleBiFunction function) { - return new TruffleExecutable(function); + public static TruffleExecutable wrap(String nfiSignature, TruffleBiFunction function) { + return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(TruffleSupplier supplier) { - return new TruffleExecutable(supplier); + public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { + return new TruffleExecutable(nfiSignature, supplier); } @ExportMessage From d6a43483c5466f4fae063c82ad48e589ccf46e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 18 Nov 2023 19:18:38 +0100 Subject: [PATCH 044/159] Towards using SqueakSSL.so * Add numReceiverAndArguments to InterpreterProxy * Turn InterpreterProxy into a singleton with mutable members frame and numReceiverAndArguments * objectRegistry is now effectively static, so all primitive invocations share an oop namespace * Implement most InterpreterProxy stubs required for SqueakSSL.so --- .../nodes/plugins/ffi/InterpreterProxy.java | 144 +++++++++++++++--- .../primitives/PrimitiveNodeFactory.java | 24 +-- 2 files changed, 133 insertions(+), 35 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 0e21633b4..d596ffe29 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -8,7 +8,11 @@ import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject; +import de.hpi.swa.trufflesqueak.model.ClassObject; import de.hpi.swa.trufflesqueak.model.NativeObject; +import de.hpi.swa.trufflesqueak.model.NilObject; +import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; @@ -19,15 +23,20 @@ import java.util.stream.Collectors; public class InterpreterProxy { + private static InterpreterProxy INSTANCE = null; - private final VirtualFrame frame; + private final SqueakImageContext context; + private VirtualFrame frame; + private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); private static Object interpreterProxyPointer = null; - public InterpreterProxy(SqueakImageContext context, VirtualFrame frame) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + private InterpreterProxy(SqueakImageContext context, VirtualFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + this.context = context; this.frame = frame; + this.numReceiverAndArguments = numReceiverAndArguments; if (interpreterProxyPointer == null) { final TruffleExecutable[] truffleExecutables = getExecutables(); final String truffleExecutablesSignatures = Arrays.stream(truffleExecutables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); @@ -42,6 +51,20 @@ public InterpreterProxy(SqueakImageContext context, VirtualFrame frame) throws U interpreterProxy,"createInterpreterProxy", (Object[]) truffleExecutables); } } + + public static InterpreterProxy instanceFor(SqueakImageContext context, VirtualFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + if (INSTANCE == null) { + INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); + return INSTANCE; + } + if (INSTANCE.context != context) { + throw new RuntimeException("InterpreterProxy does not support multiple SqueakImageContexts"); + } + INSTANCE.frame = frame; + INSTANCE.numReceiverAndArguments = numReceiverAndArguments; + return INSTANCE; + } + public Object getPointer() { return interpreterProxyPointer; } @@ -70,69 +93,142 @@ public TruffleExecutable[] getExecutables() { } public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); + postPrimitiveCleanups.clear(); + } + private Object objectRegistryGet(long oop) { + System.out.println("Asked for oop " + oop); + return objectRegistry.get((int) oop); + } + + private int addObjectToRegistry(Object object) { + int oop = objectRegistry.size(); + objectRegistry.add(object); + return oop; + } + + private int oopFor(Object object) { + int oop = objectRegistry.indexOf(object); + if (oop < 0) { + oop = addObjectToRegistry(object); + } + System.out.println("Giving out oop " + oop + " for " + object); + return oop; + } + + private int getStackPointer() { + return FrameAccess.getStackPointer(frame); + } + + private void setStackPointer(int stackPointer) { + FrameAccess.setStackPointer(frame, stackPointer); + } + + private void pushObject(Object object) { + System.out.println("Pushing object " + object); + int stackPointer = getStackPointer() + 1; + setStackPointer(stackPointer); + FrameAccess.setSlot(frame, stackPointer, object); } - private NativeObject objectRegistryGet(long oop) { - return (NativeObject) objectRegistry.get((int) oop); + + private Object getObjectOnStack(long reverseStackIndex) { + if (reverseStackIndex < 0) { + primitiveFail(); + return null; + } + int stackIndex = getStackPointer() - (int) reverseStackIndex; + if (stackIndex < 0) { + primitiveFail(); + return null; + } + return FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); + } + + private long objectToLong(Object object) { + if (!(object instanceof Long)) { + System.out.println("Object to long called with non-Long: " + object); + primitiveFail(); + return 0; + } + return (Long)object; } private int byteSizeOf(long oop) { - return NativeObjectStorage.from(objectRegistryGet(oop)).byteSizeOf(); + return NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)).byteSizeOf(); } private int classString() { - return 1;// TODO + return oopFor(context.byteStringClass); } private int failed() { - return 1;// TODO + return 0; // TODO: when changing primitiveFail to continue executing, properly implement this } private NativeObjectStorage firstIndexableField(long oop) { - NativeObjectStorage storage = NativeObjectStorage.from(objectRegistryGet(oop)); + NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); return storage; } private int instantiateClassindexableSize(long classPointer, long size) { - return 1;// TODO + Object classObject = objectRegistryGet(classPointer); + if (!(classObject instanceof ClassObject)) { + System.out.println("instantiateClassindexableSize called with non-ClassObject: " + classObject); + primitiveFail(); + return -1; + } + SqueakObjectNewNode objectNewNode = SqueakObjectNewNode.create(); + AbstractSqueakObject newObject = objectNewNode.execute(context, (ClassObject) classObject, (int)size); + return oopFor(newObject); } private int isBytes(long oop) { - return objectRegistryGet(oop).isByteType() ? 1 : 0; + Object object = objectRegistryGet(oop); + if (!(object instanceof NativeObject)) { + return 0; + } + return ((NativeObject) object).isByteType() ? 1 : 0; } private int majorVersion() { return 1; } private int methodArgumentCount() { - return FrameAccess.getNumArguments(frame); + return numReceiverAndArguments - 1; } private int minorVersion() { return 17; } private int nilObject() { - return 1;// TODO + return oopFor(NilObject.SINGLETON); } private int pop(long nItems) { - return 1;// TODO + setStackPointer(getStackPointer() - (int)nItems); + return 1; } private int popthenPush(long nItems, long oop) { - return 1;// TODO + pop(nItems); + push(oop); + return 1; } private int primitiveFail() { + // TODO: continue executing C code + // TODO: adjust failed accordingly throw PrimitiveFailed.GENERIC_ERROR; } private int pushInteger(long integerValue) { - return 1;// TODO + pushObject(integerValue); + return 1; + } + private int push(long oop) { + pushObject(objectRegistryGet(oop)); + return 1; } private int signed32BitIntegerFor(long integerValue) { - return 1;// TODO + return oopFor(integerValue); } private int signed32BitValueOf(long oop) { - return 1;// TODO + return (int)objectToLong(objectRegistryGet(oop)); } - private int stackIntegerValue(long stackIndex) { - return 1;// TODO + private long stackIntegerValue(long reverseStackIndex) { + return objectToLong(getObjectOnStack(reverseStackIndex)); } - private int stackValue(long stackIndex) { - Object objectOnStack = FrameAccess.getStackValue(frame, (int) stackIndex, FrameAccess.getNumArguments(frame)); - int objectIndex = objectRegistry.size(); - objectRegistry.add(objectOnStack); - return objectIndex; + private int stackValue(long reverseStackIndex) { + return oopFor(getObjectOnStack(reverseStackIndex)); } public interface PostPrimitiveCleanup { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index df9553a79..92fdb2cf1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -37,8 +37,8 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.SecurityPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.SoundCodecPrims; import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakFFIPrims; -import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakSSL; import de.hpi.swa.trufflesqueak.nodes.plugins.TruffleSqueakPlugin; +import de.hpi.swa.trufflesqueak.nodes.plugins.UUIDPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.UnixOSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.Win32OSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ZipPlugin; @@ -114,8 +114,8 @@ public final class PrimitiveNodeFactory { new SocketPlugin(), new SoundCodecPrims(), new SqueakFFIPrims(), - new SqueakSSL(), - //new UUIDPlugin(), + //new SqueakSSL(), + new UUIDPlugin(), new ZipPlugin(), OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; fillPrimitiveTable(plugins); @@ -210,36 +210,38 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (functionName.equals("primitivePluginVersion")) { return null; } - return new NonExistentPrimitiveNode(moduleName, functionName); + return new NonExistentPrimitiveNode(moduleName, functionName, numReceiverAndArguments); } } static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { final String moduleName; final String functionName; + final int numReceiverAndArguments; - public NonExistentPrimitiveNode(String moduleName, String functionName) { + public NonExistentPrimitiveNode(String moduleName, String functionName, int numReceiverAndArguments) { this.moduleName = moduleName; this.functionName = functionName; + this.numReceiverAndArguments = numReceiverAndArguments; } @Override public Object execute(VirtualFrame frame) { - final Object uuidPlugin = NFIUtils.loadLibrary(getContext(), "UUIDPlugin.so", "{ " + - "initialiseModule():SINT64; " + + final Object uuidPlugin = NFIUtils.loadLibrary(getContext(), "SqueakSSL.so", "{ " + + //"initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + - "shutdownModule():SINT64; " + + //"shutdownModule():SINT64; " + functionName + "():SINT64; " + " }"); final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { - interpreterProxy = new InterpreterProxy(getContext(), frame); + interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); - uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); + //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); final Object result = uuidPluginLibrary.invokeMember(uuidPlugin, functionName); - uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); + //uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); return result; } catch (Exception e) { From 1c28473a2e0c68cc90f0add2e095417476242c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 20 Nov 2023 15:17:58 +0100 Subject: [PATCH 045/159] Fix stack pointer before running C code --- .../nodes/primitives/PrimitiveNodeFactory.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 92fdb2cf1..64c342133 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -7,6 +7,7 @@ package de.hpi.swa.trufflesqueak.nodes.primitives; import com.oracle.truffle.api.dsl.NodeFactory; +import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropLibrary; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; @@ -52,6 +53,7 @@ import de.hpi.swa.trufflesqueak.nodes.primitives.impl.IOPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.MiscellaneousPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.StoragePrimitives; +import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; import de.hpi.swa.trufflesqueak.util.OS; import org.graalvm.collections.EconomicMap; @@ -236,6 +238,10 @@ public Object execute(VirtualFrame frame) { final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { + // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by the number of arguments + // before transferring control. We need the stack pointer to point at the last argument, + // since the C code expects that. Therefore, we undo the decrement operation here. + FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments - 1); interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); From f08b4d37d770483f4858b72cd5f621478c763e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:35:14 +0100 Subject: [PATCH 046/159] Use MaterializedFrames [skip ci] --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 7 ++++--- .../nodes/primitives/PrimitiveNodeFactory.java | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index d596ffe29..c94be952a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -1,5 +1,6 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; +import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -26,14 +27,14 @@ public class InterpreterProxy { private static InterpreterProxy INSTANCE = null; private final SqueakImageContext context; - private VirtualFrame frame; + private MaterializedFrame frame; private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); private static Object interpreterProxyPointer = null; - private InterpreterProxy(SqueakImageContext context, VirtualFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { this.context = context; this.frame = frame; this.numReceiverAndArguments = numReceiverAndArguments; @@ -52,7 +53,7 @@ private InterpreterProxy(SqueakImageContext context, VirtualFrame frame, int num } } - public static InterpreterProxy instanceFor(SqueakImageContext context, VirtualFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static InterpreterProxy instanceFor(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { if (INSTANCE == null) { INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); return INSTANCE; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 64c342133..44b5ff94f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -242,7 +242,7 @@ public Object execute(VirtualFrame frame) { // before transferring control. We need the stack pointer to point at the last argument, // since the C code expects that. Therefore, we undo the decrement operation here. FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments - 1); - interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); + interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); From 834e86b0123559b6c74534c94a696c54ec23ff95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:36:38 +0100 Subject: [PATCH 047/159] Fix off-by-one in pre-call stackPointer adjustment [skip ci] --- .../trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 44b5ff94f..e538080b3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -238,10 +238,10 @@ public Object execute(VirtualFrame frame) { final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { - // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by the number of arguments + // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by numReceiverAndArguments // before transferring control. We need the stack pointer to point at the last argument, // since the C code expects that. Therefore, we undo the decrement operation here. - FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments - 1); + FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments); interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); From b01faa343c8e2367478a498c8b3a1f3f7e431d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:38:21 +0100 Subject: [PATCH 048/159] Fix stack access using stackPointer [skip ci] --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index c94be952a..6ed796625 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -128,7 +128,7 @@ private void pushObject(Object object) { System.out.println("Pushing object " + object); int stackPointer = getStackPointer() + 1; setStackPointer(stackPointer); - FrameAccess.setSlot(frame, stackPointer, object); + FrameAccess.setStackSlot(frame, stackPointer - 1, object); } private Object getObjectOnStack(long reverseStackIndex) { @@ -136,7 +136,9 @@ private Object getObjectOnStack(long reverseStackIndex) { primitiveFail(); return null; } - int stackIndex = getStackPointer() - (int) reverseStackIndex; + // the stack pointer is the index of the object that is pushed onto the stack next, + // so we subtract 1 to get the index of the object that was last pushed onto the stack + int stackIndex = getStackPointer() - 1 - (int) reverseStackIndex; if (stackIndex < 0) { primitiveFail(); return null; From ed23920cf606ca7b35d2ef920f7fe7fe484e248b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:40:56 +0100 Subject: [PATCH 049/159] Only load libraries once --- .../nodes/primitives/PrimitiveNodeFactory.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index e538080b3..c16afd936 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -58,8 +58,10 @@ import de.hpi.swa.trufflesqueak.util.OS; import org.graalvm.collections.EconomicMap; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; public final class PrimitiveNodeFactory { @@ -220,6 +222,7 @@ static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { final String moduleName; final String functionName; final int numReceiverAndArguments; + static Map loadedLibraries = new HashMap<>(); public NonExistentPrimitiveNode(String moduleName, String functionName, int numReceiverAndArguments) { this.moduleName = moduleName; @@ -229,12 +232,13 @@ public NonExistentPrimitiveNode(String moduleName, String functionName, int numR @Override public Object execute(VirtualFrame frame) { - final Object uuidPlugin = NFIUtils.loadLibrary(getContext(), "SqueakSSL.so", "{ " + - //"initialiseModule():SINT64; " + - "setInterpreter(POINTER):SINT64; " + - //"shutdownModule():SINT64; " + - functionName + "():SINT64; " + - " }"); + final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> + NFIUtils.loadLibrary(getContext(), "SqueakSSL.so", "{ " + + //"initialiseModule():SINT64; " + + "setInterpreter(POINTER):SINT64; " + + //"shutdownModule():SINT64; " + + functionName + "():SINT64; " + + " }")); final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { From cb2d874e0841c55ec87b1dfb2f920b82fd6bd2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:41:44 +0100 Subject: [PATCH 050/159] Add NFIUtils.loadMember [skip ci] --- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 6ace8f37b..777a91de7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,7 +1,11 @@ package de.hpi.swa.trufflesqueak.util; +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.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +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; @@ -75,12 +79,24 @@ default Object execute(Object... arguments) { } } - public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { - final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; + public static Object executeNFI(SqueakImageContext context, String nfiCode) { final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); return context.env.parseInternal(source).call(); } + public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { + final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; + return executeNFI(context, nfiCode); + } + + public static Object loadMember(SqueakImageContext context, Object library, String name, String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + InteropLibrary interopLibrary = getInteropLibrary(library); + Object symbol = interopLibrary.readMember(library, name); + Object nfiSignature = executeNFI(context, signature); + InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); + return signatureInteropLibrary.invokeMember(nfiSignature, "bind", symbol); + } + public static InteropLibrary getInteropLibrary(Object loadedLibrary) { return InteropLibrary.getFactory().getUncached(loadedLibrary); } From 7bbb148ea4bfc56f18f65050cb02b15d7ce53f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:43:52 +0100 Subject: [PATCH 051/159] Add loading of function symbols [skip ci] --- .../trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index c16afd936..4332b9d77 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -237,11 +237,12 @@ public Object execute(VirtualFrame frame) { //"initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + //"shutdownModule():SINT64; " + - functionName + "():SINT64; " + " }")); final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { + Object functionSymbol = NFIUtils.loadMember(getContext(), uuidPlugin, functionName, "():SINT64"); + InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by numReceiverAndArguments // before transferring control. We need the stack pointer to point at the last argument, // since the C code expects that. Therefore, we undo the decrement operation here. @@ -250,7 +251,7 @@ public Object execute(VirtualFrame frame) { //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); - final Object result = uuidPluginLibrary.invokeMember(uuidPlugin, functionName); + final Object result = functionInteropLibrary.execute(functionSymbol); //uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); return result; From 47b0127949d62300d3333a068743c3a7eb7d93ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 15:44:33 +0100 Subject: [PATCH 052/159] Fix handling of return values [skip ci] --- .../nodes/primitives/PrimitiveNodeFactory.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 4332b9d77..3d8f1aaa8 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -253,8 +253,12 @@ public Object execute(VirtualFrame frame) { uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); final Object result = functionInteropLibrary.execute(functionSymbol); //uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); - - return result; + // The return value is pushed onto the stack by the Plugin via the InterpreterProxy, but TruffleSqueak + // expects the return value to be returned by this function (AbstractSendNode.executeVoid). + // Pop the return value and return it. + final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); + FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); + return returnValue; } catch (Exception e) { System.out.println("error"); e.printStackTrace(System.err); From b64dd0beafac3936d55b0b08184be6499913b25d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sat, 25 Nov 2023 16:35:12 +0100 Subject: [PATCH 053/159] Keep TruffleExecutables in memory [skip ci] --- .../nodes/plugins/ffi/InterpreterProxy.java | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 6ed796625..e81822838 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -31,6 +31,26 @@ public class InterpreterProxy { private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); + private final TruffleExecutable[] executables = new TruffleExecutable[] { + TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), + TruffleExecutable.wrap("():SINT64", this::classString), + TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("():SINT64", this::majorVersion), + TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("():SINT64", this::minorVersion), + TruffleExecutable.wrap("():SINT64", this::nilObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::pop), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), + }; private static Object interpreterProxyPointer = null; @@ -39,8 +59,7 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in this.frame = frame; this.numReceiverAndArguments = numReceiverAndArguments; if (interpreterProxyPointer == null) { - final TruffleExecutable[] truffleExecutables = getExecutables(); - final String truffleExecutablesSignatures = Arrays.stream(truffleExecutables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); + final String truffleExecutablesSignatures = Arrays.stream(executables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); final Object interpreterProxy = NFIUtils.loadLibrary( context, "InterpreterProxy.so", @@ -49,7 +68,7 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy,"createInterpreterProxy", (Object[]) truffleExecutables); + interpreterProxy,"createInterpreterProxy", (Object[]) executables); } } @@ -70,28 +89,6 @@ public Object getPointer() { return interpreterProxyPointer; } - public TruffleExecutable[] getExecutables() { - return new TruffleExecutable[] { - TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), - TruffleExecutable.wrap("():SINT64", this::classString), - TruffleExecutable.wrap("():SINT64", this::failed), - TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), - TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), - TruffleExecutable.wrap("():SINT64", this::majorVersion), - TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), - TruffleExecutable.wrap("():SINT64", this::minorVersion), - TruffleExecutable.wrap("():SINT64", this::nilObject), - TruffleExecutable.wrap("(SINT64):SINT64", this::pop), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), - TruffleExecutable.wrap("():SINT64", this::primitiveFail), - TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), - TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), - TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), - }; - } public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); postPrimitiveCleanups.clear(); From e5527bf508e784f69645e7ca40ed957b3ab421ca Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 29 Nov 2023 21:38:39 +0100 Subject: [PATCH 054/159] Make `ffi.native` use CMakeNinjaProject --- mx.trufflesqueak/mx_trufflesqueak.py | 5 +++- mx.trufflesqueak/suite.py | 25 +++++++------------ .../CMakeLists.txt | 22 ++++++++++++++++ 3 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt diff --git a/mx.trufflesqueak/mx_trufflesqueak.py b/mx.trufflesqueak/mx_trufflesqueak.py index a90a55dc7..729f73506 100644 --- a/mx.trufflesqueak/mx_trufflesqueak.py +++ b/mx.trufflesqueak/mx_trufflesqueak.py @@ -10,11 +10,14 @@ import mx import mx_gate +import mx_unittest + import mx_sdk import mx_sdk_vm import mx_sdk_vm_impl import mx_truffle -import mx_unittest + +# re-export custom mx project classes so they can be used from suite.py _SUITE = mx.suite('trufflesqueak') _COMPILER = mx.suite('compiler', fatalIfMissing=False) diff --git a/mx.trufflesqueak/suite.py b/mx.trufflesqueak/suite.py index 0cd8fe6ee..32ec06804 100644 --- a/mx.trufflesqueak/suite.py +++ b/mx.trufflesqueak/suite.py @@ -167,24 +167,17 @@ }, "de.hpi.swa.trufflesqueak.ffi.native": { "subDir": "src", - "native": "shared_lib", - "deliverable": "SqueakFFIPrims", + "class": "CMakeNinjaProject", + "vpath": True, + "ninja_targets": ["all"], "os_arch": { - "windows": { - "": { - "cflags": [] - } - }, - "linux": { - "": { - "cflags": ["-g", "-Wall", "-Werror", "-D_GNU_SOURCE"], - "ldlibs": ["-ldl"], - }, - }, "": { "": { - "cflags": ["-g", "-Wall", "-Werror"], - "ldlibs": ["-ldl"], + "cmakeConfig": {}, + "results": [ + "", + "", + ], }, }, }, @@ -277,7 +270,7 @@ "layout": { "LICENSE_TRUFFLESQUEAK.txt": "file:LICENSE", "README_TRUFFLESQUEAK.md": "file:README.md", - "lib/": "dependency:de.hpi.swa.trufflesqueak.ffi.native", + "lib/": "dependency:de.hpi.swa.trufflesqueak.ffi.native/*", }, "maven": False, }, diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt b/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt new file mode 100644 index 000000000..3aafb8798 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.22) +project(de.hpi.swa.trufflesqueak.ffi.native) + +if(NOT DEFINED SRC_DIR) + set(SRC_DIR "${CMAKE_SOURCE_DIR}") +endif() + +set(CMAKE_C_STANDARD 11) + +# don't install into the system but into the MX project's output dir +set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) + +set(CAPI_SRC "${SRC_DIR}/src") + +function(build_library LIB_NAME SOURCE_FILE) + add_library(${LIB_NAME} SHARED ${SOURCE_FILE}) + target_include_directories(${LIB_NAME} PUBLIC include) +endfunction() + + +build_library(InterpreterProxy "${CAPI_SRC}/InterpreterProxy.c") +build_library(SqueakFFIPrims "${CAPI_SRC}/SqueakFFIPrims.c") \ No newline at end of file From 4578bd0d499e32294cd6d9592ffa8a5cbc7553aa Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 29 Nov 2023 21:40:58 +0100 Subject: [PATCH 055/159] Format --- .../nodes/plugins/ffi/InterpreterProxy.java | 88 +++++++++++-------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index e81822838..5764ab942 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -1,7 +1,6 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; import com.oracle.truffle.api.frame.MaterializedFrame; -import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnknownIdentifierException; @@ -31,25 +30,25 @@ public class InterpreterProxy { private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); - private final TruffleExecutable[] executables = new TruffleExecutable[] { - TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), - TruffleExecutable.wrap("():SINT64", this::classString), - TruffleExecutable.wrap("():SINT64", this::failed), - TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), - TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), - TruffleExecutable.wrap("():SINT64", this::majorVersion), - TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), - TruffleExecutable.wrap("():SINT64", this::minorVersion), - TruffleExecutable.wrap("():SINT64", this::nilObject), - TruffleExecutable.wrap("(SINT64):SINT64", this::pop), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), - TruffleExecutable.wrap("():SINT64", this::primitiveFail), - TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), - TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), - TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), + private final TruffleExecutable[] executables = new TruffleExecutable[]{ + TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), + TruffleExecutable.wrap("():SINT64", this::classString), + TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("():SINT64", this::majorVersion), + TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("():SINT64", this::minorVersion), + TruffleExecutable.wrap("():SINT64", this::nilObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::pop), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), }; private static Object interpreterProxyPointer = null; @@ -68,21 +67,21 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy,"createInterpreterProxy", (Object[]) executables); + interpreterProxy, "createInterpreterProxy", (Object[]) executables); } } public static InterpreterProxy instanceFor(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { - if (INSTANCE == null) { - INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); - return INSTANCE; - } - if (INSTANCE.context != context) { - throw new RuntimeException("InterpreterProxy does not support multiple SqueakImageContexts"); - } - INSTANCE.frame = frame; - INSTANCE.numReceiverAndArguments = numReceiverAndArguments; - return INSTANCE; + if (INSTANCE == null) { + INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); + return INSTANCE; + } + if (INSTANCE.context != context) { + throw new RuntimeException("InterpreterProxy does not support multiple SqueakImageContexts"); + } + INSTANCE.frame = frame; + INSTANCE.numReceiverAndArguments = numReceiverAndArguments; + return INSTANCE; } public Object getPointer() { @@ -93,6 +92,7 @@ public void postPrimitiveCleanups() { postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); postPrimitiveCleanups.clear(); } + private Object objectRegistryGet(long oop) { System.out.println("Asked for oop " + oop); return objectRegistry.get((int) oop); @@ -149,23 +149,27 @@ private long objectToLong(Object object) { primitiveFail(); return 0; } - return (Long)object; + return (Long) object; } private int byteSizeOf(long oop) { return NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)).byteSizeOf(); } + private int classString() { return oopFor(context.byteStringClass); } + private int failed() { return 0; // TODO: when changing primitiveFail to continue executing, properly implement this } + private NativeObjectStorage firstIndexableField(long oop) { NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); return storage; } + private int instantiateClassindexableSize(long classPointer, long size) { Object classObject = objectRegistryGet(classPointer); if (!(classObject instanceof ClassObject)) { @@ -174,9 +178,10 @@ private int instantiateClassindexableSize(long classPointer, long size) { return -1; } SqueakObjectNewNode objectNewNode = SqueakObjectNewNode.create(); - AbstractSqueakObject newObject = objectNewNode.execute(context, (ClassObject) classObject, (int)size); + AbstractSqueakObject newObject = objectNewNode.execute(context, (ClassObject) classObject, (int) size); return oopFor(newObject); } + private int isBytes(long oop) { Object object = objectRegistryGet(oop); if (!(object instanceof NativeObject)) { @@ -184,49 +189,62 @@ private int isBytes(long oop) { } return ((NativeObject) object).isByteType() ? 1 : 0; } + private int majorVersion() { return 1; } + private int methodArgumentCount() { return numReceiverAndArguments - 1; } + private int minorVersion() { return 17; } + private int nilObject() { return oopFor(NilObject.SINGLETON); } + private int pop(long nItems) { - setStackPointer(getStackPointer() - (int)nItems); + setStackPointer(getStackPointer() - (int) nItems); return 1; } + private int popthenPush(long nItems, long oop) { pop(nItems); push(oop); return 1; } + private int primitiveFail() { // TODO: continue executing C code // TODO: adjust failed accordingly throw PrimitiveFailed.GENERIC_ERROR; } + private int pushInteger(long integerValue) { pushObject(integerValue); return 1; } + private int push(long oop) { pushObject(objectRegistryGet(oop)); return 1; } + private int signed32BitIntegerFor(long integerValue) { return oopFor(integerValue); } + private int signed32BitValueOf(long oop) { - return (int)objectToLong(objectRegistryGet(oop)); + return (int) objectToLong(objectRegistryGet(oop)); } + private long stackIntegerValue(long reverseStackIndex) { return objectToLong(getObjectOnStack(reverseStackIndex)); } + private int stackValue(long reverseStackIndex) { return oopFor(getObjectOnStack(reverseStackIndex)); } From d1d1af400f085e8750fea0c19320fe56fe7e4271 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 29 Nov 2023 21:42:54 +0100 Subject: [PATCH 056/159] Load nfi libraries from image path --- .../nodes/plugins/ffi/InterpreterProxy.java | 4 +--- .../nodes/primitives/PrimitiveNodeFactory.java | 3 +-- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 11 ++++++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 5764ab942..e9f4d87df 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -59,9 +59,7 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in this.numReceiverAndArguments = numReceiverAndArguments; if (interpreterProxyPointer == null) { final String truffleExecutablesSignatures = Arrays.stream(executables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); - final Object interpreterProxy = NFIUtils.loadLibrary( - context, - "InterpreterProxy.so", + final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" ); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 3d8f1aaa8..861519238 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -7,7 +7,6 @@ package de.hpi.swa.trufflesqueak.nodes.primitives; import com.oracle.truffle.api.dsl.NodeFactory; -import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropLibrary; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; @@ -233,7 +232,7 @@ public NonExistentPrimitiveNode(String moduleName, String functionName, int numR @Override public Object execute(VirtualFrame frame) { final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> - NFIUtils.loadLibrary(getContext(), "SqueakSSL.so", "{ " + + NFIUtils.loadLibrary(getContext(), moduleName, "{ " + //"initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + //"shutdownModule():SINT64; " + diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 777a91de7..d57b61f08 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,5 +1,6 @@ package de.hpi.swa.trufflesqueak.util; +import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; @@ -9,8 +10,11 @@ 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; +import java.io.File; + public class NFIUtils { @ExportLibrary(InteropLibrary.class) @@ -85,7 +89,12 @@ public static Object executeNFI(SqueakImageContext context, String nfiCode) { } public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { - final String nfiCode = "load \"" + moduleName + "\" " + boundSymbols; + final String libName = System.mapLibraryName(moduleName); + final TruffleFile libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName); + if (!libPath.exists()) { + throw PrimitiveFailed.GENERIC_ERROR; + } + final String nfiCode = "load \"" + libPath.getAbsoluteFile().getPath() + "\" " + boundSymbols; return executeNFI(context, nfiCode); } From 7511542b78c38732e6d35e7a99547c1783a0451d Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 29 Nov 2023 21:59:14 +0100 Subject: [PATCH 057/159] Import is not actually unused [skip ci] --- mx.trufflesqueak/mx_trufflesqueak.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mx.trufflesqueak/mx_trufflesqueak.py b/mx.trufflesqueak/mx_trufflesqueak.py index 729f73506..ef1c6d77b 100644 --- a/mx.trufflesqueak/mx_trufflesqueak.py +++ b/mx.trufflesqueak/mx_trufflesqueak.py @@ -18,6 +18,7 @@ import mx_truffle # re-export custom mx project classes so they can be used from suite.py +from mx_cmake import CMakeNinjaProject #pylint: disable=unused-import _SUITE = mx.suite('trufflesqueak') _COMPILER = mx.suite('compiler', fatalIfMissing=False) From 5c654e0a48e87b390d7266e8276e21b7766579cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 4 Dec 2023 13:03:56 +0100 Subject: [PATCH 058/159] Prevent NFI closures from being freed [skip ci] --- .../nodes/plugins/ffi/InterpreterProxy.java | 10 ++++-- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 34 +++++++++++++++++-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index e9f4d87df..b8f2eb36b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -16,6 +16,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; +import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleClosure; import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; import java.util.ArrayList; @@ -50,6 +51,7 @@ public class InterpreterProxy { TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), }; + private final TruffleClosure[] closures; private static Object interpreterProxyPointer = null; @@ -57,15 +59,19 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in this.context = context; this.frame = frame; this.numReceiverAndArguments = numReceiverAndArguments; + closures = new TruffleClosure[executables.length]; + for (int i = 0; i < executables.length; i++) { + closures[i] = executables[i].createClosure(context); + } if (interpreterProxyPointer == null) { - final String truffleExecutablesSignatures = Arrays.stream(executables).map(obj -> obj.nfiSignature).collect(Collectors.joining(",")); + final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" ); final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy, "createInterpreterProxy", (Object[]) executables); + interpreterProxy, "createInterpreterProxy", (Object[]) closures); } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index d57b61f08..a8f6da886 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -47,6 +47,22 @@ boolean isExecutable() { Object execute(Object... arguments) { return executable.execute(arguments); } + + public TruffleClosure createClosure(SqueakImageContext context) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + return new TruffleClosure(context, this); + } + } + + @ExportLibrary(value = InteropLibrary.class, delegateTo = "closure") + public static class TruffleClosure implements TruffleObject { + public final TruffleExecutable executable; + + final Object closure; + + public TruffleClosure(SqueakImageContext context, TruffleExecutable executable) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + this.executable = executable; + this.closure = createClosure(context, executable, executable.nfiSignature); + } } public interface ITruffleExecutable { @@ -98,12 +114,24 @@ public static Object loadLibrary(SqueakImageContext context, String moduleName, return executeNFI(context, nfiCode); } + public static Object createSignature(SqueakImageContext context, String signature) { + return executeNFI(context, signature); + } + + public static Object invokeSignatureMethod(SqueakImageContext context, String signature, String method, Object... args) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + Object nfiSignature = createSignature(context, signature); + InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); + return signatureInteropLibrary.invokeMember(nfiSignature, method, args); + } + + public static Object createClosure(SqueakImageContext context, Object executable, String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + return invokeSignatureMethod(context, signature, "createClosure", executable); + } + public static Object loadMember(SqueakImageContext context, Object library, String name, String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { InteropLibrary interopLibrary = getInteropLibrary(library); Object symbol = interopLibrary.readMember(library, name); - Object nfiSignature = executeNFI(context, signature); - InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); - return signatureInteropLibrary.invokeMember(nfiSignature, "bind", symbol); + return invokeSignatureMethod(context, signature, "bind", symbol); } public static InteropLibrary getInteropLibrary(Object loadedLibrary) { From 2fec6a428a0f9a0b26e7b0b6650b5f54653f5af8 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 14 Dec 2023 17:51:47 +0100 Subject: [PATCH 059/159] Add missing stubs from BitBlt support [skip ci] --- .../src/InterpreterProxy.c | 54 ++++++++++- .../nodes/plugins/ffi/InterpreterProxy.java | 95 ++++++++++++++++--- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 39 ++++++++ 3 files changed, 174 insertions(+), 14 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index 7b219d965..3df8772f7 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -5,40 +5,92 @@ VirtualMachine* createInterpreterProxy( sqInt (*byteSizeOf)(sqInt oop), sqInt (*classString)(void), sqInt (*failed)(void), + sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer), + sqInt (*fetchLong32ofObject)(sqInt fieldIndex, sqInt oop), + sqInt (*fetchPointerofObject)(sqInt index, sqInt oop), void *(*firstIndexableField)(sqInt oop), + double (*floatValueOf)(sqInt oop), sqInt (*instantiateClassindexableSize)(sqInt classPointer, sqInt size), + sqInt (*integerObjectOf)(sqInt value), + sqInt (*integerValueOf)(sqInt oop), + void *(*ioLoadFunctionFrom)(char *functionName, char *moduleName), + sqInt (*isArray)(sqInt oop), sqInt (*isBytes)(sqInt oop), + sqInt (*isPointers)(sqInt oop), + sqInt (*isPositiveMachineIntegerObject)(sqInt oop), + sqInt (*isWords)(sqInt oop), + sqInt (*isWordsOrBytes)(sqInt oop), sqInt (*majorVersion)(void), sqInt (*methodArgumentCount)(void), + sqInt (*methodReturnInteger)(sqInt integer), + sqInt (*methodReturnReceiver)(void), + sqInt (*methodReturnValue)(sqInt oop), sqInt (*minorVersion)(void), sqInt (*nilObject)(void), sqInt (*pop)(sqInt nItems), sqInt (*popthenPush)(sqInt nItems, sqInt oop), + sqInt (*positive32BitIntegerFor)(unsigned int integerValue), + usqInt (*positive32BitValueOf)(sqInt oop), + usqLong (*positive64BitValueOf)(sqInt oop), sqInt (*primitiveFail)(void), + sqInt (*primitiveFailFor)(sqInt reasonCode), + sqInt (*showDisplayBitsLeftTopRightBottom)(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b), sqInt (*pushInteger)(sqInt integerValue), sqInt (*signed32BitIntegerFor)(sqInt integerValue), int (*signed32BitValueOf)(sqInt oop), + sqInt (*slotSizeOf)(sqInt oop), sqInt (*stackIntegerValue)(sqInt offset), - sqInt (*stackValue)(sqInt offset) + sqInt (*stackObjectValue)(sqInt offset), + sqInt (*stackValue)(sqInt offset), + sqInt (*statNumGCs)(void), + sqInt (*storeIntegerofObjectwithValue)(sqInt index, sqInt oop, sqInt integer), + usqInt (*storeLong32ofObjectwithValue)(sqInt fieldIndex, sqInt oop, usqInt anInteger) ) { VirtualMachine* interpreterProxy = (VirtualMachine*)calloc(1, sizeof(VirtualMachine)); + interpreterProxy->byteSizeOf = byteSizeOf; interpreterProxy->classString = classString; interpreterProxy->failed = failed; + interpreterProxy->fetchIntegerofObject = fetchIntegerofObject; + interpreterProxy->fetchLong32ofObject = fetchLong32ofObject; + interpreterProxy->fetchPointerofObject = fetchPointerofObject; interpreterProxy->firstIndexableField = firstIndexableField; + interpreterProxy->floatValueOf = floatValueOf; interpreterProxy->instantiateClassindexableSize = instantiateClassindexableSize; + interpreterProxy->integerObjectOf = integerObjectOf; + interpreterProxy->integerValueOf = integerValueOf; + interpreterProxy->ioLoadFunctionFrom = ioLoadFunctionFrom; + interpreterProxy->isArray = isArray; interpreterProxy->isBytes = isBytes; + interpreterProxy->isPointers = isPointers; + interpreterProxy->isPositiveMachineIntegerObject = isPositiveMachineIntegerObject; + interpreterProxy->isWords = isWords; + interpreterProxy->isWordsOrBytes = isWordsOrBytes; interpreterProxy->majorVersion = majorVersion; interpreterProxy->methodArgumentCount = methodArgumentCount; + interpreterProxy->methodReturnInteger = methodReturnInteger; + interpreterProxy->methodReturnReceiver = methodReturnReceiver; + interpreterProxy->methodReturnValue = methodReturnValue; interpreterProxy->minorVersion = minorVersion; interpreterProxy->nilObject = nilObject; interpreterProxy->pop = pop; interpreterProxy->popthenPush = popthenPush; + interpreterProxy->positive32BitIntegerFor = positive32BitIntegerFor; + interpreterProxy->positive32BitValueOf = positive32BitValueOf; + interpreterProxy->positive64BitValueOf = positive64BitValueOf; interpreterProxy->primitiveFail = primitiveFail; + interpreterProxy->primitiveFailFor = primitiveFailFor; interpreterProxy->pushInteger = pushInteger; + interpreterProxy->showDisplayBitsLeftTopRightBottom = showDisplayBitsLeftTopRightBottom; interpreterProxy->signed32BitIntegerFor = signed32BitIntegerFor; interpreterProxy->signed32BitValueOf = signed32BitValueOf; + interpreterProxy->slotSizeOf = slotSizeOf; interpreterProxy->stackIntegerValue = stackIntegerValue; + interpreterProxy->stackObjectValue = stackObjectValue; interpreterProxy->stackValue = stackValue; + interpreterProxy->statNumGCs = statNumGCs; + interpreterProxy->storeIntegerofObjectwithValue = storeIntegerofObjectwithValue; + interpreterProxy->storeLong32ofObjectwithValue = storeLong32ofObjectwithValue; + return interpreterProxy; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index b8f2eb36b..bfe21ab77 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -35,22 +35,49 @@ public class InterpreterProxy { TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), TruffleExecutable.wrap("():SINT64", this::classString), TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchIntegerofObject), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchLong32ofObject), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchPointerofObject), TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64):DOUBLE", this::floatValueOf), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::integerObjectOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::integerValueOf), + TruffleExecutable.wrap("(STRING,STRING):POINTER", this::ioLoadFunctionFrom), + TruffleExecutable.wrap("(SINT64):SINT64", this::isArray), TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("(SINT64):SINT64", this::isPointers), + TruffleExecutable.wrap("(SINT64):SINT64", this::isPositiveMachineIntegerObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::isWords), + TruffleExecutable.wrap("(SINT64):SINT64", this::isWordsOrBytes), TruffleExecutable.wrap("():SINT64", this::majorVersion), TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnInteger), + TruffleExecutable.wrap("():SINT64", this::methodReturnReceiver), + TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnValue), TruffleExecutable.wrap("():SINT64", this::minorVersion), TruffleExecutable.wrap("():SINT64", this::nilObject), TruffleExecutable.wrap("(SINT64):SINT64", this::pop), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("(UINT64):SINT64", this::positive32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):UINT64", this::positive32BitValueOf), + TruffleExecutable.wrap("(SINT64):UINT64", this::positive64BitValueOf), TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::primitiveFailFor), + TruffleExecutable.wrap("(SINT64,SINT64,SINT64,SINT64,SINT64):SINT64", this::showDisplayBitsLeftTopRightBottom), TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), - TruffleExecutable.wrap("(SINT64):SINT32", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::slotSizeOf), TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackObjectValue), TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), + TruffleExecutable.wrap("():SINT64", this::statNumGCs), + TruffleExecutable.wrap("(SINT64,SINT64,SINT64):SINT64", this::storeIntegerofObjectwithValue), + TruffleExecutable.wrap("(SINT64,SINT64,UINT64):UINT64", this::storeLong32ofObjectwithValue), }; + + @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; private static Object interpreterProxyPointer = null; @@ -237,21 +264,63 @@ private int push(long oop) { return 1; } - private int signed32BitIntegerFor(long integerValue) { - return oopFor(integerValue); - } + private long fetchIntegerofObject(long fieldIndex, long objectPointer) {/* TODO */ System.out.println("Missing implementation for fetchIntegerofObject"); return 0;} - private int signed32BitValueOf(long oop) { - return (int) objectToLong(objectRegistryGet(oop)); - } + private long fetchLong32ofObject(long fieldIndex, long oop) {/* TODO */ System.out.println("Missing implementation for fetchLong32ofObject"); return 0;} - private long stackIntegerValue(long reverseStackIndex) { - return objectToLong(getObjectOnStack(reverseStackIndex)); - } + private long fetchPointerofObject(long index, long oop) {/* TODO */ System.out.println("Missing implementation for fetchPointerofObject"); return 0;} - private int stackValue(long reverseStackIndex) { - return oopFor(getObjectOnStack(reverseStackIndex)); - } + private double floatValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for floatValueOf"); return 0;} + + private long integerObjectOf(long value) {/* TODO */ System.out.println("Missing implementation for integerObjectOf"); return 0;} + + private long integerValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for integerValueOf"); return 0;} + + private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) {/* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); return null;} + + private long isArray(long oop) {/* TODO */ System.out.println("Missing implementation for isArray"); return 0;} + + private long isPointers(long oop) {/* TODO */ System.out.println("Missing implementation for isPointers"); return 0;} + + private long isPositiveMachineIntegerObject(long oop) {/* TODO */ System.out.println("Missing implementation for isPositiveMachineIntegerObject"); return 0;} + + private long isWords(long oop) {/* TODO */ System.out.println("Missing implementation for isWords"); return 0;} + + private long isWordsOrBytes(long oop) {/* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); return 0;} + + private long methodReturnInteger(long integer) {/* TODO */ System.out.println("Missing implementation for methodReturnInteger"); return 0;} + + private long methodReturnReceiver() {/* TODO */ System.out.println("Missing implementation for methodReturnReceiver"); return 0;} + + private long methodReturnValue(long oop) {/* TODO */ System.out.println("Missing implementation for methodReturnValue"); return 0;} + + private long positive32BitIntegerFor(long integerValue) {/* TODO */ System.out.println("Missing implementation for positive32BitIntegerFor"); return 0;} + + private long positive32BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for positive32BitValueOf"); return 0;} + + private long positive64BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for positive64BitValueOf"); return 0;} + + private long primitiveFailFor(long reasonCode) {/* TODO */ System.out.println("Missing implementation for primitiveFailFor"); return 0;} + + private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) {/* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); return 0;} + + private long signed32BitIntegerFor(long integerValue) {/* TODO */ System.out.println("Missing implementation for signed32BitIntegerFor"); return 0;} + + private long signed32BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for signed32BitValueOf"); return 0;} + + private long slotSizeOf(long oop) {/* TODO */ System.out.println("Missing implementation for slotSizeOf"); return 0;} + + private long stackIntegerValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackIntegerValue"); return 0;} + + private long stackObjectValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackObjectValue"); return 0;} + + private long stackValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackValue"); return 0;} + + private long statNumGCs() {/* TODO */ System.out.println("Missing implementation for statNumGCs"); return 0;} + + private long storeIntegerofObjectwithValue(long index, long oop, long integer) {/* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); return 0;} + + private long storeLong32ofObjectwithValue(long fieldIndex, long oop, long anInteger) {/* TODO */ System.out.println("Missing implementation for storeLong32ofObjectwithValue"); return 0;} public interface PostPrimitiveCleanup { void cleanup(); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index a8f6da886..f7fce949d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -33,6 +33,15 @@ public static TruffleExecutable wrap(String nfiSignature, TruffleFunction< public static TruffleExecutable wrap(String nfiSignature, TruffleBiFunction function) { return new TruffleExecutable(nfiSignature, function); } + public static TruffleExecutable wrap(String nfiSignature, TruffleTriFunction function) { + return new TruffleExecutable(nfiSignature, function); + } + public static TruffleExecutable wrap(String nfiSignature, TruffleQuadFunction function) { + return new TruffleExecutable(nfiSignature, function); + } + public static TruffleExecutable wrap(String nfiSignature, TruffleQuintFunction function) { + return new TruffleExecutable(nfiSignature, function); + } public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { return new TruffleExecutable(nfiSignature, supplier); @@ -89,6 +98,36 @@ default Object execute(Object... arguments) { } } + @FunctionalInterface + public interface TruffleTriFunction extends ITruffleExecutable { + R run(S argument1, T argument2, U argument3); + + default Object execute(Object... arguments) { + assert arguments.length == 3; + return run((S) arguments[0], (T) arguments[1], (U) arguments[2]); + } + } + + @FunctionalInterface + public interface TruffleQuadFunction extends ITruffleExecutable { + R run(S argument1, T argument2, U argument3, V argument4); + + default Object execute(Object... arguments) { + assert arguments.length == 4; + return run((S) arguments[0], (T) arguments[1], (U) arguments[2], (V) arguments[3]); + } + } + + @FunctionalInterface + public interface TruffleQuintFunction extends ITruffleExecutable { + R run(S argument1, T argument2, U argument3, V argument4, W argument5); + + default Object execute(Object... arguments) { + assert arguments.length == 5; + return run((S) arguments[0], (T) arguments[1], (U) arguments[2], (V) arguments[3], (W) arguments[4]); + } + } + @FunctionalInterface public interface TruffleSupplier extends ITruffleExecutable { R run(); From 366d95ebd4d3bf6d4bd88dc873bf303b68d57c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 18 Dec 2023 14:55:25 +0100 Subject: [PATCH 060/159] Implement some stubs and refactor --- .../nodes/plugins/ffi/InterpreterProxy.java | 107 ++++++++++++++---- 1 file changed, 83 insertions(+), 24 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index bfe21ab77..0a5296d7f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -8,10 +8,16 @@ import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject; +import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.ClassObject; +import de.hpi.swa.trufflesqueak.model.FloatObject; +import de.hpi.swa.trufflesqueak.model.LargeIntegerObject; import de.hpi.swa.trufflesqueak.model.NativeObject; import de.hpi.swa.trufflesqueak.model.NilObject; +import de.hpi.swa.trufflesqueak.model.PointersObject; +import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; @@ -21,6 +27,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.function.Function; import java.util.stream.Collectors; public class InterpreterProxy { @@ -175,12 +182,29 @@ private Object getObjectOnStack(long reverseStackIndex) { } private long objectToLong(Object object) { - if (!(object instanceof Long)) { - System.out.println("Object to long called with non-Long: " + object); - primitiveFail(); - return 0; + if (object instanceof Long longObject) { + return longObject; + } + System.out.println("Object to long called with non-Long: " + object); + primitiveFail(); + return 0; + } + + private double objectToDouble(Object object) { + if (object instanceof FloatObject floatObject) { + return floatObject.getValue(); + } + System.out.println("Object to double called with non-FloatObject: " + object); + primitiveFail(); + return 0; + } + + private int nativeObjectCheck(long oop, Function check) { + Object object = objectRegistryGet(oop); + if (object instanceof NativeObject nativeObject) { + return check.apply(nativeObject) ? 1 : 0; } - return (Long) object; + return 0; } private int byteSizeOf(long oop) { @@ -195,6 +219,10 @@ private int failed() { return 0; // TODO: when changing primitiveFail to continue executing, properly implement this } + private Object objectAt0(Object object, long index) { + return SqueakObjectAt0Node.getUncached().execute(object, index); + } + private NativeObjectStorage firstIndexableField(long oop) { NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)); postPrimitiveCleanups.add(storage); @@ -214,11 +242,7 @@ private int instantiateClassindexableSize(long classPointer, long size) { } private int isBytes(long oop) { - Object object = objectRegistryGet(oop); - if (!(object instanceof NativeObject)) { - return 0; - } - return ((NativeObject) object).isByteType() ? 1 : 0; + return nativeObjectCheck(oop, NativeObject::isByteType); } private int majorVersion() { @@ -264,27 +288,54 @@ private int push(long oop) { return 1; } - private long fetchIntegerofObject(long fieldIndex, long objectPointer) {/* TODO */ System.out.println("Missing implementation for fetchIntegerofObject"); return 0;} + private long fetchIntegerofObject(long fieldIndex, long objectPointer) { + return objectToLong(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); + } - private long fetchLong32ofObject(long fieldIndex, long oop) {/* TODO */ System.out.println("Missing implementation for fetchLong32ofObject"); return 0;} + private long fetchLong32ofObject(long fieldIndex, long oop) { + return fetchIntegerofObject(fieldIndex, oop); + } - private long fetchPointerofObject(long index, long oop) {/* TODO */ System.out.println("Missing implementation for fetchPointerofObject"); return 0;} + private long fetchPointerofObject(long index, long oop) { + return oopFor(objectAt0(objectRegistryGet(oop), index)); + } - private double floatValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for floatValueOf"); return 0;} + private double floatValueOf(long oop) { + return objectToDouble(objectRegistryGet(oop)); + } - private long integerObjectOf(long value) {/* TODO */ System.out.println("Missing implementation for integerObjectOf"); return 0;} + private long integerObjectOf(long value) { + return oopFor(value); + } - private long integerValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for integerValueOf"); return 0;} + private long integerValueOf(long oop) { + return objectToLong(objectRegistryGet(oop)); + } private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) {/* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); return null;} - private long isArray(long oop) {/* TODO */ System.out.println("Missing implementation for isArray"); return 0;} + private long isArray(long oop) { + return objectRegistryGet(oop) instanceof ArrayObject ? 1 : 0; + } - private long isPointers(long oop) {/* TODO */ System.out.println("Missing implementation for isPointers"); return 0;} + private long isPointers(long oop) { + return objectRegistryGet(oop) instanceof AbstractPointersObject ? 1 : 0; + } - private long isPositiveMachineIntegerObject(long oop) {/* TODO */ System.out.println("Missing implementation for isPositiveMachineIntegerObject"); return 0;} + private long isPositiveMachineIntegerObject(long oop) { + Object object = objectRegistryGet(oop); + if (object instanceof Long integer) { + return integer >= 0 ? 1 : 0; + } + if (object instanceof LargeIntegerObject largeInteger) { + return largeInteger.isZeroOrPositive() && largeInteger.fitsIntoLong() ? 1 : 0; + } + return 0; + } - private long isWords(long oop) {/* TODO */ System.out.println("Missing implementation for isWords"); return 0;} + private long isWords(long oop) { + return nativeObjectCheck(oop, NativeObject::isLongType); + } private long isWordsOrBytes(long oop) {/* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); return 0;} @@ -304,17 +355,25 @@ private int push(long oop) { private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) {/* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); return 0;} - private long signed32BitIntegerFor(long integerValue) {/* TODO */ System.out.println("Missing implementation for signed32BitIntegerFor"); return 0;} + private long signed32BitIntegerFor(long integerValue) { + return integerObjectOf(integerValue); + } - private long signed32BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for signed32BitValueOf"); return 0;} + private long signed32BitValueOf(long oop) { + return integerValueOf(oop); + } private long slotSizeOf(long oop) {/* TODO */ System.out.println("Missing implementation for slotSizeOf"); return 0;} - private long stackIntegerValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackIntegerValue"); return 0;} + private long stackIntegerValue(long offset) { + return objectToLong(getObjectOnStack(offset)); + } private long stackObjectValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackObjectValue"); return 0;} - private long stackValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackValue"); return 0;} + private long stackValue(long offset) { + return oopFor(getObjectOnStack(offset)); + } private long statNumGCs() {/* TODO */ System.out.println("Missing implementation for statNumGCs"); return 0;} From fd44984ad8e91f26f463857814668d86c333bae7 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 18 Dec 2023 17:55:19 +0100 Subject: [PATCH 061/159] Define supported VM_PROXY version [skip ci] --- src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index 3df8772f7..ff1a81b2c 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -1,4 +1,7 @@ #include + +#define VM_PROXY_MAJOR 1 +#define VM_PROXY_MINOR 17 #include "sqVirtualMachine.h" VirtualMachine* createInterpreterProxy( From e9d2e7e7ff165aeaa22dbac5e8160566f2572aed Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 18 Dec 2023 18:08:16 +0100 Subject: [PATCH 062/159] Switch to newly introduced executeUncached [skip ci] --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 0a5296d7f..3e20efd4f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -16,7 +16,6 @@ import de.hpi.swa.trufflesqueak.model.LargeIntegerObject; import de.hpi.swa.trufflesqueak.model.NativeObject; import de.hpi.swa.trufflesqueak.model.NilObject; -import de.hpi.swa.trufflesqueak.model.PointersObject; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; @@ -220,7 +219,7 @@ private int failed() { } private Object objectAt0(Object object, long index) { - return SqueakObjectAt0Node.getUncached().execute(object, index); + return SqueakObjectAt0Node.executeUncached(object, index); } private NativeObjectStorage firstIndexableField(long oop) { @@ -236,8 +235,7 @@ private int instantiateClassindexableSize(long classPointer, long size) { primitiveFail(); return -1; } - SqueakObjectNewNode objectNewNode = SqueakObjectNewNode.create(); - AbstractSqueakObject newObject = objectNewNode.execute(context, (ClassObject) classObject, (int) size); + AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, (ClassObject) classObject); return oopFor(newObject); } From 67cf73d46d42d74e8ee4982b0beff8f73026bdbb Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 18 Dec 2023 18:12:25 +0100 Subject: [PATCH 063/159] Implement statNumGCs [skip ci] --- .../nodes/plugins/ffi/InterpreterProxy.java | 5 ++++- .../src/de/hpi/swa/trufflesqueak/util/MiscUtils.java | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 3e20efd4f..911535c61 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -20,6 +20,7 @@ import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.util.FrameAccess; +import de.hpi.swa.trufflesqueak.util.MiscUtils; import de.hpi.swa.trufflesqueak.util.NFIUtils; import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleClosure; import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; @@ -373,7 +374,9 @@ private long stackValue(long offset) { return oopFor(getObjectOnStack(offset)); } - private long statNumGCs() {/* TODO */ System.out.println("Missing implementation for statNumGCs"); return 0;} + private long statNumGCs() { + return MiscUtils.getCollectionCount(); + } private long storeIntegerofObjectwithValue(long index, long oop, long integer) {/* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); return 0;} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/MiscUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/MiscUtils.java index 14f399e6a..294640a78 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/MiscUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/MiscUtils.java @@ -71,6 +71,16 @@ public static String format(final String format, final Object... args) { return String.format(format, args); } + @TruffleBoundary + public static long getCollectionCount() { + long totalGCCount = 0; + for (final GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) { + final long count = gcBean.getCollectionCount(); + totalGCCount += Math.max(count, 0); + } + return totalGCCount; + } + @TruffleBoundary public static long getCollectionCount(final String[] names) { final GarbageCollectorMXBean mxBean = getGarbageCollectorMXBean(names); From 10e8a3929508f54af2320eb67c11a2a37a6845ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 12:22:47 +0100 Subject: [PATCH 064/159] Clean up, regroup and comment NonExistentPrimitiveNode --- .../primitives/PrimitiveNodeFactory.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 861519238..ef4b624f9 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -208,11 +208,6 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (nodeFactory != null) { return createNode(nodeFactory, location, numReceiverAndArguments); } else { - System.out.println("trying to execute " + moduleName + ":" + functionName); - - if (functionName.equals("primitivePluginVersion")) { - return null; - } return new NonExistentPrimitiveNode(moduleName, functionName, numReceiverAndArguments); } } @@ -233,33 +228,40 @@ public NonExistentPrimitiveNode(String moduleName, String functionName, int numR public Object execute(VirtualFrame frame) { final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(getContext(), moduleName, "{ " + + // TODO, see below //"initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + + // Currently not called, since plugins are never unloaded //"shutdownModule():SINT64; " + " }")); final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { - Object functionSymbol = NFIUtils.loadMember(getContext(), uuidPlugin, functionName, "():SINT64"); - InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); + interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); + // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by numReceiverAndArguments // before transferring control. We need the stack pointer to point at the last argument, // since the C code expects that. Therefore, we undo the decrement operation here. FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments); - interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); + // TODO: Only call when the plugin actually defines the function //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); + uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); - final Object result = functionInteropLibrary.execute(functionSymbol); - //uuidPluginLibrary.invokeMember(uuidPlugin, "shutdownModule"); - // The return value is pushed onto the stack by the Plugin via the InterpreterProxy, but TruffleSqueak + + final Object functionSymbol = NFIUtils.loadMember(getContext(), uuidPlugin, functionName, "():SINT64"); + final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); + // return value is unused, the actual return value is pushed onto the stack (see below) + functionInteropLibrary.execute(functionSymbol); + + // The return value is pushed onto the stack by the plugin via the InterpreterProxy, but TruffleSqueak // expects the return value to be returned by this function (AbstractSendNode.executeVoid). // Pop the return value and return it. final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); return returnValue; } catch (Exception e) { - System.out.println("error"); + // for debugging purposes e.printStackTrace(System.err); throw PrimitiveFailed.GENERIC_ERROR; } finally { @@ -271,6 +273,7 @@ public Object execute(VirtualFrame frame) { @Override public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { + // arguments are handled via manipulation of the stack pointer, see above return execute(frame); } } From ff2d6391d27b8d00e13002eebe0e421e59709e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 12:25:09 +0100 Subject: [PATCH 065/159] Extract NonExistentPrimitiveNode --- .../plugins/ffi/NonExistentPrimitiveNode.java | 77 +++++++++++++++++++ .../primitives/PrimitiveNodeFactory.java | 67 +--------------- 2 files changed, 78 insertions(+), 66 deletions(-) create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/NonExistentPrimitiveNode.java diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/NonExistentPrimitiveNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/NonExistentPrimitiveNode.java new file mode 100644 index 000000000..3b7764211 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/NonExistentPrimitiveNode.java @@ -0,0 +1,77 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; + +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.InteropLibrary; +import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; +import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveNode; +import de.hpi.swa.trufflesqueak.util.FrameAccess; +import de.hpi.swa.trufflesqueak.util.NFIUtils; + +import java.util.HashMap; +import java.util.Map; + +public class NonExistentPrimitiveNode extends AbstractPrimitiveNode { + final String moduleName; + final String functionName; + final int numReceiverAndArguments; + static Map loadedLibraries = new HashMap<>(); + + public NonExistentPrimitiveNode(String moduleName, String functionName, int numReceiverAndArguments) { + this.moduleName = moduleName; + this.functionName = functionName; + this.numReceiverAndArguments = numReceiverAndArguments; + } + + @Override + public Object execute(VirtualFrame frame) { + final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> + NFIUtils.loadLibrary(getContext(), moduleName, "{ " + + // TODO, see below + //"initialiseModule():SINT64; " + + "setInterpreter(POINTER):SINT64; " + + // Currently not called, since plugins are never unloaded + //"shutdownModule():SINT64; " + + " }")); + final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); + InterpreterProxy interpreterProxy = null; + try { + interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); + + // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by numReceiverAndArguments + // before transferring control. We need the stack pointer to point at the last argument, + // since the C code expects that. Therefore, we undo the decrement operation here. + FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments); + + // TODO: Only call when the plugin actually defines the function + //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); + + uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); + + final Object functionSymbol = NFIUtils.loadMember(getContext(), uuidPlugin, functionName, "():SINT64"); + final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); + // return value is unused, the actual return value is pushed onto the stack (see below) + functionInteropLibrary.execute(functionSymbol); + + // The return value is pushed onto the stack by the plugin via the InterpreterProxy, but TruffleSqueak + // expects the return value to be returned by this function (AbstractSendNode.executeVoid). + // Pop the return value and return it. + final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); + FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); + return returnValue; + } catch (Exception e) { + // for debugging purposes + e.printStackTrace(System.err); + throw PrimitiveFailed.GENERIC_ERROR; + } finally { + if (interpreterProxy != null) { + interpreterProxy.postPrimitiveCleanups(); + } + } + } + + @Override + public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { + // arguments are handled via manipulation of the stack pointer, see above + return execute(frame); + } +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index ef4b624f9..c890ef54e 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -43,6 +43,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.Win32OSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ZipPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.NonExistentPrimitiveNode; import de.hpi.swa.trufflesqueak.nodes.plugins.network.SocketPlugin; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArithmeticPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArrayStreamPrimitives; @@ -212,72 +213,6 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me } } - static class NonExistentPrimitiveNode extends AbstractPrimitiveNode { - final String moduleName; - final String functionName; - final int numReceiverAndArguments; - static Map loadedLibraries = new HashMap<>(); - - public NonExistentPrimitiveNode(String moduleName, String functionName, int numReceiverAndArguments) { - this.moduleName = moduleName; - this.functionName = functionName; - this.numReceiverAndArguments = numReceiverAndArguments; - } - - @Override - public Object execute(VirtualFrame frame) { - final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> - NFIUtils.loadLibrary(getContext(), moduleName, "{ " + - // TODO, see below - //"initialiseModule():SINT64; " + - "setInterpreter(POINTER):SINT64; " + - // Currently not called, since plugins are never unloaded - //"shutdownModule():SINT64; " + - " }")); - final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); - InterpreterProxy interpreterProxy = null; - try { - interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); - - // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by numReceiverAndArguments - // before transferring control. We need the stack pointer to point at the last argument, - // since the C code expects that. Therefore, we undo the decrement operation here. - FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments); - - // TODO: Only call when the plugin actually defines the function - //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); - - uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); - - final Object functionSymbol = NFIUtils.loadMember(getContext(), uuidPlugin, functionName, "():SINT64"); - final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); - // return value is unused, the actual return value is pushed onto the stack (see below) - functionInteropLibrary.execute(functionSymbol); - - // The return value is pushed onto the stack by the plugin via the InterpreterProxy, but TruffleSqueak - // expects the return value to be returned by this function (AbstractSendNode.executeVoid). - // Pop the return value and return it. - final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); - FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); - return returnValue; - } catch (Exception e) { - // for debugging purposes - e.printStackTrace(System.err); - throw PrimitiveFailed.GENERIC_ERROR; - } finally { - if (interpreterProxy != null) { - interpreterProxy.postPrimitiveCleanups(); - } - } - } - - @Override - public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { - // arguments are handled via manipulation of the stack pointer, see above - return execute(frame); - } - } - private static boolean isLoadInstVar(final int primitiveIndex) { return PRIMITIVE_LOAD_INST_VAR_LOWER_INDEX <= primitiveIndex && primitiveIndex <= PRIMITIVE_LOAD_INST_VAR_UPPER_INDEX; } From b93d7cc03d24dcc400403d4462c8d314c0d7292b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 12:27:35 +0100 Subject: [PATCH 066/159] Rename NonExistentPrimitiveNode to PrimExternalCallNode --- ...tPrimitiveNode.java => PrimExternalCallNode.java} | 4 ++-- .../nodes/primitives/PrimitiveNodeFactory.java | 12 ++---------- 2 files changed, 4 insertions(+), 12 deletions(-) rename src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/{NonExistentPrimitiveNode.java => PrimExternalCallNode.java} (95%) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/NonExistentPrimitiveNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java similarity index 95% rename from src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/NonExistentPrimitiveNode.java rename to src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 3b7764211..cef5531fd 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/NonExistentPrimitiveNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -10,13 +10,13 @@ import java.util.HashMap; import java.util.Map; -public class NonExistentPrimitiveNode extends AbstractPrimitiveNode { +public class PrimExternalCallNode extends AbstractPrimitiveNode { final String moduleName; final String functionName; final int numReceiverAndArguments; static Map loadedLibraries = new HashMap<>(); - public NonExistentPrimitiveNode(String moduleName, String functionName, int numReceiverAndArguments) { + public PrimExternalCallNode(String moduleName, String functionName, int numReceiverAndArguments) { this.moduleName = moduleName; this.functionName = functionName; this.numReceiverAndArguments = numReceiverAndArguments; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index c890ef54e..29477e05f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -7,9 +7,6 @@ package de.hpi.swa.trufflesqueak.nodes.primitives; import com.oracle.truffle.api.dsl.NodeFactory; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.interop.InteropLibrary; -import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.NativeObject; @@ -42,8 +39,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.UnixOSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.Win32OSProcessPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.ZipPlugin; -import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy; -import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.NonExistentPrimitiveNode; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.PrimExternalCallNode; import de.hpi.swa.trufflesqueak.nodes.plugins.network.SocketPlugin; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArithmeticPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.ArrayStreamPrimitives; @@ -53,15 +49,11 @@ import de.hpi.swa.trufflesqueak.nodes.primitives.impl.IOPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.MiscellaneousPrimitives; import de.hpi.swa.trufflesqueak.nodes.primitives.impl.StoragePrimitives; -import de.hpi.swa.trufflesqueak.util.FrameAccess; -import de.hpi.swa.trufflesqueak.util.NFIUtils; import de.hpi.swa.trufflesqueak.util.OS; import org.graalvm.collections.EconomicMap; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; public final class PrimitiveNodeFactory { @@ -209,7 +201,7 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (nodeFactory != null) { return createNode(nodeFactory, location, numReceiverAndArguments); } else { - return new NonExistentPrimitiveNode(moduleName, functionName, numReceiverAndArguments); + return new PrimExternalCallNode(moduleName, functionName, numReceiverAndArguments); } } From 4b9803a5f8a7d941cc85b8bf74bdc8b15a70937b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 12:41:27 +0100 Subject: [PATCH 067/159] Extract PostPrimitiveCleanup interface --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 5 +---- .../nodes/plugins/ffi/wrappers/NativeObjectStorage.java | 1 - .../nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java | 5 +++++ 3 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 911535c61..93e97c783 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -19,6 +19,7 @@ import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.PostPrimitiveCleanup; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.MiscUtils; import de.hpi.swa.trufflesqueak.util.NFIUtils; @@ -381,8 +382,4 @@ private long statNumGCs() { private long storeIntegerofObjectwithValue(long index, long oop, long integer) {/* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); return 0;} private long storeLong32ofObjectwithValue(long fieldIndex, long oop, long anInteger) {/* TODO */ System.out.println("Missing implementation for storeLong32ofObjectwithValue"); return 0;} - - public interface PostPrimitiveCleanup { - void cleanup(); - } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index 9b68e2a00..525284c1a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -5,7 +5,6 @@ import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import de.hpi.swa.trufflesqueak.model.NativeObject; -import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy.PostPrimitiveCleanup; @ExportLibrary(InteropLibrary.class) public abstract class NativeObjectStorage implements PostPrimitiveCleanup, TruffleObject { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java new file mode 100644 index 000000000..4d1be13b3 --- /dev/null +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java @@ -0,0 +1,5 @@ +package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; + +public interface PostPrimitiveCleanup { + void cleanup(); +} \ No newline at end of file From 4b331692a5e8cbf60495ccefc0e5137bbab5f289 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 13:17:26 +0100 Subject: [PATCH 068/159] Refactor, organize and clean up InterpreterProxy --- .../src/InterpreterProxy.c | 4 +- .../nodes/plugins/ffi/InterpreterProxy.java | 262 +++++++++++------- 2 files changed, 158 insertions(+), 108 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index ff1a81b2c..9d5eb4338 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -5,6 +5,8 @@ #include "sqVirtualMachine.h" VirtualMachine* createInterpreterProxy( + // sorted alphabetically, identical to getExecutables in + // src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java sqInt (*byteSizeOf)(sqInt oop), sqInt (*classString)(void), sqInt (*failed)(void), @@ -37,8 +39,8 @@ VirtualMachine* createInterpreterProxy( usqLong (*positive64BitValueOf)(sqInt oop), sqInt (*primitiveFail)(void), sqInt (*primitiveFailFor)(sqInt reasonCode), - sqInt (*showDisplayBitsLeftTopRightBottom)(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b), sqInt (*pushInteger)(sqInt integerValue), + sqInt (*showDisplayBitsLeftTopRightBottom)(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b), sqInt (*signed32BitIntegerFor)(sqInt integerValue), int (*signed32BitValueOf)(sqInt oop), sqInt (*slotSizeOf)(sqInt oop), diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 93e97c783..504a37dc3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -33,13 +33,48 @@ public class InterpreterProxy { private static InterpreterProxy INSTANCE = null; - private final SqueakImageContext context; private MaterializedFrame frame; private int numReceiverAndArguments; private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); - private final TruffleExecutable[] executables = new TruffleExecutable[]{ + // should not be local, as the references are needed to keep the native closures alive + // since this class is a singleton, a private instance variable will suffice + @SuppressWarnings("FieldCanBeLocal") + private final TruffleClosure[] closures; + private static Object interpreterProxyPointer = null; + + /////////////////////// + // INSTANCE CREATION // + /////////////////////// + + private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + this.context = context; + this.frame = frame; + this.numReceiverAndArguments = numReceiverAndArguments; + + TruffleExecutable[] executables = getExecutables(); + closures = new TruffleClosure[executables.length]; + for (int i = 0; i < executables.length; i++) { + closures[i] = executables[i].createClosure(context); + } + + if (interpreterProxyPointer == null) { + final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); + final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", + "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" + ); + + final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); + interpreterProxyPointer = interpreterProxyLibrary.invokeMember( + interpreterProxy, "createInterpreterProxy", (Object[]) closures); + } + } + + private TruffleExecutable[] getExecutables() { + // sorted alphabetically, identical to createInterpreterProxy in + // src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c + return new TruffleExecutable[]{ TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), TruffleExecutable.wrap("():SINT64", this::classString), TruffleExecutable.wrap("():SINT64", this::failed), @@ -72,8 +107,8 @@ public class InterpreterProxy { TruffleExecutable.wrap("(SINT64):UINT64", this::positive64BitValueOf), TruffleExecutable.wrap("():SINT64", this::primitiveFail), TruffleExecutable.wrap("(SINT64):SINT64", this::primitiveFailFor), - TruffleExecutable.wrap("(SINT64,SINT64,SINT64,SINT64,SINT64):SINT64", this::showDisplayBitsLeftTopRightBottom), TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), + TruffleExecutable.wrap("(SINT64,SINT64,SINT64,SINT64,SINT64):SINT64", this::showDisplayBitsLeftTopRightBottom), TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitValueOf), TruffleExecutable.wrap("(SINT64):SINT64", this::slotSizeOf), @@ -83,31 +118,7 @@ public class InterpreterProxy { TruffleExecutable.wrap("():SINT64", this::statNumGCs), TruffleExecutable.wrap("(SINT64,SINT64,SINT64):SINT64", this::storeIntegerofObjectwithValue), TruffleExecutable.wrap("(SINT64,SINT64,UINT64):UINT64", this::storeLong32ofObjectwithValue), - }; - - @SuppressWarnings("FieldCanBeLocal") - private final TruffleClosure[] closures; - - private static Object interpreterProxyPointer = null; - - private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { - this.context = context; - this.frame = frame; - this.numReceiverAndArguments = numReceiverAndArguments; - closures = new TruffleClosure[executables.length]; - for (int i = 0; i < executables.length; i++) { - closures[i] = executables[i].createClosure(context); - } - if (interpreterProxyPointer == null) { - final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); - final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", - "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" - ); - - final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); - interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy, "createInterpreterProxy", (Object[]) closures); - } + }; } public static InterpreterProxy instanceFor(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { @@ -123,6 +134,10 @@ public static InterpreterProxy instanceFor(SqueakImageContext context, Materiali return INSTANCE; } + /////////////////// + // MISCELLANEOUS // + /////////////////// + public Object getPointer() { return interpreterProxyPointer; } @@ -132,8 +147,11 @@ public void postPrimitiveCleanups() { postPrimitiveCleanups.clear(); } + ///////////////////////////// + // OBJECT REGISTRY HELPERS // + ///////////////////////////// + private Object objectRegistryGet(long oop) { - System.out.println("Asked for oop " + oop); return objectRegistry.get((int) oop); } @@ -148,10 +166,13 @@ private int oopFor(Object object) { if (oop < 0) { oop = addObjectToRegistry(object); } - System.out.println("Giving out oop " + oop + " for " + object); return oop; } + /////////////////// + // STACK HELPERS // + /////////////////// + private int getStackPointer() { return FrameAccess.getStackPointer(frame); } @@ -161,10 +182,10 @@ private void setStackPointer(int stackPointer) { } private void pushObject(Object object) { - System.out.println("Pushing object " + object); - int stackPointer = getStackPointer() + 1; - setStackPointer(stackPointer); - FrameAccess.setStackSlot(frame, stackPointer - 1, object); + int stackPointer = getStackPointer(); + setStackPointer(stackPointer + 1); + // push to the original stack pointer, as it always points to the slot where the next object is pushed + FrameAccess.setStackSlot(frame, stackPointer, object); } private Object getObjectOnStack(long reverseStackIndex) { @@ -182,11 +203,15 @@ private Object getObjectOnStack(long reverseStackIndex) { return FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); } + //////////////////////// + // CONVERSION HELPERS // + //////////////////////// + private long objectToLong(Object object) { if (object instanceof Long longObject) { return longObject; } - System.out.println("Object to long called with non-Long: " + object); + System.err.println("Object to long called with non-Long: " + object); primitiveFail(); return 0; } @@ -195,11 +220,28 @@ private double objectToDouble(Object object) { if (object instanceof FloatObject floatObject) { return floatObject.getValue(); } - System.out.println("Object to double called with non-FloatObject: " + object); + System.err.println("Object to double called with non-FloatObject: " + object); primitiveFail(); return 0; } + /////////////////////// + // ACCESSING HELPERS // + /////////////////////// + + private Object objectAt0(Object object, long index) { + return SqueakObjectAt0Node.executeUncached(object, index); + } + + //////////////////////// + // TYPE CHECK HELPERS // + //////////////////////// + + private int instanceOfCheck(long oop, Class klass) { + Object object = objectRegistryGet(oop); + return klass.isInstance(object) ? 1 : 0; + } + private int nativeObjectCheck(long oop, Function check) { Object object = objectRegistryGet(oop); if (object instanceof NativeObject nativeObject) { @@ -208,8 +250,15 @@ private int nativeObjectCheck(long oop, Function check) { return 0; } + /////////////////////////////// + // INTERPRETER PROXY METHODS // + /////////////////////////////// + private int byteSizeOf(long oop) { - return NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)).byteSizeOf(); + if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { + return NativeObjectStorage.from(nativeObject).byteSizeOf(); + } + return 0; } private int classString() { @@ -220,74 +269,6 @@ private int failed() { return 0; // TODO: when changing primitiveFail to continue executing, properly implement this } - private Object objectAt0(Object object, long index) { - return SqueakObjectAt0Node.executeUncached(object, index); - } - - private NativeObjectStorage firstIndexableField(long oop) { - NativeObjectStorage storage = NativeObjectStorage.from((NativeObject) objectRegistryGet(oop)); - postPrimitiveCleanups.add(storage); - return storage; - } - - private int instantiateClassindexableSize(long classPointer, long size) { - Object classObject = objectRegistryGet(classPointer); - if (!(classObject instanceof ClassObject)) { - System.out.println("instantiateClassindexableSize called with non-ClassObject: " + classObject); - primitiveFail(); - return -1; - } - AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, (ClassObject) classObject); - return oopFor(newObject); - } - - private int isBytes(long oop) { - return nativeObjectCheck(oop, NativeObject::isByteType); - } - - private int majorVersion() { - return 1; - } - - private int methodArgumentCount() { - return numReceiverAndArguments - 1; - } - - private int minorVersion() { - return 17; - } - - private int nilObject() { - return oopFor(NilObject.SINGLETON); - } - - private int pop(long nItems) { - setStackPointer(getStackPointer() - (int) nItems); - return 1; - } - - private int popthenPush(long nItems, long oop) { - pop(nItems); - push(oop); - return 1; - } - - private int primitiveFail() { - // TODO: continue executing C code - // TODO: adjust failed accordingly - throw PrimitiveFailed.GENERIC_ERROR; - } - - private int pushInteger(long integerValue) { - pushObject(integerValue); - return 1; - } - - private int push(long oop) { - pushObject(objectRegistryGet(oop)); - return 1; - } - private long fetchIntegerofObject(long fieldIndex, long objectPointer) { return objectToLong(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); } @@ -300,10 +281,30 @@ private long fetchPointerofObject(long index, long oop) { return oopFor(objectAt0(objectRegistryGet(oop), index)); } + private NativeObjectStorage firstIndexableField(long oop) { + if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { + NativeObjectStorage storage = NativeObjectStorage.from(nativeObject); + postPrimitiveCleanups.add(storage); + return storage; + } + return null; + } + private double floatValueOf(long oop) { return objectToDouble(objectRegistryGet(oop)); } + private int instantiateClassindexableSize(long classPointer, long size) { + Object object = objectRegistryGet(classPointer); + if (object instanceof ClassObject classObject) { + AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, classObject); + return oopFor(newObject); + } + System.err.println("instantiateClassindexableSize called with non-ClassObject: " + object); + primitiveFail(); + return 0; + } + private long integerObjectOf(long value) { return oopFor(value); } @@ -315,11 +316,15 @@ private long integerValueOf(long oop) { private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) {/* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); return null;} private long isArray(long oop) { - return objectRegistryGet(oop) instanceof ArrayObject ? 1 : 0; + return instanceOfCheck(oop, ArrayObject.class); + } + + private int isBytes(long oop) { + return nativeObjectCheck(oop, NativeObject::isByteType); } private long isPointers(long oop) { - return objectRegistryGet(oop) instanceof AbstractPointersObject ? 1 : 0; + return instanceOfCheck(oop, AbstractPointersObject.class); } private long isPositiveMachineIntegerObject(long oop) { @@ -339,20 +344,63 @@ private long isWords(long oop) { private long isWordsOrBytes(long oop) {/* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); return 0;} + private int majorVersion() { + return 1; + } + + private int methodArgumentCount() { + return numReceiverAndArguments - 1; + } + private long methodReturnInteger(long integer) {/* TODO */ System.out.println("Missing implementation for methodReturnInteger"); return 0;} private long methodReturnReceiver() {/* TODO */ System.out.println("Missing implementation for methodReturnReceiver"); return 0;} private long methodReturnValue(long oop) {/* TODO */ System.out.println("Missing implementation for methodReturnValue"); return 0;} + private int minorVersion() { + return 17; + } + + private int nilObject() { + return oopFor(NilObject.SINGLETON); + } + + private int pop(long nItems) { + setStackPointer(getStackPointer() - (int) nItems); + return 1; + } + + private int popthenPush(long nItems, long oop) { + pop(nItems); + push(oop); + return 1; + } + private long positive32BitIntegerFor(long integerValue) {/* TODO */ System.out.println("Missing implementation for positive32BitIntegerFor"); return 0;} private long positive32BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for positive32BitValueOf"); return 0;} private long positive64BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for positive64BitValueOf"); return 0;} + private int primitiveFail() { + // TODO: continue executing C code + // TODO: adjust failed accordingly + throw PrimitiveFailed.GENERIC_ERROR; + } + private long primitiveFailFor(long reasonCode) {/* TODO */ System.out.println("Missing implementation for primitiveFailFor"); return 0;} + private int push(long oop) { + pushObject(objectRegistryGet(oop)); + return 1; + } + + private int pushInteger(long integerValue) { + pushObject(integerValue); + return 1; + } + private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) {/* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); return 0;} private long signed32BitIntegerFor(long integerValue) { From ef8d1ef7a5995c6118978979765a3a26d081e590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 13:20:43 +0100 Subject: [PATCH 069/159] Move nativeAddress assignment into toNative --- .../trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java | 4 ++-- .../trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java | 4 ++-- .../trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java | 4 ++-- .../nodes/plugins/ffi/wrappers/NativeObjectStorage.java | 4 ++-- .../nodes/plugins/ffi/wrappers/ShortStorage.java | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index 8da40a8d8..43cc43817 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -18,8 +18,8 @@ public int byteSizeOf() { } @Override - protected void allocate() { - nativeAddress = UnsafeUtils.allocateNativeBytes(storage); + protected long allocate() { + return UnsafeUtils.allocateNativeBytes(storage); } @Override diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index 170f3735c..e72c6c8df 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -18,8 +18,8 @@ public int byteSizeOf() { } @Override - protected void allocate() { - nativeAddress = UnsafeUtils.allocateNativeInts(storage); + protected long allocate() { + return UnsafeUtils.allocateNativeInts(storage); } @Override diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index 8a923c123..f967cce4d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -18,8 +18,8 @@ public int byteSizeOf() { } @Override - protected void allocate() { - nativeAddress = UnsafeUtils.allocateNativeLongs(storage); + protected long allocate() { + return UnsafeUtils.allocateNativeLongs(storage); } @Override diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index 525284c1a..d489a0055 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -39,11 +39,11 @@ public long asPointer() { @ExportMessage public void toNative() { if (isAllocated) return; - allocate(); + nativeAddress = allocate(); isAllocated = true; } public abstract int byteSizeOf(); - protected abstract void allocate(); + protected abstract long allocate(); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 9f7a9d58f..404235f00 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -18,8 +18,8 @@ public int byteSizeOf() { } @Override - protected void allocate() { - nativeAddress = UnsafeUtils.allocateNativeShorts(storage); + protected long allocate() { + return UnsafeUtils.allocateNativeShorts(storage); } @Override From 3ea777dbc6c8b909ddea82ffbb67f3834834fd79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 13:25:00 +0100 Subject: [PATCH 070/159] Refactor and reorder NFIUtils --- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index f7fce949d..73c67ae69 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -19,14 +19,18 @@ public class NFIUtils { @ExportLibrary(InteropLibrary.class) public static class TruffleExecutable implements TruffleObject { - public String nfiSignature; - ITruffleExecutable executable; + public final String nfiSignature; + final ITruffleExecutable executable; public TruffleExecutable(String nfiSignature, ITruffleExecutable executable) { this.nfiSignature = nfiSignature; this.executable = executable; } + public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { + return new TruffleExecutable(nfiSignature, supplier); + } + public static TruffleExecutable wrap(String nfiSignature, TruffleFunction function) { return new TruffleExecutable(nfiSignature, function); } @@ -43,10 +47,6 @@ public static TruffleExecutable wrap(String nfiSignature, Truf return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { - return new TruffleExecutable(nfiSignature, supplier); - } - @ExportMessage boolean isExecutable() { return true; @@ -78,6 +78,16 @@ public interface ITruffleExecutable { Object execute(Object... arguments); } + @FunctionalInterface + public interface TruffleSupplier extends ITruffleExecutable { + R run(); + + default Object execute(Object... arguments) { + assert arguments.length == 0; + return run(); + } + } + @FunctionalInterface public interface TruffleFunction extends ITruffleExecutable { R run(T argument); @@ -128,16 +138,6 @@ default Object execute(Object... arguments) { } } - @FunctionalInterface - public interface TruffleSupplier extends ITruffleExecutable { - R run(); - - default Object execute(Object... arguments) { - assert arguments.length == 0; - return run(); - } - } - public static Object executeNFI(SqueakImageContext context, String nfiCode) { final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); return context.env.parseInternal(source).call(); From c13ef1cccd8f11f648ff0c1d4dcf6b979cb7c0cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 13:28:45 +0100 Subject: [PATCH 071/159] Use Predicate instead of Function [skip ci] --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 504a37dc3..2228588e5 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -28,7 +28,7 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Collectors; public class InterpreterProxy { @@ -242,10 +242,10 @@ private int instanceOfCheck(long oop, Class klass) { return klass.isInstance(object) ? 1 : 0; } - private int nativeObjectCheck(long oop, Function check) { + private int nativeObjectCheck(long oop, Predicate predicate) { Object object = objectRegistryGet(oop); if (object instanceof NativeObject nativeObject) { - return check.apply(nativeObject) ? 1 : 0; + return predicate.test(nativeObject) ? 1 : 0; } return 0; } From 71e707b6d8ea85294415c096cb61b878d11b3303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 13:32:31 +0100 Subject: [PATCH 072/159] Add copy note [skip ci] --- src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h index 2ee037cf6..b7bde95f0 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h @@ -1,6 +1,9 @@ #include #include "sqMemoryAccess.h" +//////////// from here on: copied from +//////////// https://github.com/OpenSmalltalk/opensmalltalk-vm/blob/ec421b99cf41fc5f2f5fb734b536d6233cdde809/src/spur64.cog/vmCallback.h + /* Automatically generated by CCodeGeneratorGlobalStructure VMMaker.oscog-eem.3150 uuid: 832f44e4-6d22-4545-ae94-d8453b49d54f */ @@ -30,4 +33,4 @@ typedef struct _VMCallbackContext { #define retword 1 #define retword64 2 #define retdouble 3 -#define retstruct 4 +#define retstruct 4 \ No newline at end of file From 9740643a493345352d2de038823f447421300844 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 21 Dec 2023 13:49:10 +0100 Subject: [PATCH 073/159] Apply eclipseformat --- .../nodes/plugins/ffi/InterpreterProxy.java | 176 +++++++++++------- .../plugins/ffi/PrimExternalCallNode.java | 18 +- .../ffi/wrappers/NativeObjectStorage.java | 4 +- .../primitives/PrimitiveNodeFactory.java | 72 +++---- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 25 ++- 5 files changed, 174 insertions(+), 121 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 2228588e5..804c6600a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -40,15 +40,15 @@ public class InterpreterProxy { private final ArrayList postPrimitiveCleanups = new ArrayList<>(); // should not be local, as the references are needed to keep the native closures alive // since this class is a singleton, a private instance variable will suffice - @SuppressWarnings("FieldCanBeLocal") - private final TruffleClosure[] closures; + @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; private static Object interpreterProxyPointer = null; /////////////////////// // INSTANCE CREATION // /////////////////////// - private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) + throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { this.context = context; this.frame = frame; this.numReceiverAndArguments = numReceiverAndArguments; @@ -62,12 +62,11 @@ private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, in if (interpreterProxyPointer == null) { final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", - "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }" - ); + "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }"); final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy, "createInterpreterProxy", (Object[]) closures); + interpreterProxy, "createInterpreterProxy", (Object[]) closures); } } @@ -75,53 +74,54 @@ private TruffleExecutable[] getExecutables() { // sorted alphabetically, identical to createInterpreterProxy in // src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c return new TruffleExecutable[]{ - TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), - TruffleExecutable.wrap("():SINT64", this::classString), - TruffleExecutable.wrap("():SINT64", this::failed), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchIntegerofObject), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchLong32ofObject), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchPointerofObject), - TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), - TruffleExecutable.wrap("(SINT64):DOUBLE", this::floatValueOf), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), - TruffleExecutable.wrap("(SINT64):SINT64", this::integerObjectOf), - TruffleExecutable.wrap("(SINT64):SINT64", this::integerValueOf), - TruffleExecutable.wrap("(STRING,STRING):POINTER", this::ioLoadFunctionFrom), - TruffleExecutable.wrap("(SINT64):SINT64", this::isArray), - TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), - TruffleExecutable.wrap("(SINT64):SINT64", this::isPointers), - TruffleExecutable.wrap("(SINT64):SINT64", this::isPositiveMachineIntegerObject), - TruffleExecutable.wrap("(SINT64):SINT64", this::isWords), - TruffleExecutable.wrap("(SINT64):SINT64", this::isWordsOrBytes), - TruffleExecutable.wrap("():SINT64", this::majorVersion), - TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), - TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnInteger), - TruffleExecutable.wrap("():SINT64", this::methodReturnReceiver), - TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnValue), - TruffleExecutable.wrap("():SINT64", this::minorVersion), - TruffleExecutable.wrap("():SINT64", this::nilObject), - TruffleExecutable.wrap("(SINT64):SINT64", this::pop), - TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), - TruffleExecutable.wrap("(UINT64):SINT64", this::positive32BitIntegerFor), - TruffleExecutable.wrap("(SINT64):UINT64", this::positive32BitValueOf), - TruffleExecutable.wrap("(SINT64):UINT64", this::positive64BitValueOf), - TruffleExecutable.wrap("():SINT64", this::primitiveFail), - TruffleExecutable.wrap("(SINT64):SINT64", this::primitiveFailFor), - TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), - TruffleExecutable.wrap("(SINT64,SINT64,SINT64,SINT64,SINT64):SINT64", this::showDisplayBitsLeftTopRightBottom), - TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), - TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitValueOf), - TruffleExecutable.wrap("(SINT64):SINT64", this::slotSizeOf), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackObjectValue), - TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), - TruffleExecutable.wrap("():SINT64", this::statNumGCs), - TruffleExecutable.wrap("(SINT64,SINT64,SINT64):SINT64", this::storeIntegerofObjectwithValue), - TruffleExecutable.wrap("(SINT64,SINT64,UINT64):UINT64", this::storeLong32ofObjectwithValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), + TruffleExecutable.wrap("():SINT64", this::classString), + TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchIntegerofObject), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchLong32ofObject), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchPointerofObject), + TruffleExecutable.wrap("(SINT64):POINTER", this::firstIndexableField), + TruffleExecutable.wrap("(SINT64):DOUBLE", this::floatValueOf), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::instantiateClassindexableSize), + TruffleExecutable.wrap("(SINT64):SINT64", this::integerObjectOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::integerValueOf), + TruffleExecutable.wrap("(STRING,STRING):POINTER", this::ioLoadFunctionFrom), + TruffleExecutable.wrap("(SINT64):SINT64", this::isArray), + TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("(SINT64):SINT64", this::isPointers), + TruffleExecutable.wrap("(SINT64):SINT64", this::isPositiveMachineIntegerObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::isWords), + TruffleExecutable.wrap("(SINT64):SINT64", this::isWordsOrBytes), + TruffleExecutable.wrap("():SINT64", this::majorVersion), + TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnInteger), + TruffleExecutable.wrap("():SINT64", this::methodReturnReceiver), + TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnValue), + TruffleExecutable.wrap("():SINT64", this::minorVersion), + TruffleExecutable.wrap("():SINT64", this::nilObject), + TruffleExecutable.wrap("(SINT64):SINT64", this::pop), + TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), + TruffleExecutable.wrap("(UINT64):SINT64", this::positive32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):UINT64", this::positive32BitValueOf), + TruffleExecutable.wrap("(SINT64):UINT64", this::positive64BitValueOf), + TruffleExecutable.wrap("():SINT64", this::primitiveFail), + TruffleExecutable.wrap("(SINT64):SINT64", this::primitiveFailFor), + TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), + TruffleExecutable.wrap("(SINT64,SINT64,SINT64,SINT64,SINT64):SINT64", this::showDisplayBitsLeftTopRightBottom), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), + TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitValueOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::slotSizeOf), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackIntegerValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackObjectValue), + TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), + TruffleExecutable.wrap("():SINT64", this::statNumGCs), + TruffleExecutable.wrap("(SINT64,SINT64,SINT64):SINT64", this::storeIntegerofObjectwithValue), + TruffleExecutable.wrap("(SINT64,SINT64,UINT64):UINT64", this::storeLong32ofObjectwithValue), }; } - public static InterpreterProxy instanceFor(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static InterpreterProxy instanceFor(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) + throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { if (INSTANCE == null) { INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); return INSTANCE; @@ -184,7 +184,8 @@ private void setStackPointer(int stackPointer) { private void pushObject(Object object) { int stackPointer = getStackPointer(); setStackPointer(stackPointer + 1); - // push to the original stack pointer, as it always points to the slot where the next object is pushed + // push to the original stack pointer, as it always points to the slot where the next object + // is pushed FrameAccess.setStackSlot(frame, stackPointer, object); } @@ -266,7 +267,8 @@ private int classString() { } private int failed() { - return 0; // TODO: when changing primitiveFail to continue executing, properly implement this + return 0; // TODO: when changing primitiveFail to continue executing, properly implement + // this } private long fetchIntegerofObject(long fieldIndex, long objectPointer) { @@ -313,7 +315,10 @@ private long integerValueOf(long oop) { return objectToLong(objectRegistryGet(oop)); } - private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) {/* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); return null;} + private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) { + /* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); + return null; + } private long isArray(long oop) { return instanceOfCheck(oop, ArrayObject.class); @@ -342,7 +347,10 @@ private long isWords(long oop) { return nativeObjectCheck(oop, NativeObject::isLongType); } - private long isWordsOrBytes(long oop) {/* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); return 0;} + private long isWordsOrBytes(long oop) { + /* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); + return 0; + } private int majorVersion() { return 1; @@ -352,11 +360,20 @@ private int methodArgumentCount() { return numReceiverAndArguments - 1; } - private long methodReturnInteger(long integer) {/* TODO */ System.out.println("Missing implementation for methodReturnInteger"); return 0;} + private long methodReturnInteger(long integer) { + /* TODO */ System.out.println("Missing implementation for methodReturnInteger"); + return 0; + } - private long methodReturnReceiver() {/* TODO */ System.out.println("Missing implementation for methodReturnReceiver"); return 0;} + private long methodReturnReceiver() { + /* TODO */ System.out.println("Missing implementation for methodReturnReceiver"); + return 0; + } - private long methodReturnValue(long oop) {/* TODO */ System.out.println("Missing implementation for methodReturnValue"); return 0;} + private long methodReturnValue(long oop) { + /* TODO */ System.out.println("Missing implementation for methodReturnValue"); + return 0; + } private int minorVersion() { return 17; @@ -377,11 +394,20 @@ private int popthenPush(long nItems, long oop) { return 1; } - private long positive32BitIntegerFor(long integerValue) {/* TODO */ System.out.println("Missing implementation for positive32BitIntegerFor"); return 0;} + private long positive32BitIntegerFor(long integerValue) { + /* TODO */ System.out.println("Missing implementation for positive32BitIntegerFor"); + return 0; + } - private long positive32BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for positive32BitValueOf"); return 0;} + private long positive32BitValueOf(long oop) { + /* TODO */ System.out.println("Missing implementation for positive32BitValueOf"); + return 0; + } - private long positive64BitValueOf(long oop) {/* TODO */ System.out.println("Missing implementation for positive64BitValueOf"); return 0;} + private long positive64BitValueOf(long oop) { + /* TODO */ System.out.println("Missing implementation for positive64BitValueOf"); + return 0; + } private int primitiveFail() { // TODO: continue executing C code @@ -389,7 +415,10 @@ private int primitiveFail() { throw PrimitiveFailed.GENERIC_ERROR; } - private long primitiveFailFor(long reasonCode) {/* TODO */ System.out.println("Missing implementation for primitiveFailFor"); return 0;} + private long primitiveFailFor(long reasonCode) { + /* TODO */ System.out.println("Missing implementation for primitiveFailFor"); + return 0; + } private int push(long oop) { pushObject(objectRegistryGet(oop)); @@ -401,7 +430,10 @@ private int pushInteger(long integerValue) { return 1; } - private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) {/* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); return 0;} + private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) { + /* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); + return 0; + } private long signed32BitIntegerFor(long integerValue) { return integerObjectOf(integerValue); @@ -411,13 +443,19 @@ private long signed32BitValueOf(long oop) { return integerValueOf(oop); } - private long slotSizeOf(long oop) {/* TODO */ System.out.println("Missing implementation for slotSizeOf"); return 0;} + private long slotSizeOf(long oop) { + /* TODO */ System.out.println("Missing implementation for slotSizeOf"); + return 0; + } private long stackIntegerValue(long offset) { return objectToLong(getObjectOnStack(offset)); } - private long stackObjectValue(long offset) {/* TODO */ System.out.println("Missing implementation for stackObjectValue"); return 0;} + private long stackObjectValue(long offset) { + /* TODO */ System.out.println("Missing implementation for stackObjectValue"); + return 0; + } private long stackValue(long offset) { return oopFor(getObjectOnStack(offset)); @@ -427,7 +465,13 @@ private long statNumGCs() { return MiscUtils.getCollectionCount(); } - private long storeIntegerofObjectwithValue(long index, long oop, long integer) {/* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); return 0;} + private long storeIntegerofObjectwithValue(long index, long oop, long integer) { + /* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); + return 0; + } - private long storeLong32ofObjectwithValue(long fieldIndex, long oop, long anInteger) {/* TODO */ System.out.println("Missing implementation for storeLong32ofObjectwithValue"); return 0;} + private long storeLong32ofObjectwithValue(long fieldIndex, long oop, long anInteger) { + /* TODO */ System.out.println("Missing implementation for storeLong32ofObjectwithValue"); + return 0; + } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index cef5531fd..28f8b34b0 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -24,26 +24,26 @@ public PrimExternalCallNode(String moduleName, String functionName, int numRecei @Override public Object execute(VirtualFrame frame) { - final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> - NFIUtils.loadLibrary(getContext(), moduleName, "{ " + + final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(getContext(), moduleName, "{ " + // TODO, see below - //"initialiseModule():SINT64; " + + // "initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + // Currently not called, since plugins are never unloaded - //"shutdownModule():SINT64; " + + // "shutdownModule():SINT64; " + " }")); final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); InterpreterProxy interpreterProxy = null; try { interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); - // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by numReceiverAndArguments + // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by + // numReceiverAndArguments // before transferring control. We need the stack pointer to point at the last argument, // since the C code expects that. Therefore, we undo the decrement operation here. FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments); // TODO: Only call when the plugin actually defines the function - //uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); + // uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); @@ -52,8 +52,10 @@ public Object execute(VirtualFrame frame) { // return value is unused, the actual return value is pushed onto the stack (see below) functionInteropLibrary.execute(functionSymbol); - // The return value is pushed onto the stack by the plugin via the InterpreterProxy, but TruffleSqueak - // expects the return value to be returned by this function (AbstractSendNode.executeVoid). + // The return value is pushed onto the stack by the plugin via the InterpreterProxy, but + // TruffleSqueak + // expects the return value to be returned by this function + // (AbstractSendNode.executeVoid). // Pop the return value and return it. final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index d489a0055..5b39e5af4 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -25,7 +25,6 @@ public static NativeObjectStorage from(NativeObject object) { } } - @ExportMessage public boolean isPointer() { return isAllocated; @@ -38,7 +37,8 @@ public long asPointer() { @ExportMessage public void toNative() { - if (isAllocated) return; + if (isAllocated) + return; nativeAddress = allocate(); isAllocated = true; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 29477e05f..8b6df937c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -75,45 +75,45 @@ public final class PrimitiveNodeFactory { static { final AbstractPrimitiveFactoryHolder[] indexPrimitives = { - new ArithmeticPrimitives(), - new ArrayStreamPrimitives(), - new BlockClosurePrimitives(), - new ContextPrimitives(), - new ControlPrimitives(), - new IOPrimitives(), - new MiscellaneousPrimitives(), - new StoragePrimitives()}; + new ArithmeticPrimitives(), + new ArrayStreamPrimitives(), + new BlockClosurePrimitives(), + new ContextPrimitives(), + new ControlPrimitives(), + new IOPrimitives(), + new MiscellaneousPrimitives(), + new StoragePrimitives()}; fillPrimitiveTable(indexPrimitives); final AbstractPrimitiveFactoryHolder[] plugins = { - new B2DPlugin(), - new BitBltPlugin(), - new BMPReadWriterPlugin(), - new ClipboardExtendedPlugin(), - new CroquetPlugin(), - new DropPlugin(), - new DSAPrims(), - new FilePlugin(), - new FloatArrayPlugin(), - new Float64ArrayPlugin(), - new TruffleSqueakPlugin(), - new HostWindowPlugin(), - new JPEGReaderPlugin(), - new JPEGReadWriter2Plugin(), - new LargeIntegers(), - new LocalePlugin(), - new Matrix2x3Plugin(), - new MiscPrimitivePlugin(), - new NullPlugin(), - new PolyglotPlugin(), - new SecurityPlugin(), - new SocketPlugin(), - new SoundCodecPrims(), - new SqueakFFIPrims(), - //new SqueakSSL(), - new UUIDPlugin(), - new ZipPlugin(), - OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; + new B2DPlugin(), + new BitBltPlugin(), + new BMPReadWriterPlugin(), + new ClipboardExtendedPlugin(), + new CroquetPlugin(), + new DropPlugin(), + new DSAPrims(), + new FilePlugin(), + new FloatArrayPlugin(), + new Float64ArrayPlugin(), + new TruffleSqueakPlugin(), + new HostWindowPlugin(), + new JPEGReaderPlugin(), + new JPEGReadWriter2Plugin(), + new LargeIntegers(), + new LocalePlugin(), + new Matrix2x3Plugin(), + new MiscPrimitivePlugin(), + new NullPlugin(), + new PolyglotPlugin(), + new SecurityPlugin(), + new SocketPlugin(), + new SoundCodecPrims(), + new SqueakFFIPrims(), + // new SqueakSSL(), + new UUIDPlugin(), + new ZipPlugin(), + OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; fillPrimitiveTable(plugins); fillPluginMap(plugins); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 73c67ae69..fce79530f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -27,23 +27,27 @@ public TruffleExecutable(String nfiSignature, ITruffleExecutable executable) { this.executable = executable; } - public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { + public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { return new TruffleExecutable(nfiSignature, supplier); } - public static TruffleExecutable wrap(String nfiSignature, TruffleFunction function) { + public static TruffleExecutable wrap(String nfiSignature, TruffleFunction function) { return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleBiFunction function) { + + public static TruffleExecutable wrap(String nfiSignature, TruffleBiFunction function) { return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleTriFunction function) { + + public static TruffleExecutable wrap(String nfiSignature, TruffleTriFunction function) { return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleQuadFunction function) { + + public static TruffleExecutable wrap(String nfiSignature, TruffleQuadFunction function) { return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleQuintFunction function) { + + public static TruffleExecutable wrap(String nfiSignature, TruffleQuintFunction function) { return new TruffleExecutable(nfiSignature, function); } @@ -157,17 +161,20 @@ public static Object createSignature(SqueakImageContext context, String signatur return executeNFI(context, signature); } - public static Object invokeSignatureMethod(SqueakImageContext context, String signature, String method, Object... args) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static Object invokeSignatureMethod(SqueakImageContext context, String signature, String method, Object... args) + throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { Object nfiSignature = createSignature(context, signature); InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); return signatureInteropLibrary.invokeMember(nfiSignature, method, args); } - public static Object createClosure(SqueakImageContext context, Object executable, String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static Object createClosure(SqueakImageContext context, Object executable, String signature) + throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { return invokeSignatureMethod(context, signature, "createClosure", executable); } - public static Object loadMember(SqueakImageContext context, Object library, String name, String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static Object loadMember(SqueakImageContext context, Object library, String name, String signature) + throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { InteropLibrary interopLibrary = getInteropLibrary(library); Object symbol = interopLibrary.readMember(library, name); return invokeSignatureMethod(context, signature, "bind", symbol); From 729be5338daf64750e202a76615524bd91b3f0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 14:06:28 +0100 Subject: [PATCH 074/159] Use size in instantiateClassindexableSize --- .../trufflesqueak/nodes/accessing/SqueakObjectNewNode.java | 4 ++++ .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/accessing/SqueakObjectNewNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/accessing/SqueakObjectNewNode.java index f7a06a296..c61325c57 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/accessing/SqueakObjectNewNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/accessing/SqueakObjectNewNode.java @@ -53,6 +53,10 @@ public final AbstractSqueakObjectWithClassAndHash execute(final Node node, final return image.reportAllocation(executeAllocation(node, image, classObject, extraSize)); } + public static final AbstractSqueakObjectWithClassAndHash executeUncached(final SqueakImageContext image, final ClassObject classObject, final int extraSize) { + return SqueakObjectNewNodeGen.getUncached().execute(null, image, classObject, extraSize); + } + protected abstract AbstractSqueakObjectWithClassAndHash executeAllocation(Node node, SqueakImageContext image, ClassObject classObject, int extraSize); @Specialization(guards = "classObject.isZeroSized()") diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 804c6600a..7a2537fd5 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -299,7 +299,7 @@ private double floatValueOf(long oop) { private int instantiateClassindexableSize(long classPointer, long size) { Object object = objectRegistryGet(classPointer); if (object instanceof ClassObject classObject) { - AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, classObject); + AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, classObject, (int) size); return oopFor(newObject); } System.err.println("instantiateClassindexableSize called with non-ClassObject: " + object); From df325419de027643f15166c8974816f22d7eb1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 14:25:31 +0100 Subject: [PATCH 075/159] Suppress unused parameters warnings in stubs --- .../.checkstyle_checks.xml | 1 + .../nodes/plugins/ffi/InterpreterProxy.java | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/.checkstyle_checks.xml b/src/de.hpi.swa.trufflesqueak/.checkstyle_checks.xml index 6e01ed725..5fe8aa177 100644 --- a/src/de.hpi.swa.trufflesqueak/.checkstyle_checks.xml +++ b/src/de.hpi.swa.trufflesqueak/.checkstyle_checks.xml @@ -188,6 +188,7 @@ + diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 7a2537fd5..aa9731d19 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -315,6 +315,7 @@ private long integerValueOf(long oop) { return objectToLong(objectRegistryGet(oop)); } + @SuppressWarnings("unused") private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) { /* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); return null; @@ -347,6 +348,7 @@ private long isWords(long oop) { return nativeObjectCheck(oop, NativeObject::isLongType); } + @SuppressWarnings("unused") private long isWordsOrBytes(long oop) { /* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); return 0; @@ -360,16 +362,19 @@ private int methodArgumentCount() { return numReceiverAndArguments - 1; } + @SuppressWarnings("unused") private long methodReturnInteger(long integer) { /* TODO */ System.out.println("Missing implementation for methodReturnInteger"); return 0; } + @SuppressWarnings("unused") private long methodReturnReceiver() { /* TODO */ System.out.println("Missing implementation for methodReturnReceiver"); return 0; } + @SuppressWarnings("unused") private long methodReturnValue(long oop) { /* TODO */ System.out.println("Missing implementation for methodReturnValue"); return 0; @@ -394,16 +399,19 @@ private int popthenPush(long nItems, long oop) { return 1; } + @SuppressWarnings("unused") private long positive32BitIntegerFor(long integerValue) { /* TODO */ System.out.println("Missing implementation for positive32BitIntegerFor"); return 0; } + @SuppressWarnings("unused") private long positive32BitValueOf(long oop) { /* TODO */ System.out.println("Missing implementation for positive32BitValueOf"); return 0; } + @SuppressWarnings("unused") private long positive64BitValueOf(long oop) { /* TODO */ System.out.println("Missing implementation for positive64BitValueOf"); return 0; @@ -415,6 +423,7 @@ private int primitiveFail() { throw PrimitiveFailed.GENERIC_ERROR; } + @SuppressWarnings("unused") private long primitiveFailFor(long reasonCode) { /* TODO */ System.out.println("Missing implementation for primitiveFailFor"); return 0; @@ -430,6 +439,7 @@ private int pushInteger(long integerValue) { return 1; } + @SuppressWarnings("unused") private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) { /* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); return 0; @@ -443,6 +453,7 @@ private long signed32BitValueOf(long oop) { return integerValueOf(oop); } + @SuppressWarnings("unused") private long slotSizeOf(long oop) { /* TODO */ System.out.println("Missing implementation for slotSizeOf"); return 0; @@ -452,6 +463,7 @@ private long stackIntegerValue(long offset) { return objectToLong(getObjectOnStack(offset)); } + @SuppressWarnings("unused") private long stackObjectValue(long offset) { /* TODO */ System.out.println("Missing implementation for stackObjectValue"); return 0; @@ -465,11 +477,13 @@ private long statNumGCs() { return MiscUtils.getCollectionCount(); } + @SuppressWarnings("unused") private long storeIntegerofObjectwithValue(long index, long oop, long integer) { /* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); return 0; } + @SuppressWarnings("unused") private long storeLong32ofObjectwithValue(long fieldIndex, long oop, long anInteger) { /* TODO */ System.out.println("Missing implementation for storeLong32ofObjectwithValue"); return 0; From e8ab2559903475720c9e2942919ac3e009d97b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 14:25:45 +0100 Subject: [PATCH 076/159] Make InterpreterProxy.objectAt0 static --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index aa9731d19..91a5d98a5 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -230,7 +230,7 @@ private double objectToDouble(Object object) { // ACCESSING HELPERS // /////////////////////// - private Object objectAt0(Object object, long index) { + private static Object objectAt0(Object object, long index) { return SqueakObjectAt0Node.executeUncached(object, index); } From a25ca3d08f5c911d8484d56e6537ff480a6596a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 21 Dec 2023 14:27:19 +0100 Subject: [PATCH 077/159] Remove unnecessary ExportLibrary annotations [skip ci] --- .../trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java | 3 --- .../trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java | 3 --- .../trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java | 3 --- .../trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java | 3 --- 4 files changed, 12 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index 43cc43817..96dac046e 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -1,10 +1,7 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.library.ExportLibrary; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -@ExportLibrary(InteropLibrary.class) public class ByteStorage extends NativeObjectStorage { byte[] storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index e72c6c8df..41ee84a3f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -1,10 +1,7 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.library.ExportLibrary; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -@ExportLibrary(InteropLibrary.class) public class IntStorage extends NativeObjectStorage { int[] storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index f967cce4d..85d9cda62 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -1,10 +1,7 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.library.ExportLibrary; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -@ExportLibrary(InteropLibrary.class) public class LongStorage extends NativeObjectStorage { long[] storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 404235f00..2e700a35d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -1,10 +1,7 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.library.ExportLibrary; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -@ExportLibrary(InteropLibrary.class) public class ShortStorage extends NativeObjectStorage { short[] storage; From 1a2e07e526d601f8794067ebc7b1e8c5c6283e2c Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 21 Dec 2023 14:56:12 +0100 Subject: [PATCH 078/159] Add guard for missing primitivePluginVersion on SqueakFFIPrims [skip ci] --- .../trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 8b6df937c..f1cd99a96 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -201,6 +201,11 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (nodeFactory != null) { return createNode(nodeFactory, location, numReceiverAndArguments); } else { + // Missing implementation by SqueakFFIPrims + // FFIPlatformDescription class>>#currentPluginVersion + if (moduleName.equals("SqueakFFIPrims")) { + return null; + } return new PrimExternalCallNode(moduleName, functionName, numReceiverAndArguments); } } From f47e0aa21cb3b16521b541a06f5edcc4918e54e4 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 21 Dec 2023 16:56:12 +0100 Subject: [PATCH 079/159] Make parameters and variables final as advised by checkstyle [skip ci] --- .../nodes/plugins/ffi/InterpreterProxy.java | 106 ++++++++++-------- .../plugins/ffi/PrimExternalCallNode.java | 6 +- .../plugins/ffi/wrappers/ByteStorage.java | 2 +- .../plugins/ffi/wrappers/IntStorage.java | 2 +- .../plugins/ffi/wrappers/LongStorage.java | 2 +- .../ffi/wrappers/NativeObjectStorage.java | 2 +- .../plugins/ffi/wrappers/ShortStorage.java | 2 +- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 43 +++---- .../swa/trufflesqueak/util/UnsafeUtils.java | 8 +- 9 files changed, 94 insertions(+), 79 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 91a5d98a5..63942954f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -33,6 +33,7 @@ public class InterpreterProxy { private static InterpreterProxy INSTANCE = null; +public final class InterpreterProxy { private final SqueakImageContext context; private MaterializedFrame frame; private int numReceiverAndArguments; @@ -47,13 +48,13 @@ public class InterpreterProxy { // INSTANCE CREATION // /////////////////////// - private InterpreterProxy(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) + private InterpreterProxy(final SqueakImageContext context, final MaterializedFrame frame, final int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { this.context = context; this.frame = frame; this.numReceiverAndArguments = numReceiverAndArguments; - TruffleExecutable[] executables = getExecutables(); + final TruffleExecutable[] executables = getExecutables(); closures = new TruffleClosure[executables.length]; for (int i = 0; i < executables.length; i++) { closures[i] = executables[i].createClosure(context); @@ -120,7 +121,7 @@ private TruffleExecutable[] getExecutables() { }; } - public static InterpreterProxy instanceFor(SqueakImageContext context, MaterializedFrame frame, int numReceiverAndArguments) + public static InterpreterProxy instanceFor(final SqueakImageContext context, final MaterializedFrame frame, final int numReceiverAndArguments) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { if (INSTANCE == null) { INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); @@ -151,17 +152,17 @@ public void postPrimitiveCleanups() { // OBJECT REGISTRY HELPERS // ///////////////////////////// - private Object objectRegistryGet(long oop) { + private Object objectRegistryGet(final long oop) { return objectRegistry.get((int) oop); } - private int addObjectToRegistry(Object object) { - int oop = objectRegistry.size(); + private int addObjectToRegistry(final Object object) { + final int oop = objectRegistry.size(); objectRegistry.add(object); return oop; } - private int oopFor(Object object) { + private int oopFor(final Object object) { int oop = objectRegistry.indexOf(object); if (oop < 0) { oop = addObjectToRegistry(object); @@ -177,26 +178,26 @@ private int getStackPointer() { return FrameAccess.getStackPointer(frame); } - private void setStackPointer(int stackPointer) { + private void setStackPointer(final int stackPointer) { FrameAccess.setStackPointer(frame, stackPointer); } - private void pushObject(Object object) { - int stackPointer = getStackPointer(); + private void pushObject(final Object object) { + final int stackPointer = getStackPointer(); setStackPointer(stackPointer + 1); // push to the original stack pointer, as it always points to the slot where the next object // is pushed FrameAccess.setStackSlot(frame, stackPointer, object); } - private Object getObjectOnStack(long reverseStackIndex) { + private Object getObjectOnStack(final long reverseStackIndex) { if (reverseStackIndex < 0) { primitiveFail(); return null; } // the stack pointer is the index of the object that is pushed onto the stack next, // so we subtract 1 to get the index of the object that was last pushed onto the stack - int stackIndex = getStackPointer() - 1 - (int) reverseStackIndex; + final int stackIndex = getStackPointer() - 1 - (int) reverseStackIndex; if (stackIndex < 0) { primitiveFail(); return null; @@ -208,7 +209,7 @@ private Object getObjectOnStack(long reverseStackIndex) { // CONVERSION HELPERS // //////////////////////// - private long objectToLong(Object object) { + private long objectToLong(final Object object) { if (object instanceof Long longObject) { return longObject; } @@ -217,7 +218,7 @@ private long objectToLong(Object object) { return 0; } - private double objectToDouble(Object object) { + private double objectToDouble(final Object object) { if (object instanceof FloatObject floatObject) { return floatObject.getValue(); } @@ -230,7 +231,7 @@ private double objectToDouble(Object object) { // ACCESSING HELPERS // /////////////////////// - private static Object objectAt0(Object object, long index) { + private static Object objectAt0(final Object object, final long index) { return SqueakObjectAt0Node.executeUncached(object, index); } @@ -238,13 +239,13 @@ private static Object objectAt0(Object object, long index) { // TYPE CHECK HELPERS // //////////////////////// - private int instanceOfCheck(long oop, Class klass) { - Object object = objectRegistryGet(oop); + private int instanceOfCheck(final long oop, final Class klass) { + final Object object = objectRegistryGet(oop); return klass.isInstance(object) ? 1 : 0; } - private int nativeObjectCheck(long oop, Predicate predicate) { - Object object = objectRegistryGet(oop); + private int nativeObjectCheck(final long oop, final Predicate predicate) { + final Object object = objectRegistryGet(oop); if (object instanceof NativeObject nativeObject) { return predicate.test(nativeObject) ? 1 : 0; } @@ -255,7 +256,7 @@ private int nativeObjectCheck(long oop, Predicate predicate) { // INTERPRETER PROXY METHODS // /////////////////////////////// - private int byteSizeOf(long oop) { + private int byteSizeOf(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { return NativeObjectStorage.from(nativeObject).byteSizeOf(); } @@ -271,70 +272,71 @@ private int failed() { // this } - private long fetchIntegerofObject(long fieldIndex, long objectPointer) { + private long fetchIntegerofObject(final long fieldIndex, final long objectPointer) { return objectToLong(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); } - private long fetchLong32ofObject(long fieldIndex, long oop) { + private long fetchLong32ofObject(final long fieldIndex, final long oop) { return fetchIntegerofObject(fieldIndex, oop); } - private long fetchPointerofObject(long index, long oop) { + private long fetchPointerofObject(final long index, final long oop) { return oopFor(objectAt0(objectRegistryGet(oop), index)); } - private NativeObjectStorage firstIndexableField(long oop) { + private NativeObjectStorage firstIndexableField(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { - NativeObjectStorage storage = NativeObjectStorage.from(nativeObject); + final NativeObjectStorage storage = NativeObjectStorage.from(nativeObject); postPrimitiveCleanups.add(storage); return storage; } return null; } - private double floatValueOf(long oop) { + private double floatValueOf(final long oop) { return objectToDouble(objectRegistryGet(oop)); } - private int instantiateClassindexableSize(long classPointer, long size) { - Object object = objectRegistryGet(classPointer); + private int instantiateClassindexableSize(final long classPointer, final long size) { + final Object object = objectRegistryGet(classPointer); if (object instanceof ClassObject classObject) { - AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, classObject, (int) size); + final AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, classObject, (int) size); return oopFor(newObject); } - System.err.println("instantiateClassindexableSize called with non-ClassObject: " + object); + LogUtils.PRIMITIVES.severe(() -> "instantiateClassindexableSize called with non-ClassObject: " + object); primitiveFail(); return 0; } - private long integerObjectOf(long value) { + private long integerObjectOf(final long value) { return oopFor(value); } - private long integerValueOf(long oop) { + private long integerValueOf(final long oop) { return objectToLong(objectRegistryGet(oop)); } @SuppressWarnings("unused") private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) { /* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); + private NativeObjectStorage ioLoadFunctionFrom(final String functionName, final String moduleName) { return null; } - private long isArray(long oop) { + private long isArray(final long oop) { return instanceOfCheck(oop, ArrayObject.class); } - private int isBytes(long oop) { + private int isBytes(final long oop) { return nativeObjectCheck(oop, NativeObject::isByteType); } - private long isPointers(long oop) { + private long isPointers(final long oop) { return instanceOfCheck(oop, AbstractPointersObject.class); } - private long isPositiveMachineIntegerObject(long oop) { - Object object = objectRegistryGet(oop); + private long isPositiveMachineIntegerObject(final long oop) { + final Object object = objectRegistryGet(oop); if (object instanceof Long integer) { return integer >= 0 ? 1 : 0; } @@ -344,13 +346,14 @@ private long isPositiveMachineIntegerObject(long oop) { return 0; } - private long isWords(long oop) { + private long isWords(final long oop) { return nativeObjectCheck(oop, NativeObject::isLongType); } @SuppressWarnings("unused") private long isWordsOrBytes(long oop) { /* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); + private long isWordsOrBytes(final long oop) { return 0; } @@ -365,6 +368,7 @@ private int methodArgumentCount() { @SuppressWarnings("unused") private long methodReturnInteger(long integer) { /* TODO */ System.out.println("Missing implementation for methodReturnInteger"); + private long methodReturnInteger(final long integer) { return 0; } @@ -377,6 +381,7 @@ private long methodReturnReceiver() { @SuppressWarnings("unused") private long methodReturnValue(long oop) { /* TODO */ System.out.println("Missing implementation for methodReturnValue"); + private long methodReturnValue(final long oop) { return 0; } @@ -388,12 +393,12 @@ private int nilObject() { return oopFor(NilObject.SINGLETON); } - private int pop(long nItems) { + private int pop(final long nItems) { setStackPointer(getStackPointer() - (int) nItems); return 1; } - private int popthenPush(long nItems, long oop) { + private int popthenPush(final long nItems, final long oop) { pop(nItems); push(oop); return 1; @@ -402,18 +407,21 @@ private int popthenPush(long nItems, long oop) { @SuppressWarnings("unused") private long positive32BitIntegerFor(long integerValue) { /* TODO */ System.out.println("Missing implementation for positive32BitIntegerFor"); + private long positive32BitIntegerFor(final long integerValue) { return 0; } @SuppressWarnings("unused") private long positive32BitValueOf(long oop) { /* TODO */ System.out.println("Missing implementation for positive32BitValueOf"); + private long positive32BitValueOf(final long oop) { return 0; } @SuppressWarnings("unused") private long positive64BitValueOf(long oop) { /* TODO */ System.out.println("Missing implementation for positive64BitValueOf"); + private long positive64BitValueOf(final long oop) { return 0; } @@ -426,15 +434,16 @@ private int primitiveFail() { @SuppressWarnings("unused") private long primitiveFailFor(long reasonCode) { /* TODO */ System.out.println("Missing implementation for primitiveFailFor"); + private long primitiveFailFor(final long reasonCode) { return 0; } - private int push(long oop) { + private int push(final long oop) { pushObject(objectRegistryGet(oop)); return 1; } - private int pushInteger(long integerValue) { + private int pushInteger(final long integerValue) { pushObject(integerValue); return 1; } @@ -442,34 +451,37 @@ private int pushInteger(long integerValue) { @SuppressWarnings("unused") private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) { /* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); + private long showDisplayBitsLeftTopRightBottom(final long aForm, final long l, final long t, final long r, final long b) { return 0; } - private long signed32BitIntegerFor(long integerValue) { + private long signed32BitIntegerFor(final long integerValue) { return integerObjectOf(integerValue); } - private long signed32BitValueOf(long oop) { + private long signed32BitValueOf(final long oop) { return integerValueOf(oop); } @SuppressWarnings("unused") private long slotSizeOf(long oop) { /* TODO */ System.out.println("Missing implementation for slotSizeOf"); + private long slotSizeOf(final long oop) { return 0; } - private long stackIntegerValue(long offset) { + private long stackIntegerValue(final long offset) { return objectToLong(getObjectOnStack(offset)); } @SuppressWarnings("unused") private long stackObjectValue(long offset) { /* TODO */ System.out.println("Missing implementation for stackObjectValue"); + private long stackObjectValue(final long offset) { return 0; } - private long stackValue(long offset) { + private long stackValue(final long offset) { return oopFor(getObjectOnStack(offset)); } @@ -480,12 +492,14 @@ private long statNumGCs() { @SuppressWarnings("unused") private long storeIntegerofObjectwithValue(long index, long oop, long integer) { /* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); + private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { return 0; } @SuppressWarnings("unused") private long storeLong32ofObjectwithValue(long fieldIndex, long oop, long anInteger) { /* TODO */ System.out.println("Missing implementation for storeLong32ofObjectwithValue"); + private long storeLong32ofObjectwithValue(final long fieldIndex, final long oop, final long anInteger) { return 0; } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 28f8b34b0..ced825eb1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -16,14 +16,14 @@ public class PrimExternalCallNode extends AbstractPrimitiveNode { final int numReceiverAndArguments; static Map loadedLibraries = new HashMap<>(); - public PrimExternalCallNode(String moduleName, String functionName, int numReceiverAndArguments) { + public PrimExternalCallNode(final String moduleName, final String functionName, final int numReceiverAndArguments) { this.moduleName = moduleName; this.functionName = functionName; this.numReceiverAndArguments = numReceiverAndArguments; } @Override - public Object execute(VirtualFrame frame) { + public Object execute(final VirtualFrame frame) { final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(getContext(), moduleName, "{ " + // TODO, see below // "initialiseModule():SINT64; " + @@ -72,7 +72,7 @@ public Object execute(VirtualFrame frame) { } @Override - public Object executeWithArguments(VirtualFrame frame, Object... receiverAndArguments) { + public Object executeWithArguments(final VirtualFrame frame, final Object... receiverAndArguments) { // arguments are handled via manipulation of the stack pointer, see above return execute(frame); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index 96dac046e..2ab6225b2 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -5,7 +5,7 @@ public class ByteStorage extends NativeObjectStorage { byte[] storage; - public ByteStorage(byte[] storage) { + public ByteStorage(final byte[] storage) { this.storage = storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index 41ee84a3f..5d0361372 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -5,7 +5,7 @@ public class IntStorage extends NativeObjectStorage { int[] storage; - public IntStorage(int[] storage) { + public IntStorage(final int[] storage) { this.storage = storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index 85d9cda62..b70f52b0f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -5,7 +5,7 @@ public class LongStorage extends NativeObjectStorage { long[] storage; - public LongStorage(long[] storage) { + public LongStorage(final long[] storage) { this.storage = storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index 5b39e5af4..1eee7e8a3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -11,7 +11,7 @@ public abstract class NativeObjectStorage implements PostPrimitiveCleanup, Truff protected long nativeAddress; private boolean isAllocated = false; - public static NativeObjectStorage from(NativeObject object) { + public static NativeObjectStorage from(final NativeObject object) { if (object.isByteType()) { return new ByteStorage(object.getByteStorage()); } else if (object.isIntType()) { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 2e700a35d..8ec709c18 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -5,7 +5,7 @@ public class ShortStorage extends NativeObjectStorage { short[] storage; - public ShortStorage(short[] storage) { + public ShortStorage(final short[] storage) { this.storage = storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index fce79530f..c1101a5be 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -22,32 +22,32 @@ public static class TruffleExecutable implements TruffleObject { public final String nfiSignature; final ITruffleExecutable executable; - public TruffleExecutable(String nfiSignature, ITruffleExecutable executable) { + public TruffleExecutable(final String nfiSignature, final ITruffleExecutable executable) { this.nfiSignature = nfiSignature; this.executable = executable; } - public static TruffleExecutable wrap(String nfiSignature, TruffleSupplier supplier) { + public static TruffleExecutable wrap(final String nfiSignature, final TruffleSupplier supplier) { return new TruffleExecutable(nfiSignature, supplier); } - public static TruffleExecutable wrap(String nfiSignature, TruffleFunction function) { + public static TruffleExecutable wrap(final String nfiSignature, final TruffleFunction function) { return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleBiFunction function) { + public static TruffleExecutable wrap(final String nfiSignature, final TruffleBiFunction function) { return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleTriFunction function) { + public static TruffleExecutable wrap(final String nfiSignature, final TruffleTriFunction function) { return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleQuadFunction function) { + public static TruffleExecutable wrap(final String nfiSignature, final TruffleQuadFunction function) { return new TruffleExecutable(nfiSignature, function); } - public static TruffleExecutable wrap(String nfiSignature, TruffleQuintFunction function) { + public static TruffleExecutable wrap(final String nfiSignature, final TruffleQuintFunction function) { return new TruffleExecutable(nfiSignature, function); } @@ -57,11 +57,11 @@ boolean isExecutable() { } @ExportMessage - Object execute(Object... arguments) { + Object execute(final Object... arguments) { return executable.execute(arguments); } - public TruffleClosure createClosure(SqueakImageContext context) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public TruffleClosure createClosure(final SqueakImageContext context) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { return new TruffleClosure(context, this); } } @@ -72,7 +72,8 @@ public static class TruffleClosure implements TruffleObject { final Object closure; - public TruffleClosure(SqueakImageContext context, TruffleExecutable executable) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public TruffleClosure(final SqueakImageContext context, final TruffleExecutable executable) + throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { this.executable = executable; this.closure = createClosure(context, executable, executable.nfiSignature); } @@ -142,12 +143,12 @@ default Object execute(Object... arguments) { } } - public static Object executeNFI(SqueakImageContext context, String nfiCode) { + public static Object executeNFI(final SqueakImageContext context, final String nfiCode) { final Source source = Source.newBuilder("nfi", nfiCode, "native").build(); return context.env.parseInternal(source).call(); } - public static Object loadLibrary(SqueakImageContext context, String moduleName, String boundSymbols) { + public static Object loadLibrary(final SqueakImageContext context, final String moduleName, final String boundSymbols) { final String libName = System.mapLibraryName(moduleName); final TruffleFile libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName); if (!libPath.exists()) { @@ -157,30 +158,30 @@ public static Object loadLibrary(SqueakImageContext context, String moduleName, return executeNFI(context, nfiCode); } - public static Object createSignature(SqueakImageContext context, String signature) { + public static Object createSignature(final SqueakImageContext context, final String signature) { return executeNFI(context, signature); } - public static Object invokeSignatureMethod(SqueakImageContext context, String signature, String method, Object... args) + public static Object invokeSignatureMethod(final SqueakImageContext context, final String signature, final String method, final Object... args) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { - Object nfiSignature = createSignature(context, signature); - InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); + final Object nfiSignature = createSignature(context, signature); + final InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); return signatureInteropLibrary.invokeMember(nfiSignature, method, args); } - public static Object createClosure(SqueakImageContext context, Object executable, String signature) + public static Object createClosure(final SqueakImageContext context, final Object executable, final String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { return invokeSignatureMethod(context, signature, "createClosure", executable); } - public static Object loadMember(SqueakImageContext context, Object library, String name, String signature) + public static Object loadMember(final SqueakImageContext context, final Object library, final String name, final String signature) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { - InteropLibrary interopLibrary = getInteropLibrary(library); - Object symbol = interopLibrary.readMember(library, name); + final InteropLibrary interopLibrary = getInteropLibrary(library); + final Object symbol = interopLibrary.readMember(library, name); return invokeSignatureMethod(context, signature, "bind", symbol); } - public static InteropLibrary getInteropLibrary(Object loadedLibrary) { + public static InteropLibrary getInteropLibrary(final Object loadedLibrary) { return InteropLibrary.getFactory().getUncached(loadedLibrary); } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java index 640ba9ac7..d97dc7b6c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java @@ -90,22 +90,22 @@ public static long allocateNativeLongs(final long[] src) { return address; } - public static void copyNativeBytesBackAndFree(final long address, byte[] dest) { + public static void copyNativeBytesBackAndFree(final long address, final byte[] dest) { UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_BYTE_BASE_OFFSET, dest.length * Byte.BYTES); UNSAFE.freeMemory(address); } - public static void copyNativeShortsBackAndFree(final long address, short[] dest) { + public static void copyNativeShortsBackAndFree(final long address, final short[] dest) { UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_SHORT_BASE_OFFSET, (long) dest.length * Short.BYTES); UNSAFE.freeMemory(address); } - public static void copyNativeIntsBackAndFree(final long address, int[] dest) { + public static void copyNativeIntsBackAndFree(final long address, final int[] dest) { UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_INT_BASE_OFFSET, (long) dest.length * Integer.BYTES); UNSAFE.freeMemory(address); } - public static void copyNativeLongsBackAndFree(final long address, long[] dest) { + public static void copyNativeLongsBackAndFree(final long address, final long[] dest) { UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_LONG_BASE_OFFSET, (long) dest.length * Long.BYTES); UNSAFE.freeMemory(address); } From 347b8564b90ec8e8e386784c9252dc71255664a6 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 21 Dec 2023 17:01:28 +0100 Subject: [PATCH 080/159] Use LogUtils [skip ci] --- .../nodes/plugins/ffi/InterpreterProxy.java | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 63942954f..443ff234f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -21,6 +21,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.PostPrimitiveCleanup; import de.hpi.swa.trufflesqueak.util.FrameAccess; +import de.hpi.swa.trufflesqueak.util.LogUtils; import de.hpi.swa.trufflesqueak.util.MiscUtils; import de.hpi.swa.trufflesqueak.util.NFIUtils; import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleClosure; @@ -213,7 +214,7 @@ private long objectToLong(final Object object) { if (object instanceof Long longObject) { return longObject; } - System.err.println("Object to long called with non-Long: " + object); + LogUtils.PRIMITIVES.severe(() -> "Object to long called with non-Long: " + object); primitiveFail(); return 0; } @@ -222,7 +223,7 @@ private double objectToDouble(final Object object) { if (object instanceof FloatObject floatObject) { return floatObject.getValue(); } - System.err.println("Object to double called with non-FloatObject: " + object); + LogUtils.PRIMITIVES.severe(() -> "Object to long called with non-FloatObject: " + object); primitiveFail(); return 0; } @@ -317,9 +318,9 @@ private long integerValueOf(final long oop) { } @SuppressWarnings("unused") - private NativeObjectStorage ioLoadFunctionFrom(String functionName, String moduleName) { - /* TODO */ System.out.println("Missing implementation for ioLoadFunctionFrom"); private NativeObjectStorage ioLoadFunctionFrom(final String functionName, final String moduleName) { + /* TODO */ + LogUtils.PRIMITIVES.severe(() -> "Missing implementation for ioLoadFunctionFrom"); return null; } @@ -351,9 +352,9 @@ private long isWords(final long oop) { } @SuppressWarnings("unused") - private long isWordsOrBytes(long oop) { - /* TODO */ System.out.println("Missing implementation for isWordsOrBytes"); private long isWordsOrBytes(final long oop) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for isWordsOrBytes"); return 0; } @@ -366,22 +367,23 @@ private int methodArgumentCount() { } @SuppressWarnings("unused") - private long methodReturnInteger(long integer) { - /* TODO */ System.out.println("Missing implementation for methodReturnInteger"); private long methodReturnInteger(final long integer) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnInteger"); return 0; } @SuppressWarnings("unused") private long methodReturnReceiver() { - /* TODO */ System.out.println("Missing implementation for methodReturnReceiver"); + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnReceiver"); return 0; } @SuppressWarnings("unused") - private long methodReturnValue(long oop) { - /* TODO */ System.out.println("Missing implementation for methodReturnValue"); private long methodReturnValue(final long oop) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnValue"); return 0; } @@ -405,23 +407,23 @@ private int popthenPush(final long nItems, final long oop) { } @SuppressWarnings("unused") - private long positive32BitIntegerFor(long integerValue) { - /* TODO */ System.out.println("Missing implementation for positive32BitIntegerFor"); private long positive32BitIntegerFor(final long integerValue) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitIntegerFor"); return 0; } @SuppressWarnings("unused") - private long positive32BitValueOf(long oop) { - /* TODO */ System.out.println("Missing implementation for positive32BitValueOf"); private long positive32BitValueOf(final long oop) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitValueOf"); return 0; } @SuppressWarnings("unused") - private long positive64BitValueOf(long oop) { - /* TODO */ System.out.println("Missing implementation for positive64BitValueOf"); private long positive64BitValueOf(final long oop) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for positive64BitValueOf"); return 0; } @@ -432,9 +434,9 @@ private int primitiveFail() { } @SuppressWarnings("unused") - private long primitiveFailFor(long reasonCode) { - /* TODO */ System.out.println("Missing implementation for primitiveFailFor"); private long primitiveFailFor(final long reasonCode) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for primitiveFailFor"); return 0; } @@ -449,9 +451,9 @@ private int pushInteger(final long integerValue) { } @SuppressWarnings("unused") - private long showDisplayBitsLeftTopRightBottom(long aForm, long l, long t, long r, long b) { - /* TODO */ System.out.println("Missing implementation for showDisplayBitsLeftTopRightBottom"); private long showDisplayBitsLeftTopRightBottom(final long aForm, final long l, final long t, final long r, final long b) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for showDisplayBitsLeftTopRightBottom"); return 0; } @@ -464,9 +466,9 @@ private long signed32BitValueOf(final long oop) { } @SuppressWarnings("unused") - private long slotSizeOf(long oop) { - /* TODO */ System.out.println("Missing implementation for slotSizeOf"); private long slotSizeOf(final long oop) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for slotSizeOf"); return 0; } @@ -475,9 +477,9 @@ private long stackIntegerValue(final long offset) { } @SuppressWarnings("unused") - private long stackObjectValue(long offset) { - /* TODO */ System.out.println("Missing implementation for stackObjectValue"); private long stackObjectValue(final long offset) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for stackObjectValue"); return 0; } @@ -490,16 +492,16 @@ private long statNumGCs() { } @SuppressWarnings("unused") - private long storeIntegerofObjectwithValue(long index, long oop, long integer) { - /* TODO */ System.out.println("Missing implementation for storeIntegerofObjectwithValue"); private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for storeIntegerofObjectwithValue"); return 0; } @SuppressWarnings("unused") - private long storeLong32ofObjectwithValue(long fieldIndex, long oop, long anInteger) { - /* TODO */ System.out.println("Missing implementation for storeLong32ofObjectwithValue"); private long storeLong32ofObjectwithValue(final long fieldIndex, final long oop, final long anInteger) { + /* TODO */ + LogUtils.PRIMITIVES.warning("Missing implementation for storeLong32ofObjectwithValue"); return 0; } } From 9c62c275b7b56e7940aa014ae346755381877c51 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 21 Dec 2023 17:12:20 +0100 Subject: [PATCH 081/159] Apply misc suggestions [skip ci] --- .../nodes/plugins/ffi/InterpreterProxy.java | 11 +++++------ .../nodes/plugins/ffi/PrimExternalCallNode.java | 2 +- .../plugins/ffi/wrappers/NativeObjectStorage.java | 3 ++- .../plugins/ffi/wrappers/PostPrimitiveCleanup.java | 2 +- .../nodes/primitives/PrimitiveNodeFactory.java | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 443ff234f..d16f1bf24 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -32,9 +32,8 @@ import java.util.function.Predicate; import java.util.stream.Collectors; -public class InterpreterProxy { - private static InterpreterProxy INSTANCE = null; public final class InterpreterProxy { + private static InterpreterProxy INSTANCE; private final SqueakImageContext context; private MaterializedFrame frame; private int numReceiverAndArguments; @@ -43,7 +42,7 @@ public final class InterpreterProxy { // should not be local, as the references are needed to keep the native closures alive // since this class is a singleton, a private instance variable will suffice @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; - private static Object interpreterProxyPointer = null; + private static Object interpreterProxyPointer; /////////////////////// // INSTANCE CREATION // @@ -140,7 +139,7 @@ public static InterpreterProxy instanceFor(final SqueakImageContext context, fin // MISCELLANEOUS // /////////////////// - public Object getPointer() { + public static Object getPointer() { return interpreterProxyPointer; } @@ -269,8 +268,8 @@ private int classString() { } private int failed() { - return 0; // TODO: when changing primitiveFail to continue executing, properly implement - // this + // TODO: when changing primitiveFail to continue executing, properly implement this + return 0; } private long fetchIntegerofObject(final long fieldIndex, final long objectPointer) { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index ced825eb1..3ab0316d5 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -45,7 +45,7 @@ public Object execute(final VirtualFrame frame) { // TODO: Only call when the plugin actually defines the function // uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); - uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", interpreterProxy.getPointer()); + uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", InterpreterProxy.getPointer()); final Object functionSymbol = NFIUtils.loadMember(getContext(), uuidPlugin, functionName, "():SINT64"); final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index 1eee7e8a3..d5b793a47 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -37,8 +37,9 @@ public long asPointer() { @ExportMessage public void toNative() { - if (isAllocated) + if (isAllocated) { return; + } nativeAddress = allocate(); isAllocated = true; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java index 4d1be13b3..79c85fb8d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java @@ -2,4 +2,4 @@ public interface PostPrimitiveCleanup { void cleanup(); -} \ No newline at end of file +} diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index f1cd99a96..85ca0a150 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -298,4 +298,4 @@ private static void addEntryToPrimitiveTable(final int index, final NodeFactory< assert !map.containsKey(numReceiverAndArguments) : "primitives are not allowed to override others (#" + index + ")"; map.put(nodeFactory.getExecutionSignature().size(), nodeFactory); } -} \ No newline at end of file +} From f8fdb68ec1f0d135bc6f2e9c64f7f6751054862b Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 21 Dec 2023 18:12:16 +0100 Subject: [PATCH 082/159] Rename references to uuidPlugin [skip ci] --- .../nodes/plugins/ffi/PrimExternalCallNode.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 3ab0316d5..7e34df39a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -24,14 +24,14 @@ public PrimExternalCallNode(final String moduleName, final String functionName, @Override public Object execute(final VirtualFrame frame) { - final Object uuidPlugin = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(getContext(), moduleName, "{ " + + final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(getContext(), moduleName, "{ " + // TODO, see below // "initialiseModule():SINT64; " + "setInterpreter(POINTER):SINT64; " + // Currently not called, since plugins are never unloaded // "shutdownModule():SINT64; " + " }")); - final InteropLibrary uuidPluginLibrary = NFIUtils.getInteropLibrary(uuidPlugin); + final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(moduleLibrary); InterpreterProxy interpreterProxy = null; try { interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); @@ -45,9 +45,9 @@ public Object execute(final VirtualFrame frame) { // TODO: Only call when the plugin actually defines the function // uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); - uuidPluginLibrary.invokeMember(uuidPlugin, "setInterpreter", InterpreterProxy.getPointer()); + moduleInteropLibrary.invokeMember(moduleLibrary, "setInterpreter", InterpreterProxy.getPointer()); - final Object functionSymbol = NFIUtils.loadMember(getContext(), uuidPlugin, functionName, "():SINT64"); + final Object functionSymbol = NFIUtils.loadMember(getContext(), moduleLibrary, functionName, "():SINT64"); final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); // return value is unused, the actual return value is pushed onto the stack (see below) functionInteropLibrary.execute(functionSymbol); From 514baf61dbca15cd68b9ed509001fb0432d52220 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 8 Jan 2024 13:25:35 +0100 Subject: [PATCH 083/159] Mark storage class and field as final [skip ci] --- .../trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java | 4 ++-- .../trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java | 4 ++-- .../trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java | 4 ++-- .../nodes/plugins/ffi/wrappers/ShortStorage.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index 2ab6225b2..d1541f9be 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -2,8 +2,8 @@ import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -public class ByteStorage extends NativeObjectStorage { - byte[] storage; +public final class ByteStorage extends NativeObjectStorage { + final byte[] storage; public ByteStorage(final byte[] storage) { this.storage = storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index 5d0361372..9d316ea16 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -2,8 +2,8 @@ import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -public class IntStorage extends NativeObjectStorage { - int[] storage; +public final class IntStorage extends NativeObjectStorage { + final int[] storage; public IntStorage(final int[] storage) { this.storage = storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index b70f52b0f..4653e0963 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -2,8 +2,8 @@ import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -public class LongStorage extends NativeObjectStorage { - long[] storage; +public final class LongStorage extends NativeObjectStorage { + final long[] storage; public LongStorage(final long[] storage) { this.storage = storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 8ec709c18..a1beb3000 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -2,8 +2,8 @@ import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -public class ShortStorage extends NativeObjectStorage { - short[] storage; +public final class ShortStorage extends NativeObjectStorage { + final short[] storage; public ShortStorage(final short[] storage) { this.storage = storage; From 5cdf731da618d251b3116d0c71df0e778d46641e Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 8 Jan 2024 13:25:51 +0100 Subject: [PATCH 084/159] Mark class final [skip ci] --- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index c1101a5be..c4fab08c3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -15,7 +15,7 @@ import java.io.File; -public class NFIUtils { +public final class NFIUtils { @ExportLibrary(InteropLibrary.class) public static class TruffleExecutable implements TruffleObject { From c635accd3881b95b43eb4a0eab9b252c9f5064be Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 8 Jan 2024 13:34:29 +0100 Subject: [PATCH 085/159] Extract numBytes variables [skip ci] --- .../swa/trufflesqueak/util/UnsafeUtils.java | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java index d97dc7b6c..938e14526 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/UnsafeUtils.java @@ -67,46 +67,54 @@ public static void copyShorts(final short[] src, final long srcPos, final short[ } public static long allocateNativeBytes(final byte[] src) { - final long address = UNSAFE.allocateMemory((long) src.length * Byte.BYTES); - UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length * Byte.BYTES); + final long numBytes = src.length * Byte.BYTES; + final long address = UNSAFE.allocateMemory(numBytes); + UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, numBytes); return address; } public static long allocateNativeShorts(final short[] src) { - final long address = UNSAFE.allocateMemory((long) src.length * Short.BYTES); - UNSAFE.copyMemory(src, Unsafe.ARRAY_SHORT_BASE_OFFSET, null, address, (long) src.length * Short.BYTES); + final long numBytes = (long) src.length * Short.BYTES; + final long address = UNSAFE.allocateMemory(numBytes); + UNSAFE.copyMemory(src, Unsafe.ARRAY_SHORT_BASE_OFFSET, null, address, numBytes); return address; } public static long allocateNativeInts(final int[] src) { - final long address = UNSAFE.allocateMemory((long) src.length * Integer.BYTES); - UNSAFE.copyMemory(src, Unsafe.ARRAY_INT_BASE_OFFSET, null, address, (long) src.length * Integer.BYTES); + final long numBytes = (long) src.length * Integer.BYTES; + final long address = UNSAFE.allocateMemory(numBytes); + UNSAFE.copyMemory(src, Unsafe.ARRAY_INT_BASE_OFFSET, null, address, numBytes); return address; } public static long allocateNativeLongs(final long[] src) { - final long address = UNSAFE.allocateMemory((long) src.length * Long.BYTES); - UNSAFE.copyMemory(src, Unsafe.ARRAY_LONG_BASE_OFFSET, null, address, (long) src.length * Long.BYTES); + final long numBytes = (long) src.length * Long.BYTES; + final long address = UNSAFE.allocateMemory(numBytes); + UNSAFE.copyMemory(src, Unsafe.ARRAY_LONG_BASE_OFFSET, null, address, numBytes); return address; } public static void copyNativeBytesBackAndFree(final long address, final byte[] dest) { - UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_BYTE_BASE_OFFSET, dest.length * Byte.BYTES); + final long numBytes = dest.length * Byte.BYTES; + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_BYTE_BASE_OFFSET, numBytes); UNSAFE.freeMemory(address); } public static void copyNativeShortsBackAndFree(final long address, final short[] dest) { - UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_SHORT_BASE_OFFSET, (long) dest.length * Short.BYTES); + final long numBytes = (long) dest.length * Short.BYTES; + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_SHORT_BASE_OFFSET, numBytes); UNSAFE.freeMemory(address); } public static void copyNativeIntsBackAndFree(final long address, final int[] dest) { - UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_INT_BASE_OFFSET, (long) dest.length * Integer.BYTES); + final long numBytes = (long) dest.length * Integer.BYTES; + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_INT_BASE_OFFSET, numBytes); UNSAFE.freeMemory(address); } public static void copyNativeLongsBackAndFree(final long address, final long[] dest) { - UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_LONG_BASE_OFFSET, (long) dest.length * Long.BYTES); + final long numBytes = (long) dest.length * Long.BYTES; + UNSAFE.copyMemory(null, address, dest, Unsafe.ARRAY_LONG_BASE_OFFSET, numBytes); UNSAFE.freeMemory(address); } From dca71f919ca5c8a3f935a64af8398e61ab4d0494 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 8 Jan 2024 14:39:47 +0100 Subject: [PATCH 086/159] Mark field final --- .../trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 7e34df39a..b621d5bd1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -14,7 +14,7 @@ public class PrimExternalCallNode extends AbstractPrimitiveNode { final String moduleName; final String functionName; final int numReceiverAndArguments; - static Map loadedLibraries = new HashMap<>(); + final static Map loadedLibraries = new HashMap<>(); public PrimExternalCallNode(final String moduleName, final String functionName, final int numReceiverAndArguments) { this.moduleName = moduleName; From 543d77d9f02596848d1f65a214bf8121413988ee Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 8 Jan 2024 14:40:04 +0100 Subject: [PATCH 087/159] Remove redundant initialisation --- .../nodes/plugins/ffi/wrappers/NativeObjectStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index d5b793a47..e6fe49e65 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -9,7 +9,7 @@ @ExportLibrary(InteropLibrary.class) public abstract class NativeObjectStorage implements PostPrimitiveCleanup, TruffleObject { protected long nativeAddress; - private boolean isAllocated = false; + private boolean isAllocated; public static NativeObjectStorage from(final NativeObject object) { if (object.isByteType()) { From 552aeaf0f6d24da0db73da00a1adb98629baed41 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 8 Jan 2024 14:46:48 +0100 Subject: [PATCH 088/159] Replace raw exception type with assertion --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index d16f1bf24..0815eb26c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -127,9 +127,8 @@ public static InterpreterProxy instanceFor(final SqueakImageContext context, fin INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); return INSTANCE; } - if (INSTANCE.context != context) { - throw new RuntimeException("InterpreterProxy does not support multiple SqueakImageContexts"); - } + assert INSTANCE.context == context : "received new SqueakImageContext"; + INSTANCE.frame = frame; INSTANCE.numReceiverAndArguments = numReceiverAndArguments; return INSTANCE; From d598774132c390459cfdbc8b4159caec966b84c6 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 11 Jan 2024 09:33:48 +0100 Subject: [PATCH 089/159] Put most of external call behind a TruffleBoundary --- .../plugins/ffi/PrimExternalCallNode.java | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index b621d5bd1..6ddf68fd5 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -1,20 +1,23 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; +import java.util.HashMap; +import java.util.Map; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.InteropLibrary; + import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveNode; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; -import java.util.HashMap; -import java.util.Map; - -public class PrimExternalCallNode extends AbstractPrimitiveNode { - final String moduleName; - final String functionName; - final int numReceiverAndArguments; - final static Map loadedLibraries = new HashMap<>(); +public final class PrimExternalCallNode extends AbstractPrimitiveNode { + private final String moduleName; + private final String functionName; + private final int numReceiverAndArguments; + private static final Map loadedLibraries = new HashMap<>(); public PrimExternalCallNode(final String moduleName, final String functionName, final int numReceiverAndArguments) { this.moduleName = moduleName; @@ -24,6 +27,17 @@ public PrimExternalCallNode(final String moduleName, final String functionName, @Override public Object execute(final VirtualFrame frame) { + return doExternalCall(frame.materialize()); + } + + @Override + public Object executeWithArguments(final VirtualFrame frame, final Object... receiverAndArguments) { + // arguments are handled via manipulation of the stack pointer, see above + return execute(frame); + } + + @TruffleBoundary + private Object doExternalCall(final MaterializedFrame frame) { final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(getContext(), moduleName, "{ " + // TODO, see below // "initialiseModule():SINT64; " + @@ -34,7 +48,7 @@ public Object execute(final VirtualFrame frame) { final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(moduleLibrary); InterpreterProxy interpreterProxy = null; try { - interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame.materialize(), numReceiverAndArguments); + interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by // numReceiverAndArguments @@ -70,10 +84,4 @@ public Object execute(final VirtualFrame frame) { } } } - - @Override - public Object executeWithArguments(final VirtualFrame frame, final Object... receiverAndArguments) { - // arguments are handled via manipulation of the stack pointer, see above - return execute(frame); - } } From 6ae678b2d4fb0953abb45d64a5d358d2705a6cc5 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 11 Jan 2024 09:34:47 +0100 Subject: [PATCH 090/159] Add a TruffleBoundary to TruffleExecutable --- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index c4fab08c3..3734d27c8 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,5 +1,8 @@ package de.hpi.swa.trufflesqueak.util; +import java.io.File; + +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -10,11 +13,10 @@ 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; -import java.io.File; - public final class NFIUtils { @ExportLibrary(InteropLibrary.class) @@ -57,6 +59,7 @@ boolean isExecutable() { } @ExportMessage + @TruffleBoundary Object execute(final Object... arguments) { return executable.execute(arguments); } From 95fc76ede23151058eae2b373f09f58ecfd4fa0d Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 11 Jan 2024 15:11:33 +0100 Subject: [PATCH 091/159] Extract loading from execute --- .../plugins/ffi/PrimExternalCallNode.java | 66 ++++++++++++------- .../primitives/PrimitiveNodeFactory.java | 11 +++- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 8 +-- 3 files changed, 55 insertions(+), 30 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 6ddf68fd5..a3a1c4a3d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -1,30 +1,60 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; -import java.util.HashMap; -import java.util.Map; - import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; - +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; +import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveNode; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; +import java.util.HashMap; +import java.util.Map; + public final class PrimExternalCallNode extends AbstractPrimitiveNode { - private final String moduleName; - private final String functionName; + private final Object moduleLibrary; + private final InteropLibrary moduleInteropLibrary; + private final Object functionSymbol; + private final InteropLibrary functionInteropLibrary; private final int numReceiverAndArguments; private static final Map loadedLibraries = new HashMap<>(); - public PrimExternalCallNode(final String moduleName, final String functionName, final int numReceiverAndArguments) { - this.moduleName = moduleName; - this.functionName = functionName; + public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary moduleInteropLibrary, final Object functionSymbol, final InteropLibrary functionInteropLibrary, + final int numReceiverAndArguments) { + this.moduleLibrary = moduleLibrary; + this.moduleInteropLibrary = moduleInteropLibrary; + this.functionSymbol = functionSymbol; + this.functionInteropLibrary = functionInteropLibrary; this.numReceiverAndArguments = numReceiverAndArguments; } + public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) + throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + final SqueakImageContext context = SqueakImageContext.getSlow(); + final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(context, moduleName, "{ " + + // TODO, see below + // "initialiseModule():SINT64; " + + "setInterpreter(POINTER):SINT64; " + + // Currently not called, since plugins are never unloaded + // "shutdownModule():SINT64; " + + " }")); + if (moduleLibrary == null) { + return null; + } + final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(moduleLibrary); + + final Object functionSymbol = NFIUtils.loadMember(context, moduleLibrary, functionName, "():SINT64"); + final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); + + return new PrimExternalCallNode(moduleLibrary, moduleInteropLibrary, functionSymbol, functionInteropLibrary, numReceiverAndArguments); + } + @Override public Object execute(final VirtualFrame frame) { return doExternalCall(frame.materialize()); @@ -32,20 +62,12 @@ public Object execute(final VirtualFrame frame) { @Override public Object executeWithArguments(final VirtualFrame frame, final Object... receiverAndArguments) { - // arguments are handled via manipulation of the stack pointer, see above + // arguments are handled via manipulation of the stack pointer, see below return execute(frame); } @TruffleBoundary private Object doExternalCall(final MaterializedFrame frame) { - final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(getContext(), moduleName, "{ " + - // TODO, see below - // "initialiseModule():SINT64; " + - "setInterpreter(POINTER):SINT64; " + - // Currently not called, since plugins are never unloaded - // "shutdownModule():SINT64; " + - " }")); - final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(moduleLibrary); InterpreterProxy interpreterProxy = null; try { interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); @@ -61,16 +83,12 @@ private Object doExternalCall(final MaterializedFrame frame) { moduleInteropLibrary.invokeMember(moduleLibrary, "setInterpreter", InterpreterProxy.getPointer()); - final Object functionSymbol = NFIUtils.loadMember(getContext(), moduleLibrary, functionName, "():SINT64"); - final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); // return value is unused, the actual return value is pushed onto the stack (see below) functionInteropLibrary.execute(functionSymbol); // The return value is pushed onto the stack by the plugin via the InterpreterProxy, but - // TruffleSqueak - // expects the return value to be returned by this function - // (AbstractSendNode.executeVoid). - // Pop the return value and return it. + // TruffleSqueak expects the return value to be returned by this function + // (AbstractSendNode.executeVoid). Pop the return value and return it. final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); return returnValue; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index 85ca0a150..a432ab325 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -7,6 +7,10 @@ package de.hpi.swa.trufflesqueak.nodes.primitives; import com.oracle.truffle.api.dsl.NodeFactory; +import com.oracle.truffle.api.interop.ArityException; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.NativeObject; @@ -206,7 +210,12 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (moduleName.equals("SqueakFFIPrims")) { return null; } - return new PrimExternalCallNode(moduleName, functionName, numReceiverAndArguments); + try { + return PrimExternalCallNode.load(moduleName, functionName, numReceiverAndArguments); + } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException | UnsupportedTypeException e) { + assert false : e.getMessage(); + return null; + } } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 3734d27c8..c0e2323ca 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,7 +1,5 @@ package de.hpi.swa.trufflesqueak.util; -import java.io.File; - import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.interop.ArityException; @@ -13,10 +11,10 @@ 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; +import java.io.File; + public final class NFIUtils { @ExportLibrary(InteropLibrary.class) @@ -155,7 +153,7 @@ public static Object loadLibrary(final SqueakImageContext context, final String final String libName = System.mapLibraryName(moduleName); final TruffleFile libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName); if (!libPath.exists()) { - throw PrimitiveFailed.GENERIC_ERROR; + return null; } final String nfiCode = "load \"" + libPath.getAbsoluteFile().getPath() + "\" " + boundSymbols; return executeNFI(context, nfiCode); From 9e71b6d76eede5a14c0d2a34242da8dd92d49ba8 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Thu, 11 Jan 2024 16:19:28 +0100 Subject: [PATCH 092/159] Move error handling closer to throw --- .../nodes/plugins/ffi/InterpreterProxy.java | 1 + .../plugins/ffi/PrimExternalCallNode.java | 6 +---- .../primitives/PrimitiveNodeFactory.java | 25 ++++++++----------- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 24 ++++++++++++------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 0815eb26c..54f822402 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -64,6 +64,7 @@ private InterpreterProxy(final SqueakImageContext context, final MaterializedFra final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }"); + assert interpreterProxy != null : "InterpreterProxy module not found!"; final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); interpreterProxyPointer = interpreterProxyLibrary.invokeMember( diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index a3a1c4a3d..28edec963 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -3,11 +3,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveNode; @@ -34,8 +31,7 @@ public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary mod this.numReceiverAndArguments = numReceiverAndArguments; } - public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) throws UnsupportedMessageException { final SqueakImageContext context = SqueakImageContext.getSlow(); final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(context, moduleName, "{ " + // TODO, see below diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index a432ab325..3acdbf991 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -7,10 +7,7 @@ package de.hpi.swa.trufflesqueak.nodes.primitives; import com.oracle.truffle.api.dsl.NodeFactory; -import com.oracle.truffle.api.interop.ArityException; -import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.NativeObject; @@ -204,18 +201,16 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me final NodeFactory nodeFactory = PLUGIN_MAP.get(moduleName, EconomicMap.emptyMap()).get(functionName, EconomicMap.emptyMap()).get(numReceiverAndArguments); if (nodeFactory != null) { return createNode(nodeFactory, location, numReceiverAndArguments); - } else { - // Missing implementation by SqueakFFIPrims - // FFIPlatformDescription class>>#currentPluginVersion - if (moduleName.equals("SqueakFFIPrims")) { - return null; - } - try { - return PrimExternalCallNode.load(moduleName, functionName, numReceiverAndArguments); - } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException | UnsupportedTypeException e) { - assert false : e.getMessage(); - return null; - } + } + // Missing implementation by SqueakFFIPrims + // FFIPlatformDescription class>>#currentPluginVersion + if (moduleName.equals("SqueakFFIPrims")) { + return null; + } + try { + return PrimExternalCallNode.load(moduleName, functionName, numReceiverAndArguments); + } catch (UnsupportedMessageException e) { + return null; } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index c0e2323ca..163609d69 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -163,22 +163,30 @@ public static Object createSignature(final SqueakImageContext context, final Str return executeNFI(context, signature); } - public static Object invokeSignatureMethod(final SqueakImageContext context, final String signature, final String method, final Object... args) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static Object invokeSignatureMethod(final SqueakImageContext context, final String signature, final String method, final Object... args) throws UnsupportedMessageException { final Object nfiSignature = createSignature(context, signature); final InteropLibrary signatureInteropLibrary = getInteropLibrary(nfiSignature); - return signatureInteropLibrary.invokeMember(nfiSignature, method, args); + try { + return signatureInteropLibrary.invokeMember(nfiSignature, method, args); + } catch (ArityException | UnsupportedTypeException | UnknownIdentifierException e) { + assert false : e.getMessage(); + return null; + } } - public static Object createClosure(final SqueakImageContext context, final Object executable, final String signature) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static Object createClosure(final SqueakImageContext context, final Object executable, final String signature) throws UnsupportedMessageException { return invokeSignatureMethod(context, signature, "createClosure", executable); } - public static Object loadMember(final SqueakImageContext context, final Object library, final String name, final String signature) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static Object loadMember(final SqueakImageContext context, final Object library, final String name, final String signature) throws UnsupportedMessageException { final InteropLibrary interopLibrary = getInteropLibrary(library); - final Object symbol = interopLibrary.readMember(library, name); + final Object symbol; + try { + symbol = interopLibrary.readMember(library, name); + } catch (UnknownIdentifierException e) { + assert false : e.getMessage(); + return null; + } return invokeSignatureMethod(context, signature, "bind", symbol); } From 04bc4c9c9100901b8b425805b91c1ce537bd1c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 15 Jan 2024 13:36:02 +0100 Subject: [PATCH 093/159] Move handling of InteropExceptions and detect modules without setInterpreter --- .../plugins/ffi/PrimExternalCallNode.java | 34 +++++++++++-------- .../primitives/PrimitiveNodeFactory.java | 16 +-------- .../hpi/swa/trufflesqueak/util/NFIUtils.java | 22 +++++++++--- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index a3a1c4a3d..db97a55a2 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -34,25 +34,31 @@ public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary mod this.numReceiverAndArguments = numReceiverAndArguments; } - public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) { final SqueakImageContext context = SqueakImageContext.getSlow(); - final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> NFIUtils.loadLibrary(context, moduleName, "{ " + - // TODO, see below - // "initialiseModule():SINT64; " + - "setInterpreter(POINTER):SINT64; " + - // Currently not called, since plugins are never unloaded - // "shutdownModule():SINT64; " + - " }")); + final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> { + final Object library = NFIUtils.loadLibrary(context, moduleName, ""); + try { + NFIUtils.loadMember(context, library, "setInterpreter", "(POINTER):SINT64"); + } catch (UnknownIdentifierException e) { + // module has no setInterpreter, cannot be loaded + return null; + } + return library; + }); if (moduleLibrary == null) { + // module not found return null; } final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(moduleLibrary); - - final Object functionSymbol = NFIUtils.loadMember(context, moduleLibrary, functionName, "():SINT64"); - final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); - - return new PrimExternalCallNode(moduleLibrary, moduleInteropLibrary, functionSymbol, functionInteropLibrary, numReceiverAndArguments); + try { + final Object functionSymbol = NFIUtils.loadMember(context, moduleLibrary, functionName, "():SINT64"); + final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); + return new PrimExternalCallNode(moduleLibrary, moduleInteropLibrary, functionSymbol, functionInteropLibrary, numReceiverAndArguments); + } catch (UnknownIdentifierException e) { + // function not found + return null; + } } @Override diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index a432ab325..1e5c82413 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -7,10 +7,6 @@ package de.hpi.swa.trufflesqueak.nodes.primitives; import com.oracle.truffle.api.dsl.NodeFactory; -import com.oracle.truffle.api.interop.ArityException; -import com.oracle.truffle.api.interop.UnknownIdentifierException; -import com.oracle.truffle.api.interop.UnsupportedMessageException; -import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.model.ArrayObject; import de.hpi.swa.trufflesqueak.model.CompiledCodeObject; import de.hpi.swa.trufflesqueak.model.NativeObject; @@ -205,17 +201,7 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me if (nodeFactory != null) { return createNode(nodeFactory, location, numReceiverAndArguments); } else { - // Missing implementation by SqueakFFIPrims - // FFIPlatformDescription class>>#currentPluginVersion - if (moduleName.equals("SqueakFFIPrims")) { - return null; - } - try { - return PrimExternalCallNode.load(moduleName, functionName, numReceiverAndArguments); - } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException | UnsupportedTypeException e) { - assert false : e.getMessage(); - return null; - } + return PrimExternalCallNode.load(moduleName, functionName, numReceiverAndArguments); } } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index c0e2323ca..0ff345e8f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -171,15 +171,27 @@ public static Object invokeSignatureMethod(final SqueakImageContext context, fin } public static Object createClosure(final SqueakImageContext context, final Object executable, final String signature) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { - return invokeSignatureMethod(context, signature, "createClosure", executable); + throws UnsupportedTypeException { + try { + return invokeSignatureMethod(context, signature, "createClosure", executable); + } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException e) { + // should not happen + assert false : e.getMessage(); + return null; + } } public static Object loadMember(final SqueakImageContext context, final Object library, final String name, final String signature) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + throws UnknownIdentifierException { final InteropLibrary interopLibrary = getInteropLibrary(library); - final Object symbol = interopLibrary.readMember(library, name); - return invokeSignatureMethod(context, signature, "bind", symbol); + try { + final Object symbol = interopLibrary.readMember(library, name); + return invokeSignatureMethod(context, signature, "bind", symbol); + } catch (UnsupportedMessageException | UnsupportedTypeException | ArityException e) { + // should not happen + assert false : e.getMessage(); + return null; + } } public static InteropLibrary getInteropLibrary(final Object loadedLibrary) { From 7751b2812bd6e5931ed59df9beb2b42f1cdc7db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 15 Jan 2024 13:36:43 +0100 Subject: [PATCH 094/159] Optionally call initialiseModule --- .../nodes/plugins/ffi/PrimExternalCallNode.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index db97a55a2..28e3cd799 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -38,6 +38,18 @@ public static PrimExternalCallNode load(final String moduleName, final String fu final SqueakImageContext context = SqueakImageContext.getSlow(); final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> { final Object library = NFIUtils.loadLibrary(context, moduleName, ""); + try { + // TODO: also call shutdownModule():SINT64 at some point + final Object initialiseModuleSymbol = NFIUtils.loadMember(context, library, "initialiseModule", "():SINT64"); + final InteropLibrary initialiseModuleInteropLibrary = NFIUtils.getInteropLibrary(initialiseModuleSymbol); + initialiseModuleInteropLibrary.execute(initialiseModuleSymbol); + } catch (UnknownIdentifierException e) { + // module has no initializer, ignore + } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { + // should not happen + assert false : e.getMessage(); + return null; + } try { NFIUtils.loadMember(context, library, "setInterpreter", "(POINTER):SINT64"); } catch (UnknownIdentifierException e) { From 32620dbd2ed49bab7f41d5d77de9ab583be01f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Mon, 15 Jan 2024 13:37:00 +0100 Subject: [PATCH 095/159] Add TruffleBoundary to oopFor --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 0815eb26c..d81168c2b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -1,5 +1,6 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -161,6 +162,7 @@ private int addObjectToRegistry(final Object object) { return oop; } + @TruffleBoundary private int oopFor(final Object object) { int oop = objectRegistry.indexOf(object); if (oop < 0) { From 8d0979ab6f16059fdc0253df695f7263897c6a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 18 Jan 2024 11:14:08 +0100 Subject: [PATCH 096/159] Fix checked loading of setInterpreter --- .../plugins/ffi/PrimExternalCallNode.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 28e3cd799..f44acd1a0 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -1,6 +1,7 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; @@ -37,7 +38,19 @@ public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary mod public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) { final SqueakImageContext context = SqueakImageContext.getSlow(); final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> { - final Object library = NFIUtils.loadLibrary(context, moduleName, ""); + final Object library; + try { + library = NFIUtils.loadLibrary(context, moduleName, "{ setInterpreter(POINTER):SINT64; }"); + } catch (AbstractTruffleException e) { + if (e.getMessage().equals("Unknown identifier: setInterpreter")) { + // module has no setInterpreter, cannot be loaded + return null; + } + throw e; + } + if (library == null) { + return null; + } try { // TODO: also call shutdownModule():SINT64 at some point final Object initialiseModuleSymbol = NFIUtils.loadMember(context, library, "initialiseModule", "():SINT64"); @@ -50,12 +63,6 @@ public static PrimExternalCallNode load(final String moduleName, final String fu assert false : e.getMessage(); return null; } - try { - NFIUtils.loadMember(context, library, "setInterpreter", "(POINTER):SINT64"); - } catch (UnknownIdentifierException e) { - // module has no setInterpreter, cannot be loaded - return null; - } return library; }); if (moduleLibrary == null) { From 35d143a24addb10bcdd9d892294744f41835d644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 18 Jan 2024 11:14:38 +0100 Subject: [PATCH 097/159] Update TODOs --- .../trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index f44acd1a0..39d8a86ce 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -103,9 +103,7 @@ private Object doExternalCall(final MaterializedFrame frame) { // since the C code expects that. Therefore, we undo the decrement operation here. FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments); - // TODO: Only call when the plugin actually defines the function - // uuidPluginLibrary.invokeMember(uuidPlugin, "initialiseModule"); - + // TODO: can we only call this once? moduleInteropLibrary.invokeMember(moduleLibrary, "setInterpreter", InterpreterProxy.getPointer()); // return value is unused, the actual return value is pushed onto the stack (see below) From 36348afe0fd4df42a2614a99923bcf21571f9f8c Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sat, 20 Jan 2024 18:43:33 +0100 Subject: [PATCH 098/159] Utilize CompilerDirectives.shouldNotReachHere --- .../nodes/plugins/ffi/PrimExternalCallNode.java | 5 ++--- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 9 +++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 39d8a86ce..9ad443f00 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -1,5 +1,6 @@ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.MaterializedFrame; @@ -59,9 +60,7 @@ public static PrimExternalCallNode load(final String moduleName, final String fu } catch (UnknownIdentifierException e) { // module has no initializer, ignore } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { - // should not happen - assert false : e.getMessage(); - return null; + throw CompilerDirectives.shouldNotReachHere(e); } return library; }); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 0ff345e8f..b69d20d59 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,5 +1,6 @@ package de.hpi.swa.trufflesqueak.util; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.interop.ArityException; @@ -175,9 +176,7 @@ public static Object createClosure(final SqueakImageContext context, final Objec try { return invokeSignatureMethod(context, signature, "createClosure", executable); } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException e) { - // should not happen - assert false : e.getMessage(); - return null; + throw CompilerDirectives.shouldNotReachHere(e); } } @@ -188,9 +187,7 @@ public static Object loadMember(final SqueakImageContext context, final Object l final Object symbol = interopLibrary.readMember(library, name); return invokeSignatureMethod(context, signature, "bind", symbol); } catch (UnsupportedMessageException | UnsupportedTypeException | ArityException e) { - // should not happen - assert false : e.getMessage(); - return null; + throw CompilerDirectives.shouldNotReachHere(e); } } From 1b021d097452be6e819d29c352c691606cc915a9 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sat, 20 Jan 2024 18:46:45 +0100 Subject: [PATCH 099/159] Write out exceptions, add reminder to remove debug log --- .../trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 9ad443f00..9ab22d9d0 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -114,8 +114,8 @@ private Object doExternalCall(final MaterializedFrame frame) { final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); return returnValue; - } catch (Exception e) { - // for debugging purposes + } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException | UnsupportedTypeException e) { + // for debugging purposes TODO: remove me e.printStackTrace(System.err); throw PrimitiveFailed.GENERIC_ERROR; } finally { From 4f114abe91f845192ba4d4bbe5e2aaef2573af09 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sat, 20 Jan 2024 18:49:18 +0100 Subject: [PATCH 100/159] Remove never thrown exceptions --- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index b69d20d59..de5aab175 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -63,7 +63,7 @@ Object execute(final Object... arguments) { return executable.execute(arguments); } - public TruffleClosure createClosure(final SqueakImageContext context) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public TruffleClosure createClosure(final SqueakImageContext context) throws UnsupportedTypeException { return new TruffleClosure(context, this); } } @@ -75,7 +75,7 @@ public static class TruffleClosure implements TruffleObject { final Object closure; public TruffleClosure(final SqueakImageContext context, final TruffleExecutable executable) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + throws UnsupportedTypeException { this.executable = executable; this.closure = createClosure(context, executable, executable.nfiSignature); } From abfd2a967ab3cb76a40de0bd1f8437f5a575f67d Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sat, 20 Jan 2024 18:51:23 +0100 Subject: [PATCH 101/159] Suppress unchecked cast warning --- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index de5aab175..bc4d75e33 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -99,6 +99,7 @@ default Object execute(Object... arguments) { public interface TruffleFunction extends ITruffleExecutable { R run(T argument); + @SuppressWarnings("unchecked") default Object execute(Object... arguments) { assert arguments.length == 1; return run((T) arguments[0]); @@ -109,6 +110,7 @@ default Object execute(Object... arguments) { public interface TruffleBiFunction extends ITruffleExecutable { R run(S argument1, T argument2); + @SuppressWarnings("unchecked") default Object execute(Object... arguments) { assert arguments.length == 2; return run((S) arguments[0], (T) arguments[1]); @@ -119,6 +121,7 @@ default Object execute(Object... arguments) { public interface TruffleTriFunction extends ITruffleExecutable { R run(S argument1, T argument2, U argument3); + @SuppressWarnings("unchecked") default Object execute(Object... arguments) { assert arguments.length == 3; return run((S) arguments[0], (T) arguments[1], (U) arguments[2]); @@ -129,6 +132,7 @@ default Object execute(Object... arguments) { public interface TruffleQuadFunction extends ITruffleExecutable { R run(S argument1, T argument2, U argument3, V argument4); + @SuppressWarnings("unchecked") default Object execute(Object... arguments) { assert arguments.length == 4; return run((S) arguments[0], (T) arguments[1], (U) arguments[2], (V) arguments[3]); @@ -139,6 +143,7 @@ default Object execute(Object... arguments) { public interface TruffleQuintFunction extends ITruffleExecutable { R run(S argument1, T argument2, U argument3, V argument4, W argument5); + @SuppressWarnings("unchecked") default Object execute(Object... arguments) { assert arguments.length == 5; return run((S) arguments[0], (T) arguments[1], (U) arguments[2], (V) arguments[3], (W) arguments[4]); From 8b6652fc34ed2f441b08e61ae57806c7fd2fe455 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sun, 21 Jan 2024 19:47:24 +0100 Subject: [PATCH 102/159] Remove assignment to a non-final static field --- .../nodes/plugins/ffi/InterpreterProxy.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 35a96d39f..1021859a3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -43,7 +43,7 @@ public final class InterpreterProxy { // should not be local, as the references are needed to keep the native closures alive // since this class is a singleton, a private instance variable will suffice @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; - private static Object interpreterProxyPointer; + private final Object interpreterProxyPointer; /////////////////////// // INSTANCE CREATION // @@ -61,16 +61,14 @@ private InterpreterProxy(final SqueakImageContext context, final MaterializedFra closures[i] = executables[i].createClosure(context); } - if (interpreterProxyPointer == null) { - final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); - final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", - "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }"); - assert interpreterProxy != null : "InterpreterProxy module not found!"; + final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); + final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", + "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }"); + assert interpreterProxy != null : "InterpreterProxy module not found!"; - final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); - interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy, "createInterpreterProxy", (Object[]) closures); - } + final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); + interpreterProxyPointer = interpreterProxyLibrary.invokeMember( + interpreterProxy, "createInterpreterProxy", (Object[]) closures); } private TruffleExecutable[] getExecutables() { @@ -141,7 +139,7 @@ public static InterpreterProxy instanceFor(final SqueakImageContext context, fin /////////////////// public static Object getPointer() { - return interpreterProxyPointer; + return INSTANCE.interpreterProxyPointer; } public void postPrimitiveCleanups() { From ba761caa2439d66fa9b1a4e7bdf81f84733cde40 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sun, 21 Jan 2024 20:49:33 +0100 Subject: [PATCH 103/159] Remove unneeded supress --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 1021859a3..cb184ae2e 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -316,7 +316,6 @@ private long integerValueOf(final long oop) { return objectToLong(objectRegistryGet(oop)); } - @SuppressWarnings("unused") private NativeObjectStorage ioLoadFunctionFrom(final String functionName, final String moduleName) { /* TODO */ LogUtils.PRIMITIVES.severe(() -> "Missing implementation for ioLoadFunctionFrom"); From de36be429f54262e1ab3764db3e6a1b33414b65f Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sun, 21 Jan 2024 21:14:52 +0100 Subject: [PATCH 104/159] Adjust return value to match sqInt to java long --- .../nodes/plugins/ffi/InterpreterProxy.java | 102 +++++++++--------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index cb184ae2e..2bd728eb1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -205,6 +205,16 @@ private Object getObjectOnStack(final long reverseStackIndex) { return FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); } + private long returnVoid() { + // For functions that do not have a defined return value + return 0L; + } + + private long returnNull() { + // For functions that should return null (=0) + return 0L; + } + //////////////////////// // CONVERSION HELPERS // //////////////////////// @@ -239,37 +249,38 @@ private static Object objectAt0(final Object object, final long index) { // TYPE CHECK HELPERS // //////////////////////// - private int instanceOfCheck(final long oop, final Class klass) { + private long instanceOfCheck(final long oop, final Class klass) { final Object object = objectRegistryGet(oop); return klass.isInstance(object) ? 1 : 0; } - private int nativeObjectCheck(final long oop, final Predicate predicate) { + private long nativeObjectCheck(final long oop, final Predicate predicate) { final Object object = objectRegistryGet(oop); if (object instanceof NativeObject nativeObject) { return predicate.test(nativeObject) ? 1 : 0; } - return 0; + return returnVoid(); } /////////////////////////////// // INTERPRETER PROXY METHODS // /////////////////////////////// - private int byteSizeOf(final long oop) { + private long byteSizeOf(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { return NativeObjectStorage.from(nativeObject).byteSizeOf(); } - return 0; + // type is not supported + return 0L; } - private int classString() { + private long classString() { return oopFor(context.byteStringClass); } - private int failed() { + private long failed() { // TODO: when changing primitiveFail to continue executing, properly implement this - return 0; + return returnNull(); } private long fetchIntegerofObject(final long fieldIndex, final long objectPointer) { @@ -297,7 +308,7 @@ private double floatValueOf(final long oop) { return objectToDouble(objectRegistryGet(oop)); } - private int instantiateClassindexableSize(final long classPointer, final long size) { + private long instantiateClassindexableSize(final long classPointer, final long size) { final Object object = objectRegistryGet(classPointer); if (object instanceof ClassObject classObject) { final AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, classObject, (int) size); @@ -305,7 +316,7 @@ private int instantiateClassindexableSize(final long classPointer, final long si } LogUtils.PRIMITIVES.severe(() -> "instantiateClassindexableSize called with non-ClassObject: " + object); primitiveFail(); - return 0; + return returnVoid(); } private long integerObjectOf(final long value) { @@ -326,7 +337,7 @@ private long isArray(final long oop) { return instanceOfCheck(oop, ArrayObject.class); } - private int isBytes(final long oop) { + private long isBytes(final long oop) { return nativeObjectCheck(oop, NativeObject::isByteType); } @@ -342,117 +353,108 @@ private long isPositiveMachineIntegerObject(final long oop) { if (object instanceof LargeIntegerObject largeInteger) { return largeInteger.isZeroOrPositive() && largeInteger.fitsIntoLong() ? 1 : 0; } - return 0; + return returnVoid(); } private long isWords(final long oop) { return nativeObjectCheck(oop, NativeObject::isLongType); } - @SuppressWarnings("unused") private long isWordsOrBytes(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for isWordsOrBytes"); - return 0; + return returnVoid(); } - private int majorVersion() { - return 1; + private long majorVersion() { + return 1L; } - private int methodArgumentCount() { + private long methodArgumentCount() { return numReceiverAndArguments - 1; } - @SuppressWarnings("unused") private long methodReturnInteger(final long integer) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnInteger"); - return 0; + return returnVoid(); } - @SuppressWarnings("unused") private long methodReturnReceiver() { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnReceiver"); - return 0; + return returnVoid(); } - @SuppressWarnings("unused") private long methodReturnValue(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnValue"); - return 0; + return returnVoid(); } - private int minorVersion() { + private long minorVersion() { return 17; } - private int nilObject() { + private long nilObject() { return oopFor(NilObject.SINGLETON); } - private int pop(final long nItems) { + private long pop(final long nItems) { setStackPointer(getStackPointer() - (int) nItems); - return 1; + return returnNull(); } - private int popthenPush(final long nItems, final long oop) { + private long popthenPush(final long nItems, final long oop) { pop(nItems); push(oop); - return 1; + return returnVoid(); } - @SuppressWarnings("unused") private long positive32BitIntegerFor(final long integerValue) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitIntegerFor"); - return 0; + return returnVoid(); } - @SuppressWarnings("unused") private long positive32BitValueOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitValueOf"); - return 0; + return returnVoid(); } - @SuppressWarnings("unused") private long positive64BitValueOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive64BitValueOf"); - return 0; + return returnVoid(); } - private int primitiveFail() { + private long primitiveFail() { // TODO: continue executing C code // TODO: adjust failed accordingly throw PrimitiveFailed.GENERIC_ERROR; } - @SuppressWarnings("unused") private long primitiveFailFor(final long reasonCode) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for primitiveFailFor"); - return 0; + return returnVoid(); } - private int push(final long oop) { + private long push(final long oop) { pushObject(objectRegistryGet(oop)); - return 1; + return returnVoid(); } - private int pushInteger(final long integerValue) { + private long pushInteger(final long integerValue) { pushObject(integerValue); - return 1; + return returnNull(); } - @SuppressWarnings("unused") private long showDisplayBitsLeftTopRightBottom(final long aForm, final long l, final long t, final long r, final long b) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for showDisplayBitsLeftTopRightBottom"); - return 0; + return returnVoid(); } private long signed32BitIntegerFor(final long integerValue) { @@ -463,22 +465,20 @@ private long signed32BitValueOf(final long oop) { return integerValueOf(oop); } - @SuppressWarnings("unused") private long slotSizeOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for slotSizeOf"); - return 0; + return returnVoid(); } private long stackIntegerValue(final long offset) { return objectToLong(getObjectOnStack(offset)); } - @SuppressWarnings("unused") private long stackObjectValue(final long offset) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for stackObjectValue"); - return 0; + return returnVoid(); } private long stackValue(final long offset) { @@ -489,17 +489,15 @@ private long statNumGCs() { return MiscUtils.getCollectionCount(); } - @SuppressWarnings("unused") private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for storeIntegerofObjectwithValue"); - return 0; + return returnVoid(); } - @SuppressWarnings("unused") private long storeLong32ofObjectwithValue(final long fieldIndex, final long oop, final long anInteger) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for storeLong32ofObjectwithValue"); - return 0; + return returnVoid(); } } From af2c6824b1c4f4b785f1f74279cb20dac29fc875 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Sun, 21 Jan 2024 21:17:32 +0100 Subject: [PATCH 105/159] Add primFailCode --- .../nodes/plugins/ffi/InterpreterProxy.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 2bd728eb1..848e78ab5 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -7,7 +7,6 @@ import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; -import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject; @@ -17,6 +16,7 @@ import de.hpi.swa.trufflesqueak.model.LargeIntegerObject; import de.hpi.swa.trufflesqueak.model.NativeObject; import de.hpi.swa.trufflesqueak.model.NilObject; +import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.ERROR_TABLE; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; @@ -38,13 +38,18 @@ public final class InterpreterProxy { private final SqueakImageContext context; private MaterializedFrame frame; private int numReceiverAndArguments; - private final ArrayList objectRegistry = new ArrayList<>(); private final ArrayList postPrimitiveCleanups = new ArrayList<>(); // should not be local, as the references are needed to keep the native closures alive // since this class is a singleton, a private instance variable will suffice @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; private final Object interpreterProxyPointer; + /////////////////////////// + // INTERPRETER VARIABLES // + /////////////////////////// + private final ArrayList objectRegistry = new ArrayList<>(); + private long primFailCode = 0; + /////////////////////// // INSTANCE CREATION // /////////////////////// @@ -430,15 +435,12 @@ private long positive64BitValueOf(final long oop) { } private long primitiveFail() { - // TODO: continue executing C code - // TODO: adjust failed accordingly - throw PrimitiveFailed.GENERIC_ERROR; + return primitiveFailFor(ERROR_TABLE.GENERIC_ERROR.ordinal()); } private long primitiveFailFor(final long reasonCode) { - /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for primitiveFailFor"); - return returnVoid(); + LogUtils.PRIMITIVES.info(() -> "Primitive failed with code: " + reasonCode); + return primFailCode = reasonCode; } private long push(final long oop) { From 42c7ed7b55f2d4fc0ebb901b0ae0163ce276f9b9 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 22 Jan 2024 20:07:55 +0100 Subject: [PATCH 106/159] Supress unused warning for linter on all interpreter proxy methods --- .../nodes/plugins/ffi/InterpreterProxy.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 848e78ab5..496c5cedf 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -271,6 +271,7 @@ private long nativeObjectCheck(final long oop, final Predicate pre // INTERPRETER PROXY METHODS // /////////////////////////////// + @SuppressWarnings("unused") private long byteSizeOf(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { return NativeObjectStorage.from(nativeObject).byteSizeOf(); @@ -279,27 +280,33 @@ private long byteSizeOf(final long oop) { return 0L; } + @SuppressWarnings("unused") private long classString() { return oopFor(context.byteStringClass); } + @SuppressWarnings("unused") private long failed() { // TODO: when changing primitiveFail to continue executing, properly implement this return returnNull(); } + @SuppressWarnings("unused") private long fetchIntegerofObject(final long fieldIndex, final long objectPointer) { return objectToLong(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); } + @SuppressWarnings("unused") private long fetchLong32ofObject(final long fieldIndex, final long oop) { return fetchIntegerofObject(fieldIndex, oop); } + @SuppressWarnings("unused") private long fetchPointerofObject(final long index, final long oop) { return oopFor(objectAt0(objectRegistryGet(oop), index)); } + @SuppressWarnings("unused") private NativeObjectStorage firstIndexableField(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { final NativeObjectStorage storage = NativeObjectStorage.from(nativeObject); @@ -309,10 +316,12 @@ private NativeObjectStorage firstIndexableField(final long oop) { return null; } + @SuppressWarnings("unused") private double floatValueOf(final long oop) { return objectToDouble(objectRegistryGet(oop)); } + @SuppressWarnings("unused") private long instantiateClassindexableSize(final long classPointer, final long size) { final Object object = objectRegistryGet(classPointer); if (object instanceof ClassObject classObject) { @@ -324,32 +333,39 @@ private long instantiateClassindexableSize(final long classPointer, final long s return returnVoid(); } + @SuppressWarnings("unused") private long integerObjectOf(final long value) { return oopFor(value); } + @SuppressWarnings("unused") private long integerValueOf(final long oop) { return objectToLong(objectRegistryGet(oop)); } + @SuppressWarnings("unused") private NativeObjectStorage ioLoadFunctionFrom(final String functionName, final String moduleName) { /* TODO */ LogUtils.PRIMITIVES.severe(() -> "Missing implementation for ioLoadFunctionFrom"); return null; } + @SuppressWarnings("unused") private long isArray(final long oop) { return instanceOfCheck(oop, ArrayObject.class); } + @SuppressWarnings("unused") private long isBytes(final long oop) { return nativeObjectCheck(oop, NativeObject::isByteType); } + @SuppressWarnings("unused") private long isPointers(final long oop) { return instanceOfCheck(oop, AbstractPointersObject.class); } + @SuppressWarnings("unused") private long isPositiveMachineIntegerObject(final long oop) { final Object object = objectRegistryGet(oop); if (object instanceof Long integer) { @@ -361,142 +377,170 @@ private long isPositiveMachineIntegerObject(final long oop) { return returnVoid(); } + @SuppressWarnings("unused") private long isWords(final long oop) { return nativeObjectCheck(oop, NativeObject::isLongType); } + @SuppressWarnings("unused") private long isWordsOrBytes(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for isWordsOrBytes"); return returnVoid(); } + @SuppressWarnings("unused") private long majorVersion() { return 1L; } + @SuppressWarnings("unused") private long methodArgumentCount() { return numReceiverAndArguments - 1; } + @SuppressWarnings("unused") private long methodReturnInteger(final long integer) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnInteger"); return returnVoid(); } + @SuppressWarnings("unused") private long methodReturnReceiver() { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnReceiver"); return returnVoid(); } + @SuppressWarnings("unused") private long methodReturnValue(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnValue"); return returnVoid(); } + @SuppressWarnings("unused") private long minorVersion() { return 17; } + @SuppressWarnings("unused") private long nilObject() { return oopFor(NilObject.SINGLETON); } + @SuppressWarnings("unused") private long pop(final long nItems) { setStackPointer(getStackPointer() - (int) nItems); return returnNull(); } + @SuppressWarnings("unused") private long popthenPush(final long nItems, final long oop) { pop(nItems); push(oop); return returnVoid(); } + @SuppressWarnings("unused") private long positive32BitIntegerFor(final long integerValue) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitIntegerFor"); return returnVoid(); } + @SuppressWarnings("unused") private long positive32BitValueOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitValueOf"); return returnVoid(); } + @SuppressWarnings("unused") private long positive64BitValueOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive64BitValueOf"); return returnVoid(); } + @SuppressWarnings("unused") private long primitiveFail() { return primitiveFailFor(ERROR_TABLE.GENERIC_ERROR.ordinal()); } + @SuppressWarnings("unused") private long primitiveFailFor(final long reasonCode) { LogUtils.PRIMITIVES.info(() -> "Primitive failed with code: " + reasonCode); return primFailCode = reasonCode; } + @SuppressWarnings("unused") private long push(final long oop) { pushObject(objectRegistryGet(oop)); return returnVoid(); } + @SuppressWarnings("unused") private long pushInteger(final long integerValue) { pushObject(integerValue); return returnNull(); } + @SuppressWarnings("unused") private long showDisplayBitsLeftTopRightBottom(final long aForm, final long l, final long t, final long r, final long b) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for showDisplayBitsLeftTopRightBottom"); return returnVoid(); } + @SuppressWarnings("unused") private long signed32BitIntegerFor(final long integerValue) { return integerObjectOf(integerValue); } + @SuppressWarnings("unused") private long signed32BitValueOf(final long oop) { return integerValueOf(oop); } + @SuppressWarnings("unused") private long slotSizeOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for slotSizeOf"); return returnVoid(); } + @SuppressWarnings("unused") private long stackIntegerValue(final long offset) { return objectToLong(getObjectOnStack(offset)); } + @SuppressWarnings("unused") private long stackObjectValue(final long offset) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for stackObjectValue"); return returnVoid(); } + @SuppressWarnings("unused") private long stackValue(final long offset) { return oopFor(getObjectOnStack(offset)); } + @SuppressWarnings("unused") private long statNumGCs() { return MiscUtils.getCollectionCount(); } + @SuppressWarnings("unused") private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for storeIntegerofObjectwithValue"); return returnVoid(); } + @SuppressWarnings("unused") private long storeLong32ofObjectwithValue(final long fieldIndex, final long oop, final long anInteger) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for storeLong32ofObjectwithValue"); From 510bf0b6fcc73494a0417d078a1d8bc96df41767 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 22 Jan 2024 20:15:44 +0100 Subject: [PATCH 107/159] Return current primFailCode --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 496c5cedf..00140cd15 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -48,7 +48,7 @@ public final class InterpreterProxy { // INTERPRETER VARIABLES // /////////////////////////// private final ArrayList objectRegistry = new ArrayList<>(); - private long primFailCode = 0; + private long primFailCode; /////////////////////// // INSTANCE CREATION // @@ -287,8 +287,7 @@ private long classString() { @SuppressWarnings("unused") private long failed() { - // TODO: when changing primitiveFail to continue executing, properly implement this - return returnNull(); + return primFailCode; } @SuppressWarnings("unused") From 9ed2ab15c3cefeee539d73aa21d40454f492fb6d Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 22 Jan 2024 20:18:37 +0100 Subject: [PATCH 108/159] Fail correctly --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 00140cd15..09a990594 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -230,7 +230,7 @@ private long objectToLong(final Object object) { } LogUtils.PRIMITIVES.severe(() -> "Object to long called with non-Long: " + object); primitiveFail(); - return 0; + return returnNull(); } private double objectToDouble(final Object object) { @@ -239,7 +239,7 @@ private double objectToDouble(final Object object) { } LogUtils.PRIMITIVES.severe(() -> "Object to long called with non-FloatObject: " + object); primitiveFail(); - return 0; + return returnNull(); } /////////////////////// @@ -276,7 +276,8 @@ private long byteSizeOf(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { return NativeObjectStorage.from(nativeObject).byteSizeOf(); } - // type is not supported + // type is not supported (yet) + primitiveFail(); return 0L; } From 8320f67f78cf64138d3689ffbe6f7960d98c1977 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 22 Jan 2024 20:19:06 +0100 Subject: [PATCH 109/159] Compare and return long value --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 09a990594..1e839d1b1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -369,10 +369,10 @@ private long isPointers(final long oop) { private long isPositiveMachineIntegerObject(final long oop) { final Object object = objectRegistryGet(oop); if (object instanceof Long integer) { - return integer >= 0 ? 1 : 0; + return integer >= 0L ? 1L : 0L; } if (object instanceof LargeIntegerObject largeInteger) { - return largeInteger.isZeroOrPositive() && largeInteger.fitsIntoLong() ? 1 : 0; + return largeInteger.isZeroOrPositive() && largeInteger.fitsIntoLong() ? 1L : 0L; } return returnVoid(); } From aa365c56118d51780e1b744e6e8f88ac8531adb9 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Tue, 23 Jan 2024 00:27:42 +0100 Subject: [PATCH 110/159] Call setInterpreter just once --- .../nodes/plugins/ffi/PrimExternalCallNode.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 9ab22d9d0..e5d5921f3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -34,6 +34,7 @@ public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary mod this.functionSymbol = functionSymbol; this.functionInteropLibrary = functionInteropLibrary; this.numReceiverAndArguments = numReceiverAndArguments; + setInterpreter(); } public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) { @@ -79,6 +80,15 @@ public static PrimExternalCallNode load(final String moduleName, final String fu } } + private void setInterpreter() { + try { + InterpreterProxy.instanceFor(getContext(), null, 0); + moduleInteropLibrary.invokeMember(moduleLibrary, "setInterpreter", InterpreterProxy.getPointer()); + } catch (UnsupportedMessageException | ArityException | UnsupportedTypeException | UnknownIdentifierException e) { + throw CompilerDirectives.shouldNotReachHere(e); + } + } + @Override public Object execute(final VirtualFrame frame) { return doExternalCall(frame.materialize()); @@ -102,9 +112,6 @@ private Object doExternalCall(final MaterializedFrame frame) { // since the C code expects that. Therefore, we undo the decrement operation here. FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) + numReceiverAndArguments); - // TODO: can we only call this once? - moduleInteropLibrary.invokeMember(moduleLibrary, "setInterpreter", InterpreterProxy.getPointer()); - // return value is unused, the actual return value is pushed onto the stack (see below) functionInteropLibrary.execute(functionSymbol); From 705e2547e766d4fcaf5cd3209fcd2d5f20d668d9 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Tue, 23 Jan 2024 13:34:22 +0100 Subject: [PATCH 111/159] Declare as static --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 1e839d1b1..28d80c0e3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -210,12 +210,12 @@ private Object getObjectOnStack(final long reverseStackIndex) { return FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); } - private long returnVoid() { + private static long returnVoid() { // For functions that do not have a defined return value return 0L; } - private long returnNull() { + private static long returnNull() { // For functions that should return null (=0) return 0L; } From fa31696b8177c9ab6f42ace40e50602c4f452eae Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 24 Jan 2024 16:18:57 +0100 Subject: [PATCH 112/159] Mark arguments as final [ci skip] --- .../de/hpi/swa/trufflesqueak/util/NFIUtils.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index bc4d75e33..e4495e87f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -82,14 +82,14 @@ public TruffleClosure(final SqueakImageContext context, final TruffleExecutable } public interface ITruffleExecutable { - Object execute(Object... arguments); + Object execute(final Object... arguments); } @FunctionalInterface public interface TruffleSupplier extends ITruffleExecutable { R run(); - default Object execute(Object... arguments) { + default Object execute(final Object... arguments) { assert arguments.length == 0; return run(); } @@ -100,7 +100,7 @@ public interface TruffleFunction extends ITruffleExecutable { R run(T argument); @SuppressWarnings("unchecked") - default Object execute(Object... arguments) { + default Object execute(final Object... arguments) { assert arguments.length == 1; return run((T) arguments[0]); } @@ -111,7 +111,7 @@ public interface TruffleBiFunction extends ITruffleExecutable { R run(S argument1, T argument2); @SuppressWarnings("unchecked") - default Object execute(Object... arguments) { + default Object execute(final Object... arguments) { assert arguments.length == 2; return run((S) arguments[0], (T) arguments[1]); } @@ -122,7 +122,7 @@ public interface TruffleTriFunction extends ITruffleExecutable { R run(S argument1, T argument2, U argument3); @SuppressWarnings("unchecked") - default Object execute(Object... arguments) { + default Object execute(final Object... arguments) { assert arguments.length == 3; return run((S) arguments[0], (T) arguments[1], (U) arguments[2]); } @@ -133,7 +133,7 @@ public interface TruffleQuadFunction extends ITruffleExecutable { R run(S argument1, T argument2, U argument3, V argument4); @SuppressWarnings("unchecked") - default Object execute(Object... arguments) { + default Object execute(final Object... arguments) { assert arguments.length == 4; return run((S) arguments[0], (T) arguments[1], (U) arguments[2], (V) arguments[3]); } @@ -144,7 +144,7 @@ public interface TruffleQuintFunction extends ITruffleExecutab R run(S argument1, T argument2, U argument3, V argument4, W argument5); @SuppressWarnings("unchecked") - default Object execute(Object... arguments) { + default Object execute(final Object... arguments) { assert arguments.length == 5; return run((S) arguments[0], (T) arguments[1], (U) arguments[2], (V) arguments[3], (W) arguments[4]); } From 56c1c52bc56bde9d80ec55b12e652d24ec363b1f Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 24 Jan 2024 16:36:16 +0100 Subject: [PATCH 113/159] Add missing copyright [ci skip] --- src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt | 7 +++++++ .../include/sqMemoryAccess.h | 6 ++++++ .../include/sqVirtualMachine.h | 6 ++++++ .../include/vmCallback.h | 6 ++++++ .../src/InterpreterProxy.c | 6 ++++++ .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 ++++++ .../nodes/plugins/ffi/PrimExternalCallNode.java | 6 ++++++ .../nodes/plugins/ffi/wrappers/ByteStorage.java | 6 ++++++ .../nodes/plugins/ffi/wrappers/IntStorage.java | 6 ++++++ .../nodes/plugins/ffi/wrappers/LongStorage.java | 6 ++++++ .../nodes/plugins/ffi/wrappers/NativeObjectStorage.java | 6 ++++++ .../nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java | 6 ++++++ .../nodes/plugins/ffi/wrappers/ShortStorage.java | 6 ++++++ .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 6 ++++++ 14 files changed, 85 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt b/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt index 3aafb8798..993aaf970 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt @@ -1,3 +1,10 @@ +# +# Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute +# Copyright (c) 2021-2024 Oracle and/or its affiliates +# +# Licensed under the MIT License. +# + cmake_minimum_required(VERSION 3.22) project(de.hpi.swa.trufflesqueak.ffi.native) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h index 43f3e4de1..4da4d9fdb 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ #define SIZEOF_VOID_P 8 //////////// from here on: copied from diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h index 63143b70c..887184062 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ #include "vmCallback.h" //////////// from here on: copied from diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h index b7bde95f0..de591fc9d 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ #include #include "sqMemoryAccess.h" diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index 9d5eb4338..fdd2f3344 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ #include #define VM_PROXY_MAJOR 1 diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 28d80c0e3..6676bb71f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index e5d5921f3..482734d49 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; import com.oracle.truffle.api.CompilerDirectives; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index d1541f9be..aecff1068 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index 9d316ea16..ae0e41755 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index 4653e0963..dd7d361ae 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index e6fe49e65..1c429073a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; import com.oracle.truffle.api.interop.InteropLibrary; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java index 79c85fb8d..afbde5f70 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; public interface PostPrimitiveCleanup { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index a1beb3000..74d5630bb 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; import de.hpi.swa.trufflesqueak.util.UnsafeUtils; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index e4495e87f..e6df3a3f9 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2021-2024 Oracle and/or its affiliates + * + * Licensed under the MIT License. + */ package de.hpi.swa.trufflesqueak.util; import com.oracle.truffle.api.CompilerDirectives; From 3b1b75207c5ece816db2ab21841ce6944e88ed37 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 24 Jan 2024 18:53:40 +0100 Subject: [PATCH 114/159] Remove TruffleBoundary --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 2 -- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 6676bb71f..fda8e68ce 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -6,7 +6,6 @@ */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -172,7 +171,6 @@ private int addObjectToRegistry(final Object object) { return oop; } - @TruffleBoundary private int oopFor(final Object object) { int oop = objectRegistry.indexOf(object); if (oop < 0) { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index e6df3a3f9..f4929f93d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -7,7 +7,6 @@ package de.hpi.swa.trufflesqueak.util; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -64,7 +63,6 @@ boolean isExecutable() { } @ExportMessage - @TruffleBoundary Object execute(final Object... arguments) { return executable.execute(arguments); } From 78a3191f2ab5fb1fd26962d0cbe3003b3f32947c Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 13:48:10 +0100 Subject: [PATCH 115/159] Check for identity instead of equality should fix native builds --- .../nodes/plugins/ffi/InterpreterProxy.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index fda8e68ce..315bdce6d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -172,11 +172,12 @@ private int addObjectToRegistry(final Object object) { } private int oopFor(final Object object) { - int oop = objectRegistry.indexOf(object); - if (oop < 0) { - oop = addObjectToRegistry(object); + for (int oop = 0; oop < objectRegistry.size(); oop++) { + if (objectRegistry.get(oop) == object) { + return oop; + } } - return oop; + return addObjectToRegistry(object); } /////////////////// From 69db916254c9e770a63d5f8910c46522088a7ac9 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 13:49:12 +0100 Subject: [PATCH 116/159] Remove redundant final --- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index f4929f93d..25adaa4ca 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -86,7 +86,7 @@ public TruffleClosure(final SqueakImageContext context, final TruffleExecutable } public interface ITruffleExecutable { - Object execute(final Object... arguments); + Object execute(Object... arguments); } @FunctionalInterface From 7d2ae5ed805294b88c16a6106a8d51b5bebce72b Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 14:54:08 +0100 Subject: [PATCH 117/159] Throw if failed --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 2 +- .../trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 315bdce6d..4a8cb5e3b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -292,7 +292,7 @@ private long classString() { } @SuppressWarnings("unused") - private long failed() { + public long failed() { return primFailCode; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 482734d49..368c2131c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -126,6 +126,10 @@ private Object doExternalCall(final MaterializedFrame frame) { // (AbstractSendNode.executeVoid). Pop the return value and return it. final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); + long failReason = interpreterProxy.failed(); + if (failReason != 0) { + throw PrimitiveFailed.andTransferToInterpreter((int) failReason); + } return returnValue; } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException | UnsupportedTypeException e) { // for debugging purposes TODO: remove me From cf16be3644df79c1e9aecd730598aaa8bbb4f75d Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 14:55:01 +0100 Subject: [PATCH 118/159] Try to load external plugin before Java plugin --- .../nodes/primitives/PrimitiveNodeFactory.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index ee78e31f7..df02df67e 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -34,6 +34,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.SecurityPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.SoundCodecPrims; import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakFFIPrims; +import de.hpi.swa.trufflesqueak.nodes.plugins.SqueakSSL; import de.hpi.swa.trufflesqueak.nodes.plugins.TruffleSqueakPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.UUIDPlugin; import de.hpi.swa.trufflesqueak.nodes.plugins.UnixOSProcessPlugin; @@ -110,7 +111,7 @@ public final class PrimitiveNodeFactory { new SocketPlugin(), new SoundCodecPrims(), new SqueakFFIPrims(), - // new SqueakSSL(), + new SqueakSSL(), new UUIDPlugin(), new ZipPlugin(), OS.isWindows() ? new Win32OSProcessPlugin() : new UnixOSProcessPlugin()}; @@ -191,6 +192,12 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me } final String moduleName = values[NAMED_PRIMITIVE_MODULE_NAME_INDEX] instanceof final NativeObject m ? m.asStringUnsafe() : NULL_MODULE_NAME; final String functionName = ((NativeObject) values[NAMED_PRIMITIVE_FUNCTION_NAME_INDEX]).asStringUnsafe(); + + final PrimExternalCallNode externalCallNode = PrimExternalCallNode.load(moduleName, functionName, numReceiverAndArguments); + if ( externalCallNode != null) { + return externalCallNode; + } + if (numReceiverAndArguments == 1) { // Check for singleton plugin primitive final AbstractPrimitiveNode primitiveNode = SINGLETON_PLUGIN_MAP.get(moduleName, EconomicMap.emptyMap()).get(functionName); if (primitiveNode != null) { @@ -200,9 +207,8 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me final NodeFactory nodeFactory = PLUGIN_MAP.get(moduleName, EconomicMap.emptyMap()).get(functionName, EconomicMap.emptyMap()).get(numReceiverAndArguments); if (nodeFactory != null) { return createNode(nodeFactory, location, numReceiverAndArguments); - } else { - return PrimExternalCallNode.load(moduleName, functionName, numReceiverAndArguments); } + return null; } private static boolean isLoadInstVar(final int primitiveIndex) { From cdc55a28efcc14434fc5f6a032fbc50da0b11f34 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 15:28:41 +0100 Subject: [PATCH 119/159] Check for plugins without 'lib' prefix for compatibility with opensmalltalk artifacts --- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 25adaa4ca..31e8d519b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -161,9 +161,15 @@ public static Object executeNFI(final SqueakImageContext context, final String n public static Object loadLibrary(final SqueakImageContext context, final String moduleName, final String boundSymbols) { final String libName = System.mapLibraryName(moduleName); - final TruffleFile libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName); + TruffleFile libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName); if (!libPath.exists()) { - return null; + // to preserve compatibility with plugins from opensmalltalk, also check without 'lib' prefix + if (libName.startsWith("lib")) { + libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName.replace("lib", "")); + if (!libPath.exists()) { + return null; + } + } } final String nfiCode = "load \"" + libPath.getAbsoluteFile().getPath() + "\" " + boundSymbols; return executeNFI(context, nfiCode); From 1d8682e66c6026a52b4e58946a5ba7927fdb60e2 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 16:24:56 +0100 Subject: [PATCH 120/159] Re-add @TruffleBoundary for closure execute --- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 31e8d519b..137390fda 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -7,6 +7,7 @@ package de.hpi.swa.trufflesqueak.util; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -63,6 +64,7 @@ boolean isExecutable() { } @ExportMessage + @TruffleBoundary Object execute(final Object... arguments) { return executable.execute(arguments); } From 4169948e2f5a47645cddfd5de70d0c7528d5c2c8 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 17:39:56 +0100 Subject: [PATCH 121/159] Lint [ci skip] --- .../trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java | 2 +- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java index df02df67e..4891a0c07 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/primitives/PrimitiveNodeFactory.java @@ -194,7 +194,7 @@ public static AbstractPrimitiveNode getOrCreateNamed(final CompiledCodeObject me final String functionName = ((NativeObject) values[NAMED_PRIMITIVE_FUNCTION_NAME_INDEX]).asStringUnsafe(); final PrimExternalCallNode externalCallNode = PrimExternalCallNode.load(moduleName, functionName, numReceiverAndArguments); - if ( externalCallNode != null) { + if (externalCallNode != null) { return externalCallNode; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 137390fda..847359b3c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -165,7 +165,8 @@ public static Object loadLibrary(final SqueakImageContext context, final String final String libName = System.mapLibraryName(moduleName); TruffleFile libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName); if (!libPath.exists()) { - // to preserve compatibility with plugins from opensmalltalk, also check without 'lib' prefix + // to preserve compatibility with plugins from opensmalltalk, also check without 'lib' + // prefix if (libName.startsWith("lib")) { libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName.replace("lib", "")); if (!libPath.exists()) { From 51ff0628073e7c547b42f9c5705505e2ce4536a0 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 18:26:47 +0100 Subject: [PATCH 122/159] Fix null libraries not entered into map --- .../nodes/plugins/ffi/PrimExternalCallNode.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 368c2131c..eb9779842 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -46,6 +46,10 @@ public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary mod public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) { final SqueakImageContext context = SqueakImageContext.getSlow(); final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> { + if (loadedLibraries.containsKey(moduleName)) { + // if moduleName was associated with null + return null; + } final Object library; try { library = NFIUtils.loadLibrary(context, moduleName, "{ setInterpreter(POINTER):SINT64; }"); @@ -71,6 +75,8 @@ public static PrimExternalCallNode load(final String moduleName, final String fu } return library; }); + // computeIfAbsent would not put null value + loadedLibraries.putIfAbsent(moduleName, moduleLibrary); if (moduleLibrary == null) { // module not found return null; From 026c166689bddb79057700190696ddd7e555da74 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 18:32:57 +0100 Subject: [PATCH 123/159] Add missing return --- .../src/de/hpi/swa/trufflesqueak/util/NFIUtils.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 847359b3c..8d4ba92e9 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -172,6 +172,8 @@ public static Object loadLibrary(final SqueakImageContext context, final String if (!libPath.exists()) { return null; } + } else { + return null; } } final String nfiCode = "load \"" + libPath.getAbsoluteFile().getPath() + "\" " + boundSymbols; From 230be16112b651f8bb3a1fcdbd1ad4b237125b8e Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Mon, 5 Feb 2024 18:34:05 +0100 Subject: [PATCH 124/159] Declare final --- .../trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index eb9779842..0b4c5c069 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -132,7 +132,7 @@ private Object doExternalCall(final MaterializedFrame frame) { // (AbstractSendNode.executeVoid). Pop the return value and return it. final Object returnValue = FrameAccess.getStackValue(frame, FrameAccess.getStackPointer(frame) - 1, FrameAccess.getNumArguments(frame)); FrameAccess.setStackPointer(frame, FrameAccess.getStackPointer(frame) - 1); - long failReason = interpreterProxy.failed(); + final long failReason = interpreterProxy.failed(); if (failReason != 0) { throw PrimitiveFailed.andTransferToInterpreter((int) failReason); } From 65776c95c0ff4cbd3549012be8cb1d823b9af1dc Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 7 Feb 2024 18:21:31 +0100 Subject: [PATCH 125/159] Change replace to substring --- .../de/hpi/swa/trufflesqueak/util/NFIUtils.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 8d4ba92e9..87bb154e1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -165,14 +165,13 @@ public static Object loadLibrary(final SqueakImageContext context, final String final String libName = System.mapLibraryName(moduleName); TruffleFile libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName); if (!libPath.exists()) { - // to preserve compatibility with plugins from opensmalltalk, also check without 'lib' - // prefix - if (libName.startsWith("lib")) { - libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName.replace("lib", "")); - if (!libPath.exists()) { - return null; - } - } else { + // to preserve compatibility with plugins from opensmalltalk + // also check without 'lib' prefix + if (!libName.startsWith("lib")) { + return null; + } + libPath = context.getHomePath().resolve("lib" + File.separatorChar + libName.substring(3)); + if (!libPath.exists()) { return null; } } From c3e179df326329b706ccc8bdd2f3e3dc2047aa7b Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Wed, 7 Feb 2024 18:23:58 +0100 Subject: [PATCH 126/159] Remove printStackTrace --- .../trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 0b4c5c069..d29a52cfb 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -138,9 +138,7 @@ private Object doExternalCall(final MaterializedFrame frame) { } return returnValue; } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException | UnsupportedTypeException e) { - // for debugging purposes TODO: remove me - e.printStackTrace(System.err); - throw PrimitiveFailed.GENERIC_ERROR; + throw CompilerDirectives.shouldNotReachHere(e); } finally { if (interpreterProxy != null) { interpreterProxy.postPrimitiveCleanups(); From c0d7c283854260e8a23d6dddccca45c623afab2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 20:26:39 +0100 Subject: [PATCH 127/159] Extract returnBoolean --- .../nodes/plugins/ffi/InterpreterProxy.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 4a8cb5e3b..34f73555f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -215,6 +215,10 @@ private Object getObjectOnStack(final long reverseStackIndex) { return FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); } + private static long returnBoolean(final boolean bool) { + return bool ? 1L : 0L; + } + private static long returnVoid() { // For functions that do not have a defined return value return 0L; @@ -261,13 +265,13 @@ private static Object objectAt0(final Object object, final long index) { private long instanceOfCheck(final long oop, final Class klass) { final Object object = objectRegistryGet(oop); - return klass.isInstance(object) ? 1 : 0; + return returnBoolean(klass.isInstance(object)); } private long nativeObjectCheck(final long oop, final Predicate predicate) { final Object object = objectRegistryGet(oop); if (object instanceof NativeObject nativeObject) { - return predicate.test(nativeObject) ? 1 : 0; + return returnBoolean(predicate.test(nativeObject)); } return returnVoid(); } @@ -374,12 +378,12 @@ private long isPointers(final long oop) { private long isPositiveMachineIntegerObject(final long oop) { final Object object = objectRegistryGet(oop); if (object instanceof Long integer) { - return integer >= 0L ? 1L : 0L; + return returnBoolean(integer >= 0L); } if (object instanceof LargeIntegerObject largeInteger) { - return largeInteger.isZeroOrPositive() && largeInteger.fitsIntoLong() ? 1L : 0L; + return returnBoolean(largeInteger.isZeroOrPositive() && largeInteger.fitsIntoLong()); } - return returnVoid(); + return returnBoolean(false); } @SuppressWarnings("unused") From fd4b58a5e11ac4f50ef0e301257098e61633000e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 20:29:11 +0100 Subject: [PATCH 128/159] Use InterpreterProxy terminology in conversion helpers --- .../nodes/plugins/ffi/InterpreterProxy.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 34f73555f..a71b74553 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -233,7 +233,7 @@ private static long returnNull() { // CONVERSION HELPERS // //////////////////////// - private long objectToLong(final Object object) { + private long objectToInteger(final Object object) { if (object instanceof Long longObject) { return longObject; } @@ -242,7 +242,7 @@ private long objectToLong(final Object object) { return returnNull(); } - private double objectToDouble(final Object object) { + private double objectToFloat(final Object object) { if (object instanceof FloatObject floatObject) { return floatObject.getValue(); } @@ -302,7 +302,7 @@ public long failed() { @SuppressWarnings("unused") private long fetchIntegerofObject(final long fieldIndex, final long objectPointer) { - return objectToLong(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); + return objectToInteger(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); } @SuppressWarnings("unused") @@ -327,7 +327,7 @@ private NativeObjectStorage firstIndexableField(final long oop) { @SuppressWarnings("unused") private double floatValueOf(final long oop) { - return objectToDouble(objectRegistryGet(oop)); + return objectToFloat(objectRegistryGet(oop)); } @SuppressWarnings("unused") @@ -349,7 +349,7 @@ private long integerObjectOf(final long value) { @SuppressWarnings("unused") private long integerValueOf(final long oop) { - return objectToLong(objectRegistryGet(oop)); + return objectToInteger(objectRegistryGet(oop)); } @SuppressWarnings("unused") @@ -522,7 +522,7 @@ private long slotSizeOf(final long oop) { @SuppressWarnings("unused") private long stackIntegerValue(final long offset) { - return objectToLong(getObjectOnStack(offset)); + return objectToInteger(getObjectOnStack(offset)); } @SuppressWarnings("unused") From 37c34112cd76514e1f28aa63ed2c07a5b15b5855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 20:30:22 +0100 Subject: [PATCH 129/159] Add explicit integerToObject conversion --- .../nodes/plugins/ffi/InterpreterProxy.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index a71b74553..4b0d06d6c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -251,6 +251,10 @@ private double objectToFloat(final Object object) { return returnNull(); } + private static Object integerToObject(final long integer) { + return integer; // encoded as Long in TruffleSqueak + } + /////////////////////// // ACCESSING HELPERS // /////////////////////// @@ -344,7 +348,7 @@ private long instantiateClassindexableSize(final long classPointer, final long s @SuppressWarnings("unused") private long integerObjectOf(final long value) { - return oopFor(value); + return oopFor(integerToObject(value)); } @SuppressWarnings("unused") @@ -491,8 +495,8 @@ private long push(final long oop) { } @SuppressWarnings("unused") - private long pushInteger(final long integerValue) { - pushObject(integerValue); + private long pushInteger(final long integer) { + pushObject(integerToObject(integer)); return returnNull(); } From 41c9d84ed1c34b8ac8010584798763f76e7cf45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 20:34:04 +0100 Subject: [PATCH 130/159] Add hasSucceeded helper --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 4b0d06d6c..7321c6588 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -157,6 +157,10 @@ public void postPrimitiveCleanups() { postPrimitiveCleanups.clear(); } + private boolean hasSucceeded() { + return failed() == 0; + } + ///////////////////////////// // OBJECT REGISTRY HELPERS // ///////////////////////////// From 8f906eed5fbc720b1f37f10073d758cb4d9c2647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 20:37:31 +0100 Subject: [PATCH 131/159] Implement methodReturn* --- .../nodes/plugins/ffi/InterpreterProxy.java | 52 +++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 7321c6588..fea6e8034 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -219,6 +219,13 @@ private Object getObjectOnStack(final long reverseStackIndex) { return FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); } + private long methodReturnObject(Object object) { + assert hasSucceeded(); + pop(numReceiverAndArguments); + pushObject(object); + return 0; + } + private static long returnBoolean(final boolean bool) { return bool ? 1L : 0L; } @@ -259,6 +266,22 @@ private static Object integerToObject(final long integer) { return integer; // encoded as Long in TruffleSqueak } + private static Object boolToObject(final boolean bool) { + return BooleanObject.wrap(bool); + } + + private static Object boolToObject(final long bool) { + return boolToObject(bool != 0); + } + + private Object floatToObject(final double value) { + return new FloatObject(context, value); + } + + private Object stringToObject(final String string) { + return context.asByteString(string); + } + /////////////////////// // ACCESSING HELPERS // /////////////////////// @@ -416,25 +439,36 @@ private long methodArgumentCount() { return numReceiverAndArguments - 1; } + @SuppressWarnings("unused") + private long methodReturnBool(final long bool) { + return methodReturnObject(boolToObject(bool)); + } + + @SuppressWarnings("unused") + private long methodReturnFloat(final double value) { + return methodReturnObject(floatToObject(value)); + } + @SuppressWarnings("unused") private long methodReturnInteger(final long integer) { - /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnInteger"); - return returnVoid(); + return methodReturnObject(integerToObject(integer)); } @SuppressWarnings("unused") private long methodReturnReceiver() { - /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnReceiver"); - return returnVoid(); + assert hasSucceeded(); + pop(numReceiverAndArguments - 1); // leave the receiver on the stack + return 0; + } + + @SuppressWarnings("unused") + private long methodReturnString(final String string) { + return methodReturnObject(stringToObject(string)); } @SuppressWarnings("unused") private long methodReturnValue(final long oop) { - /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for methodReturnValue"); - return returnVoid(); + return methodReturnObject(objectRegistryGet(oop)); } @SuppressWarnings("unused") From ea6ce0a49b5ea2e368075346bb56574570468172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 20:37:55 +0100 Subject: [PATCH 132/159] Implement isIntegerObject --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index fea6e8034..5bef0664d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -400,6 +400,11 @@ private long isBytes(final long oop) { return nativeObjectCheck(oop, NativeObject::isByteType); } + @SuppressWarnings("unused") + private long isIntegerObject(final long oop) { + return returnBoolean(objectRegistryGet(oop) instanceof Long); + } + @SuppressWarnings("unused") private long isPointers(final long oop) { return instanceOfCheck(oop, AbstractPointersObject.class); From 212b4e2878d4e1303f6969497b87298ec13ab0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 20:38:10 +0100 Subject: [PATCH 133/159] Implement stringForCString --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 5bef0664d..45ae87b84 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -589,6 +589,11 @@ private long statNumGCs() { return MiscUtils.getCollectionCount(); } + @SuppressWarnings("unused") + private long stringForCString(final String string) { + return oopFor(stringForCString(string)); + } + @SuppressWarnings("unused") private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { /* TODO */ From 782e45dc1f1dc918a5be9fdadb414706ba16964f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 21:04:58 +0100 Subject: [PATCH 134/159] Add missing import for BooleanObject --- .../swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 45ae87b84..3a1b7eb4f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -16,6 +16,7 @@ import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject; import de.hpi.swa.trufflesqueak.model.ArrayObject; +import de.hpi.swa.trufflesqueak.model.BooleanObject; import de.hpi.swa.trufflesqueak.model.ClassObject; import de.hpi.swa.trufflesqueak.model.FloatObject; import de.hpi.swa.trufflesqueak.model.LargeIntegerObject; From 77c1ccb30337ba4e0672f64dc07cb70316f7dff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 21:05:51 +0100 Subject: [PATCH 135/159] Implement class* --- .../nodes/plugins/ffi/InterpreterProxy.java | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 3a1b7eb4f..0825d6e35 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -162,6 +162,10 @@ private boolean hasSucceeded() { return failed() == 0; } + private Object global(final String name) { + return context.lookup(name); + } + ///////////////////////////// // OBJECT REGISTRY HELPERS // ///////////////////////////// @@ -322,11 +326,121 @@ private long byteSizeOf(final long oop) { return 0L; } + @SuppressWarnings("unused") + private long classAlien() { + return oopFor(global("Alien")); + } + + @SuppressWarnings("unused") + private long classArray() { + return oopFor(context.arrayClass); + } + + @SuppressWarnings("unused") + private long classBitmap() { + return oopFor(context.bitmapClass); + } + + @SuppressWarnings("unused") + private long classByteArray() { + return oopFor(context.byteArrayClass); + } + + @SuppressWarnings("unused") + private long classCharacter() { + return oopFor(context.characterClass); + } + + @SuppressWarnings("unused") + private long classDoubleByteArray() { + return oopFor(global("DoubleByteArray")); + } + + @SuppressWarnings("unused") + private long classDoubleWordArray() { + return oopFor(global("DoubleWordArray")); + } + + @SuppressWarnings("unused") + private long classExternalAddress() { + return oopFor(global("ExternalAddress")); + } + + @SuppressWarnings("unused") + private long classExternalData() { + return oopFor(global("ExternalData")); + } + + @SuppressWarnings("unused") + private long classExternalFunction() { + return oopFor(global("ExternalFunction")); + } + + @SuppressWarnings("unused") + private long classExternalLibrary() { + return oopFor(global("ExternalLibrary")); + } + + @SuppressWarnings("unused") + private long classExternalStructure() { + return oopFor(global("ExternalStructure")); + } + + @SuppressWarnings("unused") + private long classFloat() { + return oopFor(context.floatClass); + } + + @SuppressWarnings("unused") + private long classFloat32Array() { + return oopFor(global("FloatArray")); + } + + @SuppressWarnings("unused") + private long classFloat64Array() { + return oopFor(global("Float64Array")); + } + + @SuppressWarnings("unused") + private long classLargeNegativeInteger() { + return oopFor(context.largeNegativeIntegerClass); + } + + @SuppressWarnings("unused") + private long classLargePositiveIntegerClass() { + return oopFor(context.largePositiveIntegerClass); + } + + @SuppressWarnings("unused") + private long classPoint() { + return oopFor(context.pointClass); + } + + @SuppressWarnings("unused") + private long classSemaphore() { + return oopFor(context.semaphoreClass); + } + + @SuppressWarnings("unused") + private long classSmallInteger() { + return oopFor(context.smallIntegerClass); + } + @SuppressWarnings("unused") private long classString() { return oopFor(context.byteStringClass); } + @SuppressWarnings("unused") + private long classUnsafeAlien() { + return oopFor(global("UnsafeAlien")); + } + + @SuppressWarnings("unused") + private long classWordArray() { + return oopFor(global("WordArray")); + } + @SuppressWarnings("unused") public long failed() { return primFailCode; From 7a0476a36a43dc533732c9de3a4a358b3364efa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Thu, 8 Feb 2024 21:13:58 +0100 Subject: [PATCH 136/159] Implement booleanValueOf --- .../nodes/plugins/ffi/InterpreterProxy.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 0825d6e35..5e282788b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -316,6 +316,16 @@ private long nativeObjectCheck(final long oop, final Predicate pre // INTERPRETER PROXY METHODS // /////////////////////////////// + @SuppressWarnings("unused") + private long booleanValueOf(final long oop) { + Object object = objectRegistryGet(oop); + if (object instanceof Boolean bool) { + return returnBoolean(bool); + } + primitiveFail(); + return returnNull(); + } + @SuppressWarnings("unused") private long byteSizeOf(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { From 7b680ae3f611a7e248754f621d9340393765ba48 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 08:22:27 +0100 Subject: [PATCH 137/159] Correct copyright headers and import order --- .../CMakeLists.txt | 4 ++-- .../include/sqMemoryAccess.h | 4 ++-- .../include/sqVirtualMachine.h | 4 ++-- .../include/vmCallback.h | 4 ++-- .../src/InterpreterProxy.c | 4 ++-- .../nodes/plugins/ffi/InterpreterProxy.java | 15 ++++++++------- .../nodes/plugins/ffi/PrimExternalCallNode.java | 11 ++++++----- .../nodes/plugins/ffi/wrappers/ByteStorage.java | 4 ++-- .../nodes/plugins/ffi/wrappers/IntStorage.java | 4 ++-- .../nodes/plugins/ffi/wrappers/LongStorage.java | 4 ++-- .../plugins/ffi/wrappers/NativeObjectStorage.java | 5 +++-- .../ffi/wrappers/PostPrimitiveCleanup.java | 4 ++-- .../nodes/plugins/ffi/wrappers/ShortStorage.java | 4 ++-- .../de/hpi/swa/trufflesqueak/util/NFIUtils.java | 9 +++++---- 14 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt b/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt index 993aaf970..52fb00c83 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/CMakeLists.txt @@ -1,6 +1,6 @@ # -# Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute -# Copyright (c) 2021-2024 Oracle and/or its affiliates +# Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute +# Copyright (c) 2023-2024 Oracle and/or its affiliates # # Licensed under the MIT License. # diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h index 4da4d9fdb..f6f0d5b5b 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqMemoryAccess.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h index 887184062..db2e7e43d 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/sqVirtualMachine.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h index de591fc9d..f7bb67f5f 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/include/vmCallback.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index fdd2f3344..2067580a0 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 5e282788b..65c6be52a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -1,17 +1,23 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.function.Predicate; +import java.util.stream.Collectors; + import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; + import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject; @@ -34,11 +40,6 @@ import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleClosure; import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.function.Predicate; -import java.util.stream.Collectors; - public final class InterpreterProxy { private static InterpreterProxy INSTANCE; private final SqueakImageContext context; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index d29a52cfb..d0bddbd24 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -1,11 +1,14 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; +import java.util.HashMap; +import java.util.Map; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.exception.AbstractTruffleException; @@ -16,15 +19,13 @@ import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; + import de.hpi.swa.trufflesqueak.exceptions.PrimitiveFailed; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.nodes.primitives.AbstractPrimitiveNode; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.NFIUtils; -import java.util.HashMap; -import java.util.Map; - public final class PrimExternalCallNode extends AbstractPrimitiveNode { private final Object moduleLibrary; private final InteropLibrary moduleInteropLibrary; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index aecff1068..6795079aa 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index ae0e41755..b154363fd 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index dd7d361ae..8184c1615 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index 1c429073a..641d63b9d 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ @@ -10,6 +10,7 @@ import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; + import de.hpi.swa.trufflesqueak.model.NativeObject; @ExportLibrary(InteropLibrary.class) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java index afbde5f70..66a02938e 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 74d5630bb..9323e7ad8 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java index 87bb154e1..9ba2e8d8b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/util/NFIUtils.java @@ -1,11 +1,13 @@ /* - * Copyright (c) 2017-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2021-2024 Oracle and/or its affiliates + * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute + * Copyright (c) 2023-2024 Oracle and/or its affiliates * * Licensed under the MIT License. */ package de.hpi.swa.trufflesqueak.util; +import java.io.File; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.TruffleFile; @@ -18,9 +20,8 @@ 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.image.SqueakImageContext; -import java.io.File; +import de.hpi.swa.trufflesqueak.image.SqueakImageContext; public final class NFIUtils { From e86fa72951a54ba7c12ad8e3791fbc00e8092681 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 08:47:10 +0100 Subject: [PATCH 138/159] Register unused but implemented proxy methods --- .../src/InterpreterProxy.c | 56 ++++++++++- .../nodes/plugins/ffi/InterpreterProxy.java | 99 +++++-------------- 2 files changed, 82 insertions(+), 73 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index 2067580a0..a4efcb452 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -13,8 +13,31 @@ VirtualMachine* createInterpreterProxy( // sorted alphabetically, identical to getExecutables in // src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java + sqInt (*booleanValueOf)(sqInt oop), sqInt (*byteSizeOf)(sqInt oop), + sqInt (*classAlien)(void), + sqInt (*classArray)(void), + sqInt (*classBitmap)(void), + sqInt (*classByteArray)(void), + sqInt (*classCharacter)(void), + sqInt (*classDoubleByteArray)(void), + sqInt (*classDoubleWordArray)(void), + sqInt (*classExternalAddress)(void), + sqInt (*classExternalData)(void), + sqInt (*classExternalFunction)(void), + sqInt (*classExternalLibrary)(void), + sqInt (*classExternalStructure)(void), + sqInt (*classFloat)(void), + sqInt (*classFloat32Array)(void), + sqInt (*classFloat64Array)(void), + sqInt (*classLargeNegativeInteger)(void), + sqInt (*classLargePositiveInteger)(void), + sqInt (*classPoint)(void), + sqInt (*classSemaphore)(void), + sqInt (*classSmallInteger)(void), sqInt (*classString)(void), + sqInt (*classUnsafeAlien)(void), + sqInt (*classWordArray)(void), sqInt (*failed)(void), sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer), sqInt (*fetchLong32ofObject)(sqInt fieldIndex, sqInt oop), @@ -27,14 +50,18 @@ VirtualMachine* createInterpreterProxy( void *(*ioLoadFunctionFrom)(char *functionName, char *moduleName), sqInt (*isArray)(sqInt oop), sqInt (*isBytes)(sqInt oop), + sqInt (*isIntegerObject)(sqInt oop), sqInt (*isPointers)(sqInt oop), sqInt (*isPositiveMachineIntegerObject)(sqInt oop), sqInt (*isWords)(sqInt oop), sqInt (*isWordsOrBytes)(sqInt oop), sqInt (*majorVersion)(void), sqInt (*methodArgumentCount)(void), - sqInt (*methodReturnInteger)(sqInt integer), + sqInt (*methodReturnBool)(sqInt value), + sqInt (*methodReturnFloat)(double value), + sqInt (*methodReturnInteger)(sqInt value), sqInt (*methodReturnReceiver)(void), + sqInt (*methodReturnString)(char *value), sqInt (*methodReturnValue)(sqInt oop), sqInt (*minorVersion)(void), sqInt (*nilObject)(void), @@ -59,8 +86,31 @@ VirtualMachine* createInterpreterProxy( ) { VirtualMachine* interpreterProxy = (VirtualMachine*)calloc(1, sizeof(VirtualMachine)); + interpreterProxy->booleanValueOf = booleanValueOf; interpreterProxy->byteSizeOf = byteSizeOf; + interpreterProxy->classAlien = classAlien; + interpreterProxy->classArray = classArray; + interpreterProxy->classBitmap = classBitmap; + interpreterProxy->classByteArray = classByteArray; + interpreterProxy->classCharacter = classCharacter; + interpreterProxy->classDoubleByteArray = classDoubleByteArray; + interpreterProxy->classDoubleWordArray = classDoubleWordArray; + interpreterProxy->classExternalAddress = classExternalAddress; + interpreterProxy->classExternalData = classExternalData; + interpreterProxy->classExternalFunction = classExternalFunction; + interpreterProxy->classExternalLibrary = classExternalLibrary; + interpreterProxy->classExternalStructure = classExternalStructure; + interpreterProxy->classFloat = classFloat; + interpreterProxy->classFloat32Array = classFloat32Array; + interpreterProxy->classFloat64Array = classFloat64Array; + interpreterProxy->classLargeNegativeInteger = classLargeNegativeInteger; + interpreterProxy->classLargePositiveInteger = classLargePositiveInteger; + interpreterProxy->classPoint = classPoint; + interpreterProxy->classSemaphore = classSemaphore; + interpreterProxy->classSmallInteger = classSmallInteger; interpreterProxy->classString = classString; + interpreterProxy->classUnsafeAlien = classUnsafeAlien; + interpreterProxy->classWordArray = classWordArray; interpreterProxy->failed = failed; interpreterProxy->fetchIntegerofObject = fetchIntegerofObject; interpreterProxy->fetchLong32ofObject = fetchLong32ofObject; @@ -73,14 +123,18 @@ VirtualMachine* createInterpreterProxy( interpreterProxy->ioLoadFunctionFrom = ioLoadFunctionFrom; interpreterProxy->isArray = isArray; interpreterProxy->isBytes = isBytes; + interpreterProxy->isIntegerObject = isIntegerObject; interpreterProxy->isPointers = isPointers; interpreterProxy->isPositiveMachineIntegerObject = isPositiveMachineIntegerObject; interpreterProxy->isWords = isWords; interpreterProxy->isWordsOrBytes = isWordsOrBytes; interpreterProxy->majorVersion = majorVersion; interpreterProxy->methodArgumentCount = methodArgumentCount; + interpreterProxy->methodReturnBool = methodReturnBool; + interpreterProxy->methodReturnFloat = methodReturnFloat; interpreterProxy->methodReturnInteger = methodReturnInteger; interpreterProxy->methodReturnReceiver = methodReturnReceiver; + interpreterProxy->methodReturnString = methodReturnString; interpreterProxy->methodReturnValue = methodReturnValue; interpreterProxy->minorVersion = minorVersion; interpreterProxy->nilObject = nilObject; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 65c6be52a..5e480621f 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -87,8 +87,31 @@ private TruffleExecutable[] getExecutables() { // sorted alphabetically, identical to createInterpreterProxy in // src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c return new TruffleExecutable[]{ + TruffleExecutable.wrap("(SINT64):SINT64", this::booleanValueOf), TruffleExecutable.wrap("(SINT64):SINT64", this::byteSizeOf), + TruffleExecutable.wrap("():SINT64", this::classAlien), + TruffleExecutable.wrap("():SINT64", this::classArray), + TruffleExecutable.wrap("():SINT64", this::classBitmap), + TruffleExecutable.wrap("():SINT64", this::classByteArray), + TruffleExecutable.wrap("():SINT64", this::classCharacter), + TruffleExecutable.wrap("():SINT64", this::classDoubleByteArray), + TruffleExecutable.wrap("():SINT64", this::classDoubleWordArray), + TruffleExecutable.wrap("():SINT64", this::classExternalAddress), + TruffleExecutable.wrap("():SINT64", this::classExternalData), + TruffleExecutable.wrap("():SINT64", this::classExternalFunction), + TruffleExecutable.wrap("():SINT64", this::classExternalLibrary), + TruffleExecutable.wrap("():SINT64", this::classExternalStructure), + TruffleExecutable.wrap("():SINT64", this::classFloat), + TruffleExecutable.wrap("():SINT64", this::classFloat32Array), + TruffleExecutable.wrap("():SINT64", this::classFloat64Array), + TruffleExecutable.wrap("():SINT64", this::classLargeNegativeInteger), + TruffleExecutable.wrap("():SINT64", this::classLargePositiveIntegerClass), + TruffleExecutable.wrap("():SINT64", this::classPoint), + TruffleExecutable.wrap("():SINT64", this::classSemaphore), + TruffleExecutable.wrap("():SINT64", this::classSmallInteger), TruffleExecutable.wrap("():SINT64", this::classString), + TruffleExecutable.wrap("():SINT64", this::classUnsafeAlien), + TruffleExecutable.wrap("():SINT64", this::classWordArray), TruffleExecutable.wrap("():SINT64", this::failed), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchIntegerofObject), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchLong32ofObject), @@ -101,14 +124,18 @@ private TruffleExecutable[] getExecutables() { TruffleExecutable.wrap("(STRING,STRING):POINTER", this::ioLoadFunctionFrom), TruffleExecutable.wrap("(SINT64):SINT64", this::isArray), TruffleExecutable.wrap("(SINT64):SINT64", this::isBytes), + TruffleExecutable.wrap("(SINT64):SINT64", this::isIntegerObject), TruffleExecutable.wrap("(SINT64):SINT64", this::isPointers), TruffleExecutable.wrap("(SINT64):SINT64", this::isPositiveMachineIntegerObject), TruffleExecutable.wrap("(SINT64):SINT64", this::isWords), TruffleExecutable.wrap("(SINT64):SINT64", this::isWordsOrBytes), TruffleExecutable.wrap("():SINT64", this::majorVersion), TruffleExecutable.wrap("():SINT64", this::methodArgumentCount), + TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnBool), + TruffleExecutable.wrap("(DOUBLE):SINT64", this::methodReturnFloat), TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnInteger), TruffleExecutable.wrap("():SINT64", this::methodReturnReceiver), + TruffleExecutable.wrap("(STRING):SINT64", this::methodReturnString), TruffleExecutable.wrap("(SINT64):SINT64", this::methodReturnValue), TruffleExecutable.wrap("():SINT64", this::minorVersion), TruffleExecutable.wrap("():SINT64", this::nilObject), @@ -317,7 +344,6 @@ private long nativeObjectCheck(final long oop, final Predicate pre // INTERPRETER PROXY METHODS // /////////////////////////////// - @SuppressWarnings("unused") private long booleanValueOf(final long oop) { Object object = objectRegistryGet(oop); if (object instanceof Boolean bool) { @@ -327,7 +353,6 @@ private long booleanValueOf(final long oop) { return returnNull(); } - @SuppressWarnings("unused") private long byteSizeOf(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { return NativeObjectStorage.from(nativeObject).byteSizeOf(); @@ -337,142 +362,114 @@ private long byteSizeOf(final long oop) { return 0L; } - @SuppressWarnings("unused") private long classAlien() { return oopFor(global("Alien")); } - @SuppressWarnings("unused") private long classArray() { return oopFor(context.arrayClass); } - @SuppressWarnings("unused") private long classBitmap() { return oopFor(context.bitmapClass); } - @SuppressWarnings("unused") private long classByteArray() { return oopFor(context.byteArrayClass); } - @SuppressWarnings("unused") private long classCharacter() { return oopFor(context.characterClass); } - @SuppressWarnings("unused") private long classDoubleByteArray() { return oopFor(global("DoubleByteArray")); } - @SuppressWarnings("unused") private long classDoubleWordArray() { return oopFor(global("DoubleWordArray")); } - @SuppressWarnings("unused") private long classExternalAddress() { return oopFor(global("ExternalAddress")); } - @SuppressWarnings("unused") private long classExternalData() { return oopFor(global("ExternalData")); } - @SuppressWarnings("unused") private long classExternalFunction() { return oopFor(global("ExternalFunction")); } - @SuppressWarnings("unused") private long classExternalLibrary() { return oopFor(global("ExternalLibrary")); } - @SuppressWarnings("unused") private long classExternalStructure() { return oopFor(global("ExternalStructure")); } - @SuppressWarnings("unused") private long classFloat() { return oopFor(context.floatClass); } - @SuppressWarnings("unused") private long classFloat32Array() { return oopFor(global("FloatArray")); } - @SuppressWarnings("unused") private long classFloat64Array() { return oopFor(global("Float64Array")); } - @SuppressWarnings("unused") private long classLargeNegativeInteger() { return oopFor(context.largeNegativeIntegerClass); } - @SuppressWarnings("unused") private long classLargePositiveIntegerClass() { return oopFor(context.largePositiveIntegerClass); } - @SuppressWarnings("unused") private long classPoint() { return oopFor(context.pointClass); } - @SuppressWarnings("unused") private long classSemaphore() { return oopFor(context.semaphoreClass); } - @SuppressWarnings("unused") private long classSmallInteger() { return oopFor(context.smallIntegerClass); } - @SuppressWarnings("unused") private long classString() { return oopFor(context.byteStringClass); } - @SuppressWarnings("unused") private long classUnsafeAlien() { return oopFor(global("UnsafeAlien")); } - @SuppressWarnings("unused") private long classWordArray() { return oopFor(global("WordArray")); } - @SuppressWarnings("unused") public long failed() { return primFailCode; } - @SuppressWarnings("unused") private long fetchIntegerofObject(final long fieldIndex, final long objectPointer) { return objectToInteger(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); } - @SuppressWarnings("unused") private long fetchLong32ofObject(final long fieldIndex, final long oop) { return fetchIntegerofObject(fieldIndex, oop); } - @SuppressWarnings("unused") private long fetchPointerofObject(final long index, final long oop) { return oopFor(objectAt0(objectRegistryGet(oop), index)); } - @SuppressWarnings("unused") private NativeObjectStorage firstIndexableField(final long oop) { if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { final NativeObjectStorage storage = NativeObjectStorage.from(nativeObject); @@ -482,12 +479,10 @@ private NativeObjectStorage firstIndexableField(final long oop) { return null; } - @SuppressWarnings("unused") private double floatValueOf(final long oop) { return objectToFloat(objectRegistryGet(oop)); } - @SuppressWarnings("unused") private long instantiateClassindexableSize(final long classPointer, final long size) { final Object object = objectRegistryGet(classPointer); if (object instanceof ClassObject classObject) { @@ -499,44 +494,36 @@ private long instantiateClassindexableSize(final long classPointer, final long s return returnVoid(); } - @SuppressWarnings("unused") private long integerObjectOf(final long value) { return oopFor(integerToObject(value)); } - @SuppressWarnings("unused") private long integerValueOf(final long oop) { return objectToInteger(objectRegistryGet(oop)); } - @SuppressWarnings("unused") private NativeObjectStorage ioLoadFunctionFrom(final String functionName, final String moduleName) { /* TODO */ LogUtils.PRIMITIVES.severe(() -> "Missing implementation for ioLoadFunctionFrom"); return null; } - @SuppressWarnings("unused") private long isArray(final long oop) { return instanceOfCheck(oop, ArrayObject.class); } - @SuppressWarnings("unused") private long isBytes(final long oop) { return nativeObjectCheck(oop, NativeObject::isByteType); } - @SuppressWarnings("unused") private long isIntegerObject(final long oop) { return returnBoolean(objectRegistryGet(oop) instanceof Long); } - @SuppressWarnings("unused") private long isPointers(final long oop) { return instanceOfCheck(oop, AbstractPointersObject.class); } - @SuppressWarnings("unused") private long isPositiveMachineIntegerObject(final long oop) { final Object object = objectRegistryGet(oop); if (object instanceof Long integer) { @@ -548,186 +535,154 @@ private long isPositiveMachineIntegerObject(final long oop) { return returnBoolean(false); } - @SuppressWarnings("unused") private long isWords(final long oop) { return nativeObjectCheck(oop, NativeObject::isLongType); } - @SuppressWarnings("unused") private long isWordsOrBytes(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for isWordsOrBytes"); return returnVoid(); } - @SuppressWarnings("unused") private long majorVersion() { return 1L; } - @SuppressWarnings("unused") private long methodArgumentCount() { return numReceiverAndArguments - 1; } - @SuppressWarnings("unused") private long methodReturnBool(final long bool) { return methodReturnObject(boolToObject(bool)); } - @SuppressWarnings("unused") private long methodReturnFloat(final double value) { return methodReturnObject(floatToObject(value)); } - @SuppressWarnings("unused") private long methodReturnInteger(final long integer) { return methodReturnObject(integerToObject(integer)); } - @SuppressWarnings("unused") private long methodReturnReceiver() { assert hasSucceeded(); pop(numReceiverAndArguments - 1); // leave the receiver on the stack return 0; } - @SuppressWarnings("unused") private long methodReturnString(final String string) { return methodReturnObject(stringToObject(string)); } - @SuppressWarnings("unused") private long methodReturnValue(final long oop) { return methodReturnObject(objectRegistryGet(oop)); } - @SuppressWarnings("unused") private long minorVersion() { return 17; } - @SuppressWarnings("unused") private long nilObject() { return oopFor(NilObject.SINGLETON); } - @SuppressWarnings("unused") private long pop(final long nItems) { setStackPointer(getStackPointer() - (int) nItems); return returnNull(); } - @SuppressWarnings("unused") private long popthenPush(final long nItems, final long oop) { pop(nItems); push(oop); return returnVoid(); } - @SuppressWarnings("unused") private long positive32BitIntegerFor(final long integerValue) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitIntegerFor"); return returnVoid(); } - @SuppressWarnings("unused") private long positive32BitValueOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitValueOf"); return returnVoid(); } - @SuppressWarnings("unused") private long positive64BitValueOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for positive64BitValueOf"); return returnVoid(); } - @SuppressWarnings("unused") private long primitiveFail() { return primitiveFailFor(ERROR_TABLE.GENERIC_ERROR.ordinal()); } - @SuppressWarnings("unused") private long primitiveFailFor(final long reasonCode) { LogUtils.PRIMITIVES.info(() -> "Primitive failed with code: " + reasonCode); return primFailCode = reasonCode; } - @SuppressWarnings("unused") private long push(final long oop) { pushObject(objectRegistryGet(oop)); return returnVoid(); } - @SuppressWarnings("unused") private long pushInteger(final long integer) { pushObject(integerToObject(integer)); return returnNull(); } - @SuppressWarnings("unused") private long showDisplayBitsLeftTopRightBottom(final long aForm, final long l, final long t, final long r, final long b) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for showDisplayBitsLeftTopRightBottom"); return returnVoid(); } - @SuppressWarnings("unused") private long signed32BitIntegerFor(final long integerValue) { return integerObjectOf(integerValue); } - @SuppressWarnings("unused") private long signed32BitValueOf(final long oop) { return integerValueOf(oop); } - @SuppressWarnings("unused") private long slotSizeOf(final long oop) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for slotSizeOf"); return returnVoid(); } - @SuppressWarnings("unused") private long stackIntegerValue(final long offset) { return objectToInteger(getObjectOnStack(offset)); } - @SuppressWarnings("unused") private long stackObjectValue(final long offset) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for stackObjectValue"); return returnVoid(); } - @SuppressWarnings("unused") private long stackValue(final long offset) { return oopFor(getObjectOnStack(offset)); } - @SuppressWarnings("unused") private long statNumGCs() { return MiscUtils.getCollectionCount(); } - @SuppressWarnings("unused") private long stringForCString(final String string) { return oopFor(stringForCString(string)); } - @SuppressWarnings("unused") private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for storeIntegerofObjectwithValue"); return returnVoid(); } - @SuppressWarnings("unused") private long storeLong32ofObjectwithValue(final long fieldIndex, final long oop, final long anInteger) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for storeLong32ofObjectwithValue"); From 4c7338d9d3170922c4208a8c06e37e640c09d1bc Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 08:58:00 +0100 Subject: [PATCH 139/159] Minor cleanups --- .../nodes/plugins/ffi/InterpreterProxy.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 5e480621f..508023a93 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -252,7 +252,7 @@ private Object getObjectOnStack(final long reverseStackIndex) { return FrameAccess.getStackValue(frame, stackIndex, FrameAccess.getNumArguments(frame)); } - private long methodReturnObject(Object object) { + private long methodReturnObject(final Object object) { assert hasSucceeded(); pop(numReceiverAndArguments); pushObject(object); @@ -345,7 +345,7 @@ private long nativeObjectCheck(final long oop, final Predicate pre /////////////////////////////// private long booleanValueOf(final long oop) { - Object object = objectRegistryGet(oop); + final Object object = objectRegistryGet(oop); if (object instanceof Boolean bool) { return returnBoolean(bool); } @@ -594,7 +594,7 @@ private long pop(final long nItems) { private long popthenPush(final long nItems, final long oop) { pop(nItems); - push(oop); + pushObject(objectRegistryGet(oop)); return returnVoid(); } @@ -625,11 +625,6 @@ private long primitiveFailFor(final long reasonCode) { return primFailCode = reasonCode; } - private long push(final long oop) { - pushObject(objectRegistryGet(oop)); - return returnVoid(); - } - private long pushInteger(final long integer) { pushObject(integerToObject(integer)); return returnNull(); @@ -673,10 +668,6 @@ private long statNumGCs() { return MiscUtils.getCollectionCount(); } - private long stringForCString(final String string) { - return oopFor(stringForCString(string)); - } - private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { /* TODO */ LogUtils.PRIMITIVES.warning("Missing implementation for storeIntegerofObjectwithValue"); From d88f0f9bcb5425b25db2275052bd79df43bbaba8 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 09:57:33 +0100 Subject: [PATCH 140/159] Add false and true object for LocalePlugin --- .../src/InterpreterProxy.c | 6 +++++- .../nodes/plugins/ffi/InterpreterProxy.java | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index a4efcb452..71320af5c 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -39,6 +39,7 @@ VirtualMachine* createInterpreterProxy( sqInt (*classUnsafeAlien)(void), sqInt (*classWordArray)(void), sqInt (*failed)(void), + sqInt (*falseObject)(void), sqInt (*fetchIntegerofObject)(sqInt fieldIndex, sqInt objectPointer), sqInt (*fetchLong32ofObject)(sqInt fieldIndex, sqInt oop), sqInt (*fetchPointerofObject)(sqInt index, sqInt oop), @@ -82,7 +83,8 @@ VirtualMachine* createInterpreterProxy( sqInt (*stackValue)(sqInt offset), sqInt (*statNumGCs)(void), sqInt (*storeIntegerofObjectwithValue)(sqInt index, sqInt oop, sqInt integer), - usqInt (*storeLong32ofObjectwithValue)(sqInt fieldIndex, sqInt oop, usqInt anInteger) + usqInt (*storeLong32ofObjectwithValue)(sqInt fieldIndex, sqInt oop, usqInt anInteger), + sqInt (*trueObject)(void) ) { VirtualMachine* interpreterProxy = (VirtualMachine*)calloc(1, sizeof(VirtualMachine)); @@ -112,6 +114,7 @@ VirtualMachine* createInterpreterProxy( interpreterProxy->classUnsafeAlien = classUnsafeAlien; interpreterProxy->classWordArray = classWordArray; interpreterProxy->failed = failed; + interpreterProxy->falseObject = falseObject; interpreterProxy->fetchIntegerofObject = fetchIntegerofObject; interpreterProxy->fetchLong32ofObject = fetchLong32ofObject; interpreterProxy->fetchPointerofObject = fetchPointerofObject; @@ -156,6 +159,7 @@ VirtualMachine* createInterpreterProxy( interpreterProxy->statNumGCs = statNumGCs; interpreterProxy->storeIntegerofObjectwithValue = storeIntegerofObjectwithValue; interpreterProxy->storeLong32ofObjectwithValue = storeLong32ofObjectwithValue; + interpreterProxy->trueObject = trueObject; return interpreterProxy; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 508023a93..f69bf35c6 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -113,6 +113,7 @@ private TruffleExecutable[] getExecutables() { TruffleExecutable.wrap("():SINT64", this::classUnsafeAlien), TruffleExecutable.wrap("():SINT64", this::classWordArray), TruffleExecutable.wrap("():SINT64", this::failed), + TruffleExecutable.wrap("():SINT64", this::falseObject), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchIntegerofObject), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchLong32ofObject), TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::fetchPointerofObject), @@ -157,6 +158,7 @@ private TruffleExecutable[] getExecutables() { TruffleExecutable.wrap("():SINT64", this::statNumGCs), TruffleExecutable.wrap("(SINT64,SINT64,SINT64):SINT64", this::storeIntegerofObjectwithValue), TruffleExecutable.wrap("(SINT64,SINT64,UINT64):UINT64", this::storeLong32ofObjectwithValue), + TruffleExecutable.wrap("():SINT64", this::trueObject), }; } @@ -583,10 +585,18 @@ private long minorVersion() { return 17; } + private long falseObject() { + return oopFor(BooleanObject.FALSE); + } + private long nilObject() { return oopFor(NilObject.SINGLETON); } + private long trueObject() { + return oopFor(BooleanObject.TRUE); + } + private long pop(final long nItems) { setStackPointer(getStackPointer() - (int) nItems); return returnNull(); From a6be20bd2b7912b04e420a1eaa79ac434d6f5607 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 10:31:35 +0100 Subject: [PATCH 141/159] Re-use plugins from OpenSmalltalkVM Initially, only SqueakSSL and LocalePlugin for Linux amd64/aarch64 and Windows amd64 are included. --- mx.trufflesqueak/suite.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/mx.trufflesqueak/suite.py b/mx.trufflesqueak/suite.py index a061166b1..8f785a18c 100644 --- a/mx.trufflesqueak/suite.py +++ b/mx.trufflesqueak/suite.py @@ -95,6 +95,30 @@ "sha1": "acd1c78c07e894647e8dcbd72c4fa9a136e20d6d", "licence": "LGPLv21", }, + "OSVM_PLUGINS": { + "baseurl": "https://github.com/hpi-swa/trufflesqueak/releases/download/23.1.0/osvm-plugins-202312181441", + "os_arch": { + "linux": { + "amd64": { + "urls": ["{baseurl}-linux-amd64.zip"], + "digest": "sha512:5e94f289e5e1c71772b3033fda31e637cdcbea17321f2a4448a6755dff6db2db210086cffc993320249bcb6a1df395c17a2a06aedc9636159623336ca92e8008", + }, + "aarch64": { + "urls" : ["{baseurl}-linux-aarch64.zip"], + "digest" : "sha512:b4801b2a442ca383c6d5718c5a085b1446e66010e73587f166ff2726d393ecc47d7a195bba9d586e7f6c40d587e9a89c874a39adb3f65e9633a12703b40268e9", + }, + }, + "windows": { + "amd64": { + "urls": ["{baseurl}-windows-amd64.zip"], + "digest": "sha512:10ec2b4b783bb83a814866ea237a424138802a99ee63b3cfbe2d2b2c6607e94ea000922f58f8a159108f66c0509764bc48b62885337d2a198534337eb2ed6f8e", + }, + }, + "": { + "": {"optional": True} + }, + }, + }, "TRUFFLE-ENTERPRISE": { "digest": "sha512:b883d3ead84778617f9b09edaa43634183f07cdc6ae0666cb2f4edabc52fca913138c4a7a8f9ada1adbd4a9bbe7d16fb4a1b3ceac13446f4e0c47f3d1a20469f", "maven": { @@ -301,7 +325,14 @@ "layout": { "LICENSE_TRUFFLESQUEAK.txt": "file:LICENSE", "README_TRUFFLESQUEAK.md": "file:README.md", - "lib/": "dependency:de.hpi.swa.trufflesqueak.ffi.native/*", + "lib/": [ + "dependency:de.hpi.swa.trufflesqueak.ffi.native/*", + { + "source_type": "extracted-dependency", + "dependency": "OSVM_PLUGINS", + "path": "*", + }, + ], }, "maven": False, }, From a59cd4f9bd839bc9c624b972e43aca54522936c4 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 11:47:19 +0100 Subject: [PATCH 142/159] Implement showDisplayBitsLeftTopRightBottom --- .../nodes/plugins/ffi/InterpreterProxy.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index f69bf35c6..37d32b6c8 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -19,6 +19,7 @@ import com.oracle.truffle.api.interop.UnsupportedTypeException; import de.hpi.swa.trufflesqueak.image.SqueakImageContext; +import de.hpi.swa.trufflesqueak.io.SqueakDisplay; import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; import de.hpi.swa.trufflesqueak.model.AbstractSqueakObject; import de.hpi.swa.trufflesqueak.model.ArrayObject; @@ -28,6 +29,7 @@ import de.hpi.swa.trufflesqueak.model.LargeIntegerObject; import de.hpi.swa.trufflesqueak.model.NativeObject; import de.hpi.swa.trufflesqueak.model.NilObject; +import de.hpi.swa.trufflesqueak.model.PointersObject; import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.ERROR_TABLE; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; @@ -640,9 +642,14 @@ private long pushInteger(final long integer) { return returnNull(); } - private long showDisplayBitsLeftTopRightBottom(final long aForm, final long l, final long t, final long r, final long b) { - /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for showDisplayBitsLeftTopRightBottom"); + private long showDisplayBitsLeftTopRightBottom(final long aFormOop, final long l, final long t, final long r, final long b) { + final Object aFormObject = objectRegistryGet(aFormOop); + if (aFormObject instanceof final PointersObject aForm) { + final SqueakDisplay display = context.getDisplay(); + if (aForm.isDisplay(context) && !display.getDeferUpdates()) { + display.showDisplayRect((int) l, (int) t, (int) r, (int) b); + } + } return returnVoid(); } From 4a95838cd3c7ce88bed0a879e49349dd3a03f2e9 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 11:47:30 +0100 Subject: [PATCH 143/159] Address ECJ warnings --- .../nodes/plugins/ffi/InterpreterProxy.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 37d32b6c8..aa87360e3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -508,7 +508,7 @@ private long integerValueOf(final long oop) { private NativeObjectStorage ioLoadFunctionFrom(final String functionName, final String moduleName) { /* TODO */ - LogUtils.PRIMITIVES.severe(() -> "Missing implementation for ioLoadFunctionFrom"); + LogUtils.PRIMITIVES.severe(() -> "Missing implementation for ioLoadFunctionFrom: %s>>%s".formatted(functionName, moduleName)); return null; } @@ -544,9 +544,7 @@ private long isWords(final long oop) { } private long isWordsOrBytes(final long oop) { - /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for isWordsOrBytes"); - return returnVoid(); + return nativeObjectCheck(oop, no -> no.isIntType() || no.isByteType()); } private long majorVersion() { @@ -612,19 +610,19 @@ private long popthenPush(final long nItems, final long oop) { private long positive32BitIntegerFor(final long integerValue) { /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitIntegerFor"); + LogUtils.PRIMITIVES.warning(() -> "Missing implementation for positive32BitIntegerFor: " + integerValue); return returnVoid(); } private long positive32BitValueOf(final long oop) { /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for positive32BitValueOf"); + LogUtils.PRIMITIVES.warning(() -> "Missing implementation for positive32BitValueOf: " + oop); return returnVoid(); } private long positive64BitValueOf(final long oop) { /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for positive64BitValueOf"); + LogUtils.PRIMITIVES.warning(() -> "Missing implementation for positive64BitValueOf: " + oop); return returnVoid(); } @@ -663,7 +661,7 @@ private long signed32BitValueOf(final long oop) { private long slotSizeOf(final long oop) { /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for slotSizeOf"); + LogUtils.PRIMITIVES.warning(() -> "Missing implementation for slotSizeOf: " + oop); return returnVoid(); } @@ -673,7 +671,7 @@ private long stackIntegerValue(final long offset) { private long stackObjectValue(final long offset) { /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for stackObjectValue"); + LogUtils.PRIMITIVES.warning(() -> "Missing implementation for stackObjectValue: " + offset); return returnVoid(); } @@ -687,13 +685,13 @@ private long statNumGCs() { private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for storeIntegerofObjectwithValue"); + LogUtils.PRIMITIVES.warning(() -> "Missing implementation for storeIntegerofObjectwithValue: %s, %s, %s".formatted(index, oop, integer)); return returnVoid(); } private long storeLong32ofObjectwithValue(final long fieldIndex, final long oop, final long anInteger) { /* TODO */ - LogUtils.PRIMITIVES.warning("Missing implementation for storeLong32ofObjectwithValue"); + LogUtils.PRIMITIVES.warning(() -> "Missing implementation for storeLong32ofObjectwithValue: %s, %s, %s".formatted(fieldIndex, oop, anInteger)); return returnVoid(); } } From cf2f6b177cf0f447f7c486f14d5975c830506b06 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 12:08:53 +0100 Subject: [PATCH 144/159] Add InterpreterProxy and loaded modules to context They are context-specific and cannot be re-used in a different context, which for example happens during testing. --- .../image/SqueakImageContext.java | 13 +++++ .../nodes/plugins/ffi/InterpreterProxy.java | 55 ++++++++----------- .../plugins/ffi/PrimExternalCallNode.java | 18 +++--- 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java index 04dbd25f6..c49a20b8c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java @@ -11,6 +11,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; +import java.util.Map; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -19,6 +20,7 @@ import com.oracle.truffle.api.TruffleFile; import com.oracle.truffle.api.TruffleLanguage.ContextReference; import com.oracle.truffle.api.TruffleLanguage.ParsingRequest; +import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.instrumentation.AllocationReporter; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.library.Message; @@ -64,6 +66,7 @@ import de.hpi.swa.trufflesqueak.nodes.plugins.BitBlt; import de.hpi.swa.trufflesqueak.nodes.plugins.JPEGReader; import de.hpi.swa.trufflesqueak.nodes.plugins.Zip; +import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.InterpreterProxy; import de.hpi.swa.trufflesqueak.shared.SqueakImageLocator; import de.hpi.swa.trufflesqueak.tools.SqueakMessageInterceptor; import de.hpi.swa.trufflesqueak.util.ArrayUtils; @@ -165,6 +168,8 @@ public final class SqueakImageContext { @CompilationFinal private ClassObject wideStringClass; /* Plugins */ + @CompilationFinal private InterpreterProxy interpreterProxy; + public final Map loadedLibraries = new HashMap<>(); public final B2D b2d = new B2D(this); public final BitBlt bitblt = new BitBlt(this); public String[] dropPluginFileList = new String[0]; @@ -621,6 +626,14 @@ public boolean supportsNFI() { return env.getInternalLanguages().containsKey("nfi"); } + public InterpreterProxy getInterpreterProxy(final MaterializedFrame frame, final int numReceiverAndArguments) { + if (interpreterProxy == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + interpreterProxy = new InterpreterProxy(this); + } + return interpreterProxy.instanceFor(frame, numReceiverAndArguments); + } + public PointersObject getScheduler() { if (scheduler == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index aa87360e3..02b37b19a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -11,6 +11,7 @@ import java.util.function.Predicate; import java.util.stream.Collectors; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -43,7 +44,6 @@ import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; public final class InterpreterProxy { - private static InterpreterProxy INSTANCE; private final SqueakImageContext context; private MaterializedFrame frame; private int numReceiverAndArguments; @@ -63,26 +63,26 @@ public final class InterpreterProxy { // INSTANCE CREATION // /////////////////////// - private InterpreterProxy(final SqueakImageContext context, final MaterializedFrame frame, final int numReceiverAndArguments) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { + public InterpreterProxy(final SqueakImageContext context) { this.context = context; - this.frame = frame; - this.numReceiverAndArguments = numReceiverAndArguments; - - final TruffleExecutable[] executables = getExecutables(); - closures = new TruffleClosure[executables.length]; - for (int i = 0; i < executables.length; i++) { - closures[i] = executables[i].createClosure(context); - } + try { + final TruffleExecutable[] executables = getExecutables(); + closures = new TruffleClosure[executables.length]; + for (int i = 0; i < executables.length; i++) { + closures[i] = executables[i].createClosure(context); + } - final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); - final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", - "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }"); - assert interpreterProxy != null : "InterpreterProxy module not found!"; + final String truffleExecutablesSignatures = Arrays.stream(closures).map(obj -> obj.executable.nfiSignature).collect(Collectors.joining(",")); + final Object interpreterProxy = NFIUtils.loadLibrary(context, "InterpreterProxy", + "{ createInterpreterProxy(" + truffleExecutablesSignatures + "):POINTER; }"); + assert interpreterProxy != null : "InterpreterProxy module not found!"; - final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); - interpreterProxyPointer = interpreterProxyLibrary.invokeMember( - interpreterProxy, "createInterpreterProxy", (Object[]) closures); + final InteropLibrary interpreterProxyLibrary = NFIUtils.getInteropLibrary(interpreterProxy); + interpreterProxyPointer = interpreterProxyLibrary.invokeMember( + interpreterProxy, "createInterpreterProxy", (Object[]) closures); + } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException | ArityException e) { + throw CompilerDirectives.shouldNotReachHere(e); + } } private TruffleExecutable[] getExecutables() { @@ -164,25 +164,18 @@ private TruffleExecutable[] getExecutables() { }; } - public static InterpreterProxy instanceFor(final SqueakImageContext context, final MaterializedFrame frame, final int numReceiverAndArguments) - throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException, ArityException { - if (INSTANCE == null) { - INSTANCE = new InterpreterProxy(context, frame, numReceiverAndArguments); - return INSTANCE; - } - assert INSTANCE.context == context : "received new SqueakImageContext"; - - INSTANCE.frame = frame; - INSTANCE.numReceiverAndArguments = numReceiverAndArguments; - return INSTANCE; + public InterpreterProxy instanceFor(final MaterializedFrame frame, final int numReceiverAndArguments) { + this.frame = frame; + this.numReceiverAndArguments = numReceiverAndArguments; + return this; } /////////////////// // MISCELLANEOUS // /////////////////// - public static Object getPointer() { - return INSTANCE.interpreterProxyPointer; + public Object getPointer() { + return interpreterProxyPointer; } public void postPrimitiveCleanups() { diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index d0bddbd24..ace081393 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -6,9 +6,6 @@ */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; -import java.util.HashMap; -import java.util.Map; - import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.exception.AbstractTruffleException; @@ -32,7 +29,6 @@ public final class PrimExternalCallNode extends AbstractPrimitiveNode { private final Object functionSymbol; private final InteropLibrary functionInteropLibrary; private final int numReceiverAndArguments; - private static final Map loadedLibraries = new HashMap<>(); public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary moduleInteropLibrary, final Object functionSymbol, final InteropLibrary functionInteropLibrary, final int numReceiverAndArguments) { @@ -46,8 +42,8 @@ public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary mod public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) { final SqueakImageContext context = SqueakImageContext.getSlow(); - final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> { - if (loadedLibraries.containsKey(moduleName)) { + final Object moduleLibrary = context.loadedLibraries.computeIfAbsent(moduleName, (String s) -> { + if (context.loadedLibraries.containsKey(moduleName)) { // if moduleName was associated with null return null; } @@ -77,7 +73,7 @@ public static PrimExternalCallNode load(final String moduleName, final String fu return library; }); // computeIfAbsent would not put null value - loadedLibraries.putIfAbsent(moduleName, moduleLibrary); + context.loadedLibraries.putIfAbsent(moduleName, moduleLibrary); if (moduleLibrary == null) { // module not found return null; @@ -95,8 +91,8 @@ public static PrimExternalCallNode load(final String moduleName, final String fu private void setInterpreter() { try { - InterpreterProxy.instanceFor(getContext(), null, 0); - moduleInteropLibrary.invokeMember(moduleLibrary, "setInterpreter", InterpreterProxy.getPointer()); + final InterpreterProxy interpreterProxy = getContext().getInterpreterProxy(null, 0); + moduleInteropLibrary.invokeMember(moduleLibrary, "setInterpreter", interpreterProxy.getPointer()); } catch (UnsupportedMessageException | ArityException | UnsupportedTypeException | UnknownIdentifierException e) { throw CompilerDirectives.shouldNotReachHere(e); } @@ -117,7 +113,7 @@ public Object executeWithArguments(final VirtualFrame frame, final Object... rec private Object doExternalCall(final MaterializedFrame frame) { InterpreterProxy interpreterProxy = null; try { - interpreterProxy = InterpreterProxy.instanceFor(getContext(), frame, numReceiverAndArguments); + interpreterProxy = getContext().getInterpreterProxy(frame, numReceiverAndArguments); // A send (AbstractSendNode.executeVoid) will decrement the stack pointer by // numReceiverAndArguments @@ -138,7 +134,7 @@ private Object doExternalCall(final MaterializedFrame frame) { throw PrimitiveFailed.andTransferToInterpreter((int) failReason); } return returnValue; - } catch (UnsupportedMessageException | UnknownIdentifierException | ArityException | UnsupportedTypeException e) { + } catch (UnsupportedMessageException | ArityException | UnsupportedTypeException e) { throw CompilerDirectives.shouldNotReachHere(e); } finally { if (interpreterProxy != null) { From 3d16b0ce99c8f634543a7b4a0f260687ddf4e536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Fri, 9 Feb 2024 11:56:50 +0100 Subject: [PATCH 145/159] Fix ordering of methods --- .../nodes/plugins/ffi/InterpreterProxy.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 02b37b19a..2c0d88f53 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -455,6 +455,10 @@ public long failed() { return primFailCode; } + private long falseObject() { + return oopFor(BooleanObject.FALSE); + } + private long fetchIntegerofObject(final long fieldIndex, final long objectPointer) { return objectToInteger(objectAt0(objectRegistryGet(objectPointer), fieldIndex)); } @@ -578,18 +582,10 @@ private long minorVersion() { return 17; } - private long falseObject() { - return oopFor(BooleanObject.FALSE); - } - private long nilObject() { return oopFor(NilObject.SINGLETON); } - private long trueObject() { - return oopFor(BooleanObject.TRUE); - } - private long pop(final long nItems) { setStackPointer(getStackPointer() - (int) nItems); return returnNull(); @@ -687,4 +683,8 @@ private long storeLong32ofObjectwithValue(final long fieldIndex, final long oop, LogUtils.PRIMITIVES.warning(() -> "Missing implementation for storeLong32ofObjectwithValue: %s, %s, %s".formatted(fieldIndex, oop, anInteger)); return returnVoid(); } + + private long trueObject() { + return oopFor(BooleanObject.TRUE); + } } From be4897c95f8ef33dc676c5242f12531134480c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Fri, 9 Feb 2024 12:07:10 +0100 Subject: [PATCH 146/159] Properly implement stringForCString --- .../src/InterpreterProxy.c | 2 ++ .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index 71320af5c..348fc291a 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -82,6 +82,7 @@ VirtualMachine* createInterpreterProxy( sqInt (*stackObjectValue)(sqInt offset), sqInt (*stackValue)(sqInt offset), sqInt (*statNumGCs)(void), + sqInt (*stringForCString)(char* nullTerminatedCString), sqInt (*storeIntegerofObjectwithValue)(sqInt index, sqInt oop, sqInt integer), usqInt (*storeLong32ofObjectwithValue)(sqInt fieldIndex, sqInt oop, usqInt anInteger), sqInt (*trueObject)(void) @@ -157,6 +158,7 @@ VirtualMachine* createInterpreterProxy( interpreterProxy->stackObjectValue = stackObjectValue; interpreterProxy->stackValue = stackValue; interpreterProxy->statNumGCs = statNumGCs; + interpreterProxy->stringForCString = stringForCString; interpreterProxy->storeIntegerofObjectwithValue = storeIntegerofObjectwithValue; interpreterProxy->storeLong32ofObjectwithValue = storeLong32ofObjectwithValue; interpreterProxy->trueObject = trueObject; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 2c0d88f53..b29b197cf 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -158,6 +158,7 @@ private TruffleExecutable[] getExecutables() { TruffleExecutable.wrap("(SINT64):SINT64", this::stackObjectValue), TruffleExecutable.wrap("(SINT64):SINT64", this::stackValue), TruffleExecutable.wrap("():SINT64", this::statNumGCs), + TruffleExecutable.wrap("(STRING):UINT64", this::stringForCString), TruffleExecutable.wrap("(SINT64,SINT64,SINT64):SINT64", this::storeIntegerofObjectwithValue), TruffleExecutable.wrap("(SINT64,SINT64,UINT64):UINT64", this::storeLong32ofObjectwithValue), TruffleExecutable.wrap("():SINT64", this::trueObject), @@ -672,6 +673,10 @@ private long statNumGCs() { return MiscUtils.getCollectionCount(); } + private long stringForCString(final String string) { + return oopFor(stringToObject(string)); + } + private long storeIntegerofObjectwithValue(final long index, final long oop, final long integer) { /* TODO */ LogUtils.PRIMITIVES.warning(() -> "Missing implementation for storeIntegerofObjectwithValue: %s, %s, %s".formatted(index, oop, integer)); From 763ee3271f56df8c7e1c735211029d88cffc3943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Fri, 9 Feb 2024 12:07:29 +0100 Subject: [PATCH 147/159] Readd push --- .../src/InterpreterProxy.c | 2 ++ .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index 348fc291a..0f71bf6d2 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -73,6 +73,7 @@ VirtualMachine* createInterpreterProxy( usqLong (*positive64BitValueOf)(sqInt oop), sqInt (*primitiveFail)(void), sqInt (*primitiveFailFor)(sqInt reasonCode), + sqInt (*push)(sqInt object), sqInt (*pushInteger)(sqInt integerValue), sqInt (*showDisplayBitsLeftTopRightBottom)(sqInt aForm, sqInt l, sqInt t, sqInt r, sqInt b), sqInt (*signed32BitIntegerFor)(sqInt integerValue), @@ -149,6 +150,7 @@ VirtualMachine* createInterpreterProxy( interpreterProxy->positive64BitValueOf = positive64BitValueOf; interpreterProxy->primitiveFail = primitiveFail; interpreterProxy->primitiveFailFor = primitiveFailFor; + interpreterProxy->push = push; interpreterProxy->pushInteger = pushInteger; interpreterProxy->showDisplayBitsLeftTopRightBottom = showDisplayBitsLeftTopRightBottom; interpreterProxy->signed32BitIntegerFor = signed32BitIntegerFor; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index b29b197cf..86f00930a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -149,6 +149,7 @@ private TruffleExecutable[] getExecutables() { TruffleExecutable.wrap("(SINT64):UINT64", this::positive64BitValueOf), TruffleExecutable.wrap("():SINT64", this::primitiveFail), TruffleExecutable.wrap("(SINT64):SINT64", this::primitiveFailFor), + TruffleExecutable.wrap("(SINT64):SINT64", this::push), TruffleExecutable.wrap("(SINT64):SINT64", this::pushInteger), TruffleExecutable.wrap("(SINT64,SINT64,SINT64,SINT64,SINT64):SINT64", this::showDisplayBitsLeftTopRightBottom), TruffleExecutable.wrap("(SINT64):SINT64", this::signed32BitIntegerFor), @@ -594,7 +595,7 @@ private long pop(final long nItems) { private long popthenPush(final long nItems, final long oop) { pop(nItems); - pushObject(objectRegistryGet(oop)); + push(oop); return returnVoid(); } @@ -625,6 +626,11 @@ private long primitiveFailFor(final long reasonCode) { return primFailCode = reasonCode; } + private long push(final long oop) { + pushObject(objectRegistryGet(oop)); + return returnVoid(); + } + private long pushInteger(final long integer) { pushObject(integerToObject(integer)); return returnNull(); From 54c6482eba48e9fbc6b5f536b8f71b15510a78ef Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 12:15:19 +0100 Subject: [PATCH 148/159] Fix ECJ warnings --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 86f00930a..c4a4a1535 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -166,9 +166,9 @@ private TruffleExecutable[] getExecutables() { }; } - public InterpreterProxy instanceFor(final MaterializedFrame frame, final int numReceiverAndArguments) { - this.frame = frame; - this.numReceiverAndArguments = numReceiverAndArguments; + public InterpreterProxy instanceFor(final MaterializedFrame currentFrame, final int currentNumReceiverAndArguments) { + this.frame = currentFrame; + this.numReceiverAndArguments = currentNumReceiverAndArguments; return this; } From a6b073e4462e6c6ec2cea420e61aa80965f272ca Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 12:17:33 +0100 Subject: [PATCH 149/159] Upgrade actions used in workflow for Node 20 --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab7fd2edb..ac6d5f368 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,9 +28,9 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Clone TruffleSqueak repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.8' - name: Set up dependencies @@ -63,11 +63,11 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Clone TruffleSqueak repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: submodules: true - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.8' - name: Set up dependencies @@ -148,7 +148,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Clone TruffleSqueak repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 # Oracle GraalVM for JDK 22 not released yet # - name: Set up Oracle GraalVM # uses: graalvm/setup-graalvm@v1 @@ -164,7 +164,7 @@ jobs: # cat "${JAVA_HOME}/LICENSE.txt" > "${GITHUB_WORKSPACE}/LICENSE" # if: ${{ matrix.type == 'native' }} - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '3.8' - name: Set up dependencies From dac1d2df02481e252be427a7250bbd4ab2a48287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Fri, 9 Feb 2024 12:21:15 +0100 Subject: [PATCH 150/159] Add final to instanceof variable declarations --- .../nodes/plugins/ffi/InterpreterProxy.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index c4a4a1535..3ff3820e7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -277,7 +277,7 @@ private static long returnNull() { //////////////////////// private long objectToInteger(final Object object) { - if (object instanceof Long longObject) { + if (object instanceof final Long longObject) { return longObject; } LogUtils.PRIMITIVES.severe(() -> "Object to long called with non-Long: " + object); @@ -286,7 +286,7 @@ private long objectToInteger(final Object object) { } private double objectToFloat(final Object object) { - if (object instanceof FloatObject floatObject) { + if (object instanceof final FloatObject floatObject) { return floatObject.getValue(); } LogUtils.PRIMITIVES.severe(() -> "Object to long called with non-FloatObject: " + object); @@ -333,7 +333,7 @@ private long instanceOfCheck(final long oop, final Class klass) { private long nativeObjectCheck(final long oop, final Predicate predicate) { final Object object = objectRegistryGet(oop); - if (object instanceof NativeObject nativeObject) { + if (object instanceof final NativeObject nativeObject) { return returnBoolean(predicate.test(nativeObject)); } return returnVoid(); @@ -345,7 +345,7 @@ private long nativeObjectCheck(final long oop, final Predicate pre private long booleanValueOf(final long oop) { final Object object = objectRegistryGet(oop); - if (object instanceof Boolean bool) { + if (object instanceof final Boolean bool) { return returnBoolean(bool); } primitiveFail(); @@ -353,7 +353,7 @@ private long booleanValueOf(final long oop) { } private long byteSizeOf(final long oop) { - if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { + if (objectRegistryGet(oop) instanceof final NativeObject nativeObject) { return NativeObjectStorage.from(nativeObject).byteSizeOf(); } // type is not supported (yet) @@ -474,7 +474,7 @@ private long fetchPointerofObject(final long index, final long oop) { } private NativeObjectStorage firstIndexableField(final long oop) { - if (objectRegistryGet(oop) instanceof NativeObject nativeObject) { + if (objectRegistryGet(oop) instanceof final NativeObject nativeObject) { final NativeObjectStorage storage = NativeObjectStorage.from(nativeObject); postPrimitiveCleanups.add(storage); return storage; @@ -488,7 +488,7 @@ private double floatValueOf(final long oop) { private long instantiateClassindexableSize(final long classPointer, final long size) { final Object object = objectRegistryGet(classPointer); - if (object instanceof ClassObject classObject) { + if (object instanceof final ClassObject classObject) { final AbstractSqueakObject newObject = SqueakObjectNewNode.executeUncached(context, classObject, (int) size); return oopFor(newObject); } @@ -529,10 +529,10 @@ private long isPointers(final long oop) { private long isPositiveMachineIntegerObject(final long oop) { final Object object = objectRegistryGet(oop); - if (object instanceof Long integer) { + if (object instanceof final Long integer) { return returnBoolean(integer >= 0L); } - if (object instanceof LargeIntegerObject largeInteger) { + if (object instanceof final LargeIntegerObject largeInteger) { return returnBoolean(largeInteger.isZeroOrPositive() && largeInteger.fitsIntoLong()); } return returnBoolean(false); From 6eae7fc9b3b1eb6fd2186cf7ca64da511fcb6ab6 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Fri, 9 Feb 2024 14:04:38 +0100 Subject: [PATCH 151/159] Fix 0-based error code and do not overwrite --- .../nodes/plugins/ffi/InterpreterProxy.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 3ff3820e7..35320c741 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -6,11 +6,6 @@ */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.function.Predicate; -import java.util.stream.Collectors; - import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ArityException; @@ -18,7 +13,6 @@ import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; - import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.io.SqueakDisplay; import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; @@ -31,7 +25,6 @@ import de.hpi.swa.trufflesqueak.model.NativeObject; import de.hpi.swa.trufflesqueak.model.NilObject; import de.hpi.swa.trufflesqueak.model.PointersObject; -import de.hpi.swa.trufflesqueak.model.layout.ObjectLayouts.ERROR_TABLE; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; @@ -43,6 +36,11 @@ import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleClosure; import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.function.Predicate; +import java.util.stream.Collectors; + public final class InterpreterProxy { private final SqueakImageContext context; private MaterializedFrame frame; @@ -618,7 +616,10 @@ private long positive64BitValueOf(final long oop) { } private long primitiveFail() { - return primitiveFailFor(ERROR_TABLE.GENERIC_ERROR.ordinal()); + if (primFailCode == 0) { + primitiveFailFor(1L); + } + return returnNull(); } private long primitiveFailFor(final long reasonCode) { From 0a657e2f7c8e1658b97e7d0d0537ebf6a819d200 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Fri, 9 Feb 2024 14:28:09 +0100 Subject: [PATCH 152/159] Add 32bit casts --- .../nodes/plugins/ffi/InterpreterProxy.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 35320c741..7151751ce 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -464,7 +464,7 @@ private long fetchIntegerofObject(final long fieldIndex, final long objectPointe } private long fetchLong32ofObject(final long fieldIndex, final long oop) { - return fetchIntegerofObject(fieldIndex, oop); + return (int) fetchIntegerofObject(fieldIndex, oop); } private long fetchPointerofObject(final long index, final long oop) { @@ -598,21 +598,15 @@ private long popthenPush(final long nItems, final long oop) { } private long positive32BitIntegerFor(final long integerValue) { - /* TODO */ - LogUtils.PRIMITIVES.warning(() -> "Missing implementation for positive32BitIntegerFor: " + integerValue); - return returnVoid(); + return integerObjectOf(integerValue & Integer.MAX_VALUE); } private long positive32BitValueOf(final long oop) { - /* TODO */ - LogUtils.PRIMITIVES.warning(() -> "Missing implementation for positive32BitValueOf: " + oop); - return returnVoid(); + return integerValueOf(oop) & Integer.MAX_VALUE; } private long positive64BitValueOf(final long oop) { - /* TODO */ - LogUtils.PRIMITIVES.warning(() -> "Missing implementation for positive64BitValueOf: " + oop); - return returnVoid(); + return Math.abs(integerValueOf(oop)); } private long primitiveFail() { @@ -649,11 +643,11 @@ private long showDisplayBitsLeftTopRightBottom(final long aFormOop, final long l } private long signed32BitIntegerFor(final long integerValue) { - return integerObjectOf(integerValue); + return integerObjectOf((int) integerValue); } private long signed32BitValueOf(final long oop) { - return integerValueOf(oop); + return (int) integerValueOf(oop); } private long slotSizeOf(final long oop) { From 5d5e92d6792908ec0e7077079d93410dcd2b1841 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Fri, 9 Feb 2024 14:32:03 +0100 Subject: [PATCH 153/159] Fix long return values --- .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index 7151751ce..f6ab9c9dc 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -567,7 +567,7 @@ private long methodReturnInteger(final long integer) { private long methodReturnReceiver() { assert hasSucceeded(); pop(numReceiverAndArguments - 1); // leave the receiver on the stack - return 0; + return 0L; } private long methodReturnString(final String string) { @@ -579,7 +579,7 @@ private long methodReturnValue(final long oop) { } private long minorVersion() { - return 17; + return 17L; } private long nilObject() { @@ -613,7 +613,7 @@ private long primitiveFail() { if (primFailCode == 0) { primitiveFailFor(1L); } - return returnNull(); + return 0L; } private long primitiveFailFor(final long reasonCode) { From a577ca222b0152f802b17f5d1c77eb16d979b4dc Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 14:07:37 +0100 Subject: [PATCH 154/159] Move loadedLibraries into InterpreterProxy --- .../image/SqueakImageContext.java | 8 ++- .../nodes/plugins/ffi/InterpreterProxy.java | 59 ++++++++++++++++-- .../plugins/ffi/PrimExternalCallNode.java | 60 ++----------------- 3 files changed, 63 insertions(+), 64 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java index c49a20b8c..d716e49e7 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java @@ -11,7 +11,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; -import java.util.Map; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -169,7 +168,6 @@ public final class SqueakImageContext { /* Plugins */ @CompilationFinal private InterpreterProxy interpreterProxy; - public final Map loadedLibraries = new HashMap<>(); public final B2D b2d = new B2D(this); public final BitBlt bitblt = new BitBlt(this); public String[] dropPluginFileList = new String[0]; @@ -626,11 +624,15 @@ public boolean supportsNFI() { return env.getInternalLanguages().containsKey("nfi"); } - public InterpreterProxy getInterpreterProxy(final MaterializedFrame frame, final int numReceiverAndArguments) { + public InterpreterProxy getOrCreateInterpreterProxy() { if (interpreterProxy == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); interpreterProxy = new InterpreterProxy(this); } + return interpreterProxy; + } + + public InterpreterProxy getInterpreterProxy(final MaterializedFrame frame, final int numReceiverAndArguments) { return interpreterProxy.instanceFor(frame, numReceiverAndArguments); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index f6ab9c9dc..f8eac3e6b 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -6,13 +6,22 @@ */ package de.hpi.swa.trufflesqueak.nodes.plugins.ffi; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; + import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.interop.UnsupportedMessageException; import com.oracle.truffle.api.interop.UnsupportedTypeException; + import de.hpi.swa.trufflesqueak.image.SqueakImageContext; import de.hpi.swa.trufflesqueak.io.SqueakDisplay; import de.hpi.swa.trufflesqueak.model.AbstractPointersObject; @@ -36,11 +45,6 @@ import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleClosure; import de.hpi.swa.trufflesqueak.util.NFIUtils.TruffleExecutable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.function.Predicate; -import java.util.stream.Collectors; - public final class InterpreterProxy { private final SqueakImageContext context; private MaterializedFrame frame; @@ -50,6 +54,7 @@ public final class InterpreterProxy { // since this class is a singleton, a private instance variable will suffice @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; private final Object interpreterProxyPointer; + private final Map loadedLibraries = new HashMap<>(); /////////////////////////// // INTERPRETER VARIABLES // @@ -170,11 +175,53 @@ public InterpreterProxy instanceFor(final MaterializedFrame currentFrame, final return this; } + public Object lookupModuleLibrary(final String moduleName) { + final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> { + if (loadedLibraries.containsKey(moduleName)) { + // if moduleName was associated with null + return null; + } + final Object library; + try { + library = NFIUtils.loadLibrary(context, moduleName, "{ setInterpreter(POINTER):SINT64; }"); + } catch (AbstractTruffleException e) { + if (e.getMessage().equals("Unknown identifier: setInterpreter")) { + // module has no setInterpreter, cannot be loaded + return null; + } + throw e; + } + if (library == null) { + return null; + } + try { + // TODO: also call shutdownModule():SINT64 at some point + final Object initialiseModuleSymbol = NFIUtils.loadMember(context, library, "initialiseModule", "():SINT64"); + final InteropLibrary initialiseModuleInteropLibrary = NFIUtils.getInteropLibrary(initialiseModuleSymbol); + initialiseModuleInteropLibrary.execute(initialiseModuleSymbol); + } catch (UnknownIdentifierException e) { + // module has no initializer, ignore + } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { + throw CompilerDirectives.shouldNotReachHere(e); + } + try { + final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(library); + moduleInteropLibrary.invokeMember(library, "setInterpreter", getPointer()); + } catch (UnsupportedMessageException | ArityException | UnsupportedTypeException | UnknownIdentifierException e) { + throw CompilerDirectives.shouldNotReachHere(e); + } + return library; + }); + // computeIfAbsent would not put null value + loadedLibraries.putIfAbsent(moduleName, moduleLibrary); + return moduleLibrary; + } + /////////////////// // MISCELLANEOUS // /////////////////// - public Object getPointer() { + private Object getPointer() { return interpreterProxyPointer; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index ace081393..8e1bca30a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -8,7 +8,6 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; @@ -24,77 +23,28 @@ import de.hpi.swa.trufflesqueak.util.NFIUtils; public final class PrimExternalCallNode extends AbstractPrimitiveNode { - private final Object moduleLibrary; - private final InteropLibrary moduleInteropLibrary; private final Object functionSymbol; private final InteropLibrary functionInteropLibrary; private final int numReceiverAndArguments; - public PrimExternalCallNode(final Object moduleLibrary, final InteropLibrary moduleInteropLibrary, final Object functionSymbol, final InteropLibrary functionInteropLibrary, - final int numReceiverAndArguments) { - this.moduleLibrary = moduleLibrary; - this.moduleInteropLibrary = moduleInteropLibrary; + public PrimExternalCallNode(final Object functionSymbol, final InteropLibrary functionInteropLibrary, final int numReceiverAndArguments) { this.functionSymbol = functionSymbol; this.functionInteropLibrary = functionInteropLibrary; this.numReceiverAndArguments = numReceiverAndArguments; - setInterpreter(); } public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) { final SqueakImageContext context = SqueakImageContext.getSlow(); - final Object moduleLibrary = context.loadedLibraries.computeIfAbsent(moduleName, (String s) -> { - if (context.loadedLibraries.containsKey(moduleName)) { - // if moduleName was associated with null - return null; - } - final Object library; - try { - library = NFIUtils.loadLibrary(context, moduleName, "{ setInterpreter(POINTER):SINT64; }"); - } catch (AbstractTruffleException e) { - if (e.getMessage().equals("Unknown identifier: setInterpreter")) { - // module has no setInterpreter, cannot be loaded - return null; - } - throw e; - } - if (library == null) { - return null; - } - try { - // TODO: also call shutdownModule():SINT64 at some point - final Object initialiseModuleSymbol = NFIUtils.loadMember(context, library, "initialiseModule", "():SINT64"); - final InteropLibrary initialiseModuleInteropLibrary = NFIUtils.getInteropLibrary(initialiseModuleSymbol); - initialiseModuleInteropLibrary.execute(initialiseModuleSymbol); - } catch (UnknownIdentifierException e) { - // module has no initializer, ignore - } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { - throw CompilerDirectives.shouldNotReachHere(e); - } - return library; - }); - // computeIfAbsent would not put null value - context.loadedLibraries.putIfAbsent(moduleName, moduleLibrary); + final Object moduleLibrary = context.getOrCreateInterpreterProxy().lookupModuleLibrary(moduleName); if (moduleLibrary == null) { - // module not found - return null; + return null; // module not found } - final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(moduleLibrary); try { final Object functionSymbol = NFIUtils.loadMember(context, moduleLibrary, functionName, "():SINT64"); final InteropLibrary functionInteropLibrary = NFIUtils.getInteropLibrary(functionSymbol); - return new PrimExternalCallNode(moduleLibrary, moduleInteropLibrary, functionSymbol, functionInteropLibrary, numReceiverAndArguments); + return new PrimExternalCallNode(functionSymbol, functionInteropLibrary, numReceiverAndArguments); } catch (UnknownIdentifierException e) { - // function not found - return null; - } - } - - private void setInterpreter() { - try { - final InterpreterProxy interpreterProxy = getContext().getInterpreterProxy(null, 0); - moduleInteropLibrary.invokeMember(moduleLibrary, "setInterpreter", interpreterProxy.getPointer()); - } catch (UnsupportedMessageException | ArityException | UnsupportedTypeException | UnknownIdentifierException e) { - throw CompilerDirectives.shouldNotReachHere(e); + return null; // function not found } } From 3889b4b24312d89f2d400ff149752fa2023c225e Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 14:29:35 +0100 Subject: [PATCH 155/159] Drop `PostPrimitiveCleanup` --- .../nodes/plugins/ffi/InterpreterProxy.java | 5 ++--- .../plugins/ffi/wrappers/NativeObjectStorage.java | 4 +++- .../plugins/ffi/wrappers/PostPrimitiveCleanup.java | 11 ----------- 3 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index f8eac3e6b..b93623395 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -37,7 +37,6 @@ import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectAt0Node; import de.hpi.swa.trufflesqueak.nodes.accessing.SqueakObjectNewNode; import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.NativeObjectStorage; -import de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers.PostPrimitiveCleanup; import de.hpi.swa.trufflesqueak.util.FrameAccess; import de.hpi.swa.trufflesqueak.util.LogUtils; import de.hpi.swa.trufflesqueak.util.MiscUtils; @@ -49,7 +48,7 @@ public final class InterpreterProxy { private final SqueakImageContext context; private MaterializedFrame frame; private int numReceiverAndArguments; - private final ArrayList postPrimitiveCleanups = new ArrayList<>(); + private final ArrayList postPrimitiveCleanups = new ArrayList<>(); // should not be local, as the references are needed to keep the native closures alive // since this class is a singleton, a private instance variable will suffice @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; @@ -226,7 +225,7 @@ private Object getPointer() { } public void postPrimitiveCleanups() { - postPrimitiveCleanups.forEach(PostPrimitiveCleanup::cleanup); + postPrimitiveCleanups.forEach(NativeObjectStorage::cleanup); postPrimitiveCleanups.clear(); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java index 641d63b9d..8c7a689b2 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/NativeObjectStorage.java @@ -14,7 +14,7 @@ import de.hpi.swa.trufflesqueak.model.NativeObject; @ExportLibrary(InteropLibrary.class) -public abstract class NativeObjectStorage implements PostPrimitiveCleanup, TruffleObject { +public abstract class NativeObjectStorage implements TruffleObject { protected long nativeAddress; private boolean isAllocated; @@ -54,4 +54,6 @@ public void toNative() { public abstract int byteSizeOf(); protected abstract long allocate(); + + public abstract void cleanup(); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java deleted file mode 100644 index 66a02938e..000000000 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/PostPrimitiveCleanup.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2023-2024 Software Architecture Group, Hasso Plattner Institute - * Copyright (c) 2023-2024 Oracle and/or its affiliates - * - * Licensed under the MIT License. - */ -package de.hpi.swa.trufflesqueak.nodes.plugins.ffi.wrappers; - -public interface PostPrimitiveCleanup { - void cleanup(); -} From 9eaa707a90885a4b05409fac1f47bd5e864ab1a9 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 14:31:55 +0100 Subject: [PATCH 156/159] Adjust visibility --- .../trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java | 4 ++-- .../trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java | 4 ++-- .../trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java | 4 ++-- .../nodes/plugins/ffi/wrappers/ShortStorage.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index 6795079aa..f8043c18c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -8,8 +8,8 @@ import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -public final class ByteStorage extends NativeObjectStorage { - final byte[] storage; +final class ByteStorage extends NativeObjectStorage { + private final byte[] storage; public ByteStorage(final byte[] storage) { this.storage = storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index b154363fd..1597d2dba 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -8,8 +8,8 @@ import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -public final class IntStorage extends NativeObjectStorage { - final int[] storage; +final class IntStorage extends NativeObjectStorage { + private final int[] storage; public IntStorage(final int[] storage) { this.storage = storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index 8184c1615..779d5cf43 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -8,8 +8,8 @@ import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -public final class LongStorage extends NativeObjectStorage { - final long[] storage; +final class LongStorage extends NativeObjectStorage { + private final long[] storage; public LongStorage(final long[] storage) { this.storage = storage; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 9323e7ad8..06f3edafb 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -8,8 +8,8 @@ import de.hpi.swa.trufflesqueak.util.UnsafeUtils; -public final class ShortStorage extends NativeObjectStorage { - final short[] storage; +final class ShortStorage extends NativeObjectStorage { + private final short[] storage; public ShortStorage(final short[] storage) { this.storage = storage; From fac45ecba6a184f6b131d260fb45cced087dbb01 Mon Sep 17 00:00:00 2001 From: Malte Stellmacher Date: Fri, 9 Feb 2024 15:12:11 +0100 Subject: [PATCH 157/159] Implement positive64BitIntegerFor --- .../src/InterpreterProxy.c | 2 ++ .../trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c index 0f71bf6d2..54a4474a1 100644 --- a/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c +++ b/src/de.hpi.swa.trufflesqueak.ffi.native/src/InterpreterProxy.c @@ -70,6 +70,7 @@ VirtualMachine* createInterpreterProxy( sqInt (*popthenPush)(sqInt nItems, sqInt oop), sqInt (*positive32BitIntegerFor)(unsigned int integerValue), usqInt (*positive32BitValueOf)(sqInt oop), + sqInt (*positive64BitIntegerFor)(usqLong integerValue), usqLong (*positive64BitValueOf)(sqInt oop), sqInt (*primitiveFail)(void), sqInt (*primitiveFailFor)(sqInt reasonCode), @@ -147,6 +148,7 @@ VirtualMachine* createInterpreterProxy( interpreterProxy->popthenPush = popthenPush; interpreterProxy->positive32BitIntegerFor = positive32BitIntegerFor; interpreterProxy->positive32BitValueOf = positive32BitValueOf; + interpreterProxy->positive64BitIntegerFor = positive64BitIntegerFor; interpreterProxy->positive64BitValueOf = positive64BitValueOf; interpreterProxy->primitiveFail = primitiveFail; interpreterProxy->primitiveFailFor = primitiveFailFor; diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index b93623395..eeeac92af 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -148,6 +148,7 @@ private TruffleExecutable[] getExecutables() { TruffleExecutable.wrap("(SINT64,SINT64):SINT64", this::popthenPush), TruffleExecutable.wrap("(UINT64):SINT64", this::positive32BitIntegerFor), TruffleExecutable.wrap("(SINT64):UINT64", this::positive32BitValueOf), + TruffleExecutable.wrap("(SINT64):UINT64", this::positive64BitIntegerFor), TruffleExecutable.wrap("(SINT64):UINT64", this::positive64BitValueOf), TruffleExecutable.wrap("():SINT64", this::primitiveFail), TruffleExecutable.wrap("(SINT64):SINT64", this::primitiveFailFor), @@ -651,6 +652,10 @@ private long positive32BitValueOf(final long oop) { return integerValueOf(oop) & Integer.MAX_VALUE; } + private long positive64BitIntegerFor(final long integerValue) { + return integerObjectOf(Math.abs(integerValue)); + } + private long positive64BitValueOf(final long oop) { return Math.abs(integerValueOf(oop)); } From 79e1dede69dffc22c70d893feb6a0bfea1b02e04 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 15:20:27 +0100 Subject: [PATCH 158/159] Fix ECJ warnings --- .../trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java | 2 +- .../trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java | 2 +- .../trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java | 2 +- .../trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java index f8043c18c..9cad993eb 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ByteStorage.java @@ -11,7 +11,7 @@ final class ByteStorage extends NativeObjectStorage { private final byte[] storage; - public ByteStorage(final byte[] storage) { + ByteStorage(final byte[] storage) { this.storage = storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java index 1597d2dba..569d5be4a 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/IntStorage.java @@ -11,7 +11,7 @@ final class IntStorage extends NativeObjectStorage { private final int[] storage; - public IntStorage(final int[] storage) { + IntStorage(final int[] storage) { this.storage = storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java index 779d5cf43..59bdfb7d0 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/LongStorage.java @@ -11,7 +11,7 @@ final class LongStorage extends NativeObjectStorage { private final long[] storage; - public LongStorage(final long[] storage) { + LongStorage(final long[] storage) { this.storage = storage; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java index 06f3edafb..fb9523433 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/wrappers/ShortStorage.java @@ -11,7 +11,7 @@ final class ShortStorage extends NativeObjectStorage { private final short[] storage; - public ShortStorage(final short[] storage) { + ShortStorage(final short[] storage) { this.storage = storage; } From 692a26c5680bcebdac61fd9b939fe8220145a317 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Fri, 9 Feb 2024 15:30:34 +0100 Subject: [PATCH 159/159] Move loadedLibraries back into context There seems to be some odd loading order problem on Windows. --- .../image/SqueakImageContext.java | 8 ++-- .../nodes/plugins/ffi/InterpreterProxy.java | 48 +------------------ .../plugins/ffi/PrimExternalCallNode.java | 45 ++++++++++++++++- 3 files changed, 48 insertions(+), 53 deletions(-) diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java index d716e49e7..c49a20b8c 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/image/SqueakImageContext.java @@ -11,6 +11,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; +import java.util.Map; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -168,6 +169,7 @@ public final class SqueakImageContext { /* Plugins */ @CompilationFinal private InterpreterProxy interpreterProxy; + public final Map loadedLibraries = new HashMap<>(); public final B2D b2d = new B2D(this); public final BitBlt bitblt = new BitBlt(this); public String[] dropPluginFileList = new String[0]; @@ -624,15 +626,11 @@ public boolean supportsNFI() { return env.getInternalLanguages().containsKey("nfi"); } - public InterpreterProxy getOrCreateInterpreterProxy() { + public InterpreterProxy getInterpreterProxy(final MaterializedFrame frame, final int numReceiverAndArguments) { if (interpreterProxy == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); interpreterProxy = new InterpreterProxy(this); } - return interpreterProxy; - } - - public InterpreterProxy getInterpreterProxy(final MaterializedFrame frame, final int numReceiverAndArguments) { return interpreterProxy.instanceFor(frame, numReceiverAndArguments); } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java index eeeac92af..dc19c9ae1 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/InterpreterProxy.java @@ -8,13 +8,10 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; import java.util.function.Predicate; import java.util.stream.Collectors; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.ArityException; import com.oracle.truffle.api.interop.InteropLibrary; @@ -53,7 +50,6 @@ public final class InterpreterProxy { // since this class is a singleton, a private instance variable will suffice @SuppressWarnings("FieldCanBeLocal") private final TruffleClosure[] closures; private final Object interpreterProxyPointer; - private final Map loadedLibraries = new HashMap<>(); /////////////////////////// // INTERPRETER VARIABLES // @@ -175,53 +171,11 @@ public InterpreterProxy instanceFor(final MaterializedFrame currentFrame, final return this; } - public Object lookupModuleLibrary(final String moduleName) { - final Object moduleLibrary = loadedLibraries.computeIfAbsent(moduleName, (String s) -> { - if (loadedLibraries.containsKey(moduleName)) { - // if moduleName was associated with null - return null; - } - final Object library; - try { - library = NFIUtils.loadLibrary(context, moduleName, "{ setInterpreter(POINTER):SINT64; }"); - } catch (AbstractTruffleException e) { - if (e.getMessage().equals("Unknown identifier: setInterpreter")) { - // module has no setInterpreter, cannot be loaded - return null; - } - throw e; - } - if (library == null) { - return null; - } - try { - // TODO: also call shutdownModule():SINT64 at some point - final Object initialiseModuleSymbol = NFIUtils.loadMember(context, library, "initialiseModule", "():SINT64"); - final InteropLibrary initialiseModuleInteropLibrary = NFIUtils.getInteropLibrary(initialiseModuleSymbol); - initialiseModuleInteropLibrary.execute(initialiseModuleSymbol); - } catch (UnknownIdentifierException e) { - // module has no initializer, ignore - } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { - throw CompilerDirectives.shouldNotReachHere(e); - } - try { - final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(library); - moduleInteropLibrary.invokeMember(library, "setInterpreter", getPointer()); - } catch (UnsupportedMessageException | ArityException | UnsupportedTypeException | UnknownIdentifierException e) { - throw CompilerDirectives.shouldNotReachHere(e); - } - return library; - }); - // computeIfAbsent would not put null value - loadedLibraries.putIfAbsent(moduleName, moduleLibrary); - return moduleLibrary; - } - /////////////////// // MISCELLANEOUS // /////////////////// - private Object getPointer() { + public Object getPointer() { return interpreterProxyPointer; } diff --git a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java index 8e1bca30a..baa2793e3 100644 --- a/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java +++ b/src/de.hpi.swa.trufflesqueak/src/de/hpi/swa/trufflesqueak/nodes/plugins/ffi/PrimExternalCallNode.java @@ -8,6 +8,7 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.exception.AbstractTruffleException; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.ArityException; @@ -35,7 +36,7 @@ public PrimExternalCallNode(final Object functionSymbol, final InteropLibrary fu public static PrimExternalCallNode load(final String moduleName, final String functionName, final int numReceiverAndArguments) { final SqueakImageContext context = SqueakImageContext.getSlow(); - final Object moduleLibrary = context.getOrCreateInterpreterProxy().lookupModuleLibrary(moduleName); + final Object moduleLibrary = lookupModuleLibrary(context, moduleName); if (moduleLibrary == null) { return null; // module not found } @@ -48,6 +49,48 @@ public static PrimExternalCallNode load(final String moduleName, final String fu } } + private static Object lookupModuleLibrary(final SqueakImageContext context, final String moduleName) { + final Object moduleLibrary = context.loadedLibraries.computeIfAbsent(moduleName, (String s) -> { + if (context.loadedLibraries.containsKey(moduleName)) { + // if moduleName was associated with null + return null; + } + final Object library; + try { + library = NFIUtils.loadLibrary(context, moduleName, "{ setInterpreter(POINTER):SINT64; }"); + } catch (AbstractTruffleException e) { + if (e.getMessage().equals("Unknown identifier: setInterpreter")) { + // module has no setInterpreter, cannot be loaded + return null; + } + throw e; + } + if (library == null) { + return null; + } + try { + // TODO: also call shutdownModule():SINT64 at some point + final Object initialiseModuleSymbol = NFIUtils.loadMember(context, library, "initialiseModule", "():SINT64"); + final InteropLibrary initialiseModuleInteropLibrary = NFIUtils.getInteropLibrary(initialiseModuleSymbol); + initialiseModuleInteropLibrary.execute(initialiseModuleSymbol); + } catch (UnknownIdentifierException e) { + // module has no initializer, ignore + } catch (UnsupportedTypeException | ArityException | UnsupportedMessageException e) { + throw CompilerDirectives.shouldNotReachHere(e); + } + try { + final InteropLibrary moduleInteropLibrary = NFIUtils.getInteropLibrary(library); + moduleInteropLibrary.invokeMember(library, "setInterpreter", context.getInterpreterProxy(null, 0).getPointer()); + } catch (UnsupportedMessageException | ArityException | UnsupportedTypeException | UnknownIdentifierException e) { + throw CompilerDirectives.shouldNotReachHere(e); + } + return library; + }); + // computeIfAbsent would not put null value + context.loadedLibraries.putIfAbsent(moduleName, moduleLibrary); + return moduleLibrary; + } + @Override public Object execute(final VirtualFrame frame) { return doExternalCall(frame.materialize());