From 3a46c2bf6f8a1655018606bbf391eb63ddefcf2d Mon Sep 17 00:00:00 2001 From: Andrea Peruffo Date: Wed, 2 Oct 2024 10:33:46 +0100 Subject: [PATCH] Primitive, non boxing, long array based MStack (#531) Supersede #447 this is a complete implementation, already passing all the tests up to the interpreter, can be tested with something like: ``` mvn clean install -pl runtime-tests -am ``` I started, but got a bit confused about the changes necessary in "aot", @electrum or @danielperano I would love some help in finalizing this PR :pray: and learning a bit more how `asm` works ... This is a prerequisite to avoid arrays construction [here](https://github.com/dylibso/chicory/pull/528/files#diff-f9f476fefd928e6770830c090018da2b95a054834c70bf472460d568fd1a9d2bR184), the plan is to open up the underlying array so that we can perform operations just using the offset :crossed_fingers: --- README.md | 22 +- .../com/dylibso/chicory/testing/Spectest.java | 2 +- aot/pom.xml | 1 - .../com/dylibso/chicory/aot/AotEmitters.java | 24 +- .../com/dylibso/chicory/aot/AotMachine.java | 43 +- .../com/dylibso/chicory/aot/AotMethods.java | 24 +- .../java/com/dylibso/chicory/aot/AotUtil.java | 148 +-- .../chicory/aot/HostFunctionInvoker.java | 5 +- ...alueWrapper.java => LongArrayWrapper.java} | 11 +- .../dylibso/chicory/aot/ValueConversions.java | 34 + .../ApprovalTest.verifyBrTable.approved.txt | 12 +- .../ApprovalTest.verifyBranching.approved.txt | 12 +- .../ApprovalTest.verifyFloat.approved.txt | 4 +- .../ApprovalTest.verifyHelloWasi.approved.txt | 54 +- .../ApprovalTest.verifyI32.approved.txt | 4 +- ...ApprovalTest.verifyI32Renamed.approved.txt | 4 +- .../ApprovalTest.verifyIterFact.approved.txt | 12 +- ...pprovalTest.verifyKitchenSink.approved.txt | 12 +- .../ApprovalTest.verifyMemory.approved.txt | 22 +- .../ApprovalTest.verifyStart.approved.txt | 22 +- .../ApprovalTest.verifyTrap.approved.txt | 4 +- .../java/com/dylibso/chicory/cli/Cli.java | 7 +- .../function/processor/FunctionProcessor.java | 50 +- .../test/resources/BasicMathGenerated.java | 58 +- .../src/test/resources/NestedGenerated.java | 41 +- .../test/resources/NoPackageGenerated.java | 41 +- .../src/test/resources/SimpleGenerated.java | 76 +- .../bench/BenchmarkFactorialExecution.java | 5 +- pom.xml | 1 + .../com/dylibso/chicory/testing/Spectest.java | 2 +- .../chicory/runtime/ConstantEvaluators.java | 3 +- .../chicory/runtime/ExportFunction.java | 3 +- .../chicory/runtime/GlobalInstance.java | 26 +- .../com/dylibso/chicory/runtime/Instance.java | 28 +- .../chicory/runtime/InterpreterMachine.java | 843 +++++++++--------- .../com/dylibso/chicory/runtime/MStack.java | 54 +- .../com/dylibso/chicory/runtime/Machine.java | 3 +- .../com/dylibso/chicory/runtime/Memory.java | 41 +- .../dylibso/chicory/runtime/OpcodeImpl.java | 14 +- .../dylibso/chicory/runtime/StackFrame.java | 18 +- .../chicory/runtime/TableInstance.java | 10 +- .../chicory/runtime/WasmFunctionHandle.java | 4 +- .../chicory/runtime/InterruptionTest.java | 3 +- .../dylibso/chicory/runtime/ModuleTest.java | 136 ++- .../dylibso/chicory/maven/JavaTestGen.java | 20 +- .../dylibso/chicory/maven/wast/WasmValue.java | 102 ++- .../dylibso/chicory/wabt/Wat2WasmTest.java | 7 +- .../dylibso/chicory/wasi/WasiPreview1.java | 8 +- .../chicory/wasi/WasiPreview1Test.java | 22 +- .../com/dylibso/chicory/wasm/types/Value.java | 201 ++--- .../dylibso/chicory/wasm/types/ValueTest.java | 12 +- 51 files changed, 1139 insertions(+), 1176 deletions(-) rename aot/src/main/java/com/dylibso/chicory/aot/{ValueWrapper.java => LongArrayWrapper.java} (55%) create mode 100644 aot/src/main/java/com/dylibso/chicory/aot/ValueConversions.java diff --git a/README.md b/README.md index 0bbe55f39..616916fcd 100644 --- a/README.md +++ b/README.md @@ -140,13 +140,13 @@ when we want to go back to Java. This export function takes an `i32` argument. W on the return value to get back the Java integer: ```java -Value result = iterFact.apply(Value.i32(5))[0]; -System.out.println("Result: " + result.asInt()); // should print 120 (5!) +long result = iterFact.apply(5)[0]; +System.out.println("Result: " + result); // should print 120 (5!) ``` @@ -192,7 +192,7 @@ Memory memory = instance.memory(); String message = "Hello, World!"; int len = message.getBytes().length; // allocate {len} bytes of memory, this returns a pointer to that memory -int ptr = alloc.apply(Value.i32(len))[0].asInt(); +int ptr = (int) alloc.apply(len)[0]; // We can now write the message to the module's memory: memory.writeString(ptr, message); ``` @@ -201,14 +201,14 @@ Now we can call `countVowels` with this pointer to the string. It will do it's j call `dealloc` to free that memory in the module. Though the module could do this itself if you want: ```java -Value result = countVowels.apply(Value.i32(ptr), Value.i32(len))[0]; -dealloc.apply(Value.i32(ptr), Value.i32(len)); -assert(3 == result.asInt()); // 3 vowels in Hello, World! +var result = countVowels.apply(ptr, len)[0]; +dealloc.apply(ptr, len); +assert(3L == result); // 3 vowels in Hello, World! ``` @@ -253,9 +253,9 @@ import com.dylibso.chicory.wasm.types.ValueType; var func = new HostFunction( "console", "log", - (Instance instance, Value... args) -> { // decompiled is: console_log(13, 0); - var len = args[0].asInt(); - var offset = args[1].asInt(); + (Instance instance, long... args) -> { // decompiled is: console_log(13, 0); + var len = (int) args[0]; + var offset = (int) args[1]; var message = instance.memory().readString(offset, len); println(message); return null; diff --git a/aot-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java b/aot-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java index b0051059a..7dbd9a0c3 100644 --- a/aot-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java +++ b/aot-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java @@ -19,7 +19,7 @@ // https://github.com/WebAssembly/spec/blob/ee82c8e50c5106e0cedada0a083d4cc4129034a2/interpreter/host/spectest.ml public final class Spectest { - private static final WasmFunctionHandle noop = (Instance instance, Value... args) -> null; + private static final WasmFunctionHandle noop = (Instance instance, long... args) -> null; private Spectest() {} diff --git a/aot/pom.xml b/aot/pom.xml index 559cd8a53..fd8c14533 100644 --- a/aot/pom.xml +++ b/aot/pom.xml @@ -34,7 +34,6 @@ org.ow2.asm asm-util - true com.approvaltests diff --git a/aot/src/main/java/com/dylibso/chicory/aot/AotEmitters.java b/aot/src/main/java/com/dylibso/chicory/aot/AotEmitters.java index 4a073e2c7..741a345b2 100644 --- a/aot/src/main/java/com/dylibso/chicory/aot/AotEmitters.java +++ b/aot/src/main/java/com/dylibso/chicory/aot/AotEmitters.java @@ -3,7 +3,6 @@ import static com.dylibso.chicory.aot.AotMethods.CHECK_INTERRUPTION; import static com.dylibso.chicory.aot.AotMethods.INSTANCE_READ_GLOBAL; import static com.dylibso.chicory.aot.AotMethods.INSTANCE_SET_ELEMENT; -import static com.dylibso.chicory.aot.AotMethods.INSTANCE_WRITE_GLOBAL; import static com.dylibso.chicory.aot.AotMethods.MEMORY_COPY; import static com.dylibso.chicory.aot.AotMethods.MEMORY_DROP; import static com.dylibso.chicory.aot.AotMethods.MEMORY_FILL; @@ -31,12 +30,14 @@ import static com.dylibso.chicory.aot.AotMethods.TABLE_SET; import static com.dylibso.chicory.aot.AotMethods.TABLE_SIZE; import static com.dylibso.chicory.aot.AotMethods.THROW_OUT_OF_BOUNDS_MEMORY_ACCESS; +import static com.dylibso.chicory.aot.AotMethods.WRITE_GLOBAL; import static com.dylibso.chicory.aot.AotUtil.StackSize; -import static com.dylibso.chicory.aot.AotUtil.boxer; import static com.dylibso.chicory.aot.AotUtil.callIndirectMethodName; import static com.dylibso.chicory.aot.AotUtil.callIndirectMethodType; import static com.dylibso.chicory.aot.AotUtil.emitInvokeStatic; import static com.dylibso.chicory.aot.AotUtil.emitInvokeVirtual; +import static com.dylibso.chicory.aot.AotUtil.emitJvmToLong; +import static com.dylibso.chicory.aot.AotUtil.emitLongToJvm; import static com.dylibso.chicory.aot.AotUtil.emitPop; import static com.dylibso.chicory.aot.AotUtil.jvmType; import static com.dylibso.chicory.aot.AotUtil.loadTypeOpcode; @@ -45,7 +46,6 @@ import static com.dylibso.chicory.aot.AotUtil.methodTypeFor; import static com.dylibso.chicory.aot.AotUtil.stackSize; import static com.dylibso.chicory.aot.AotUtil.storeTypeOpcode; -import static com.dylibso.chicory.aot.AotUtil.unboxer; import static com.dylibso.chicory.aot.AotUtil.validateArgumentType; import static com.dylibso.chicory.wasm.types.Value.REF_NULL_VALUE; @@ -218,21 +218,19 @@ public static void GLOBAL_GET(AotContext ctx, AnnotatedInstruction ins, MethodVi asm.visitLdcInsn(globalIndex); emitInvokeVirtual(asm, INSTANCE_READ_GLOBAL); - Method unboxer = unboxer(ctx.globalTypes().get(globalIndex)); - emitInvokeVirtual(asm, unboxer); + var globalType = ctx.globalTypes().get(globalIndex); + emitLongToJvm(asm, ctx.globalTypes().get(globalIndex)); - ctx.pushStackSize(stackSize(unboxer.getReturnType())); + ctx.pushStackSize(stackSize(globalType)); } public static void GLOBAL_SET(AotContext ctx, AnnotatedInstruction ins, MethodVisitor asm) { int globalIndex = (int) ins.operand(0); - emitInvokeStatic(asm, boxer(ctx.globalTypes().get(globalIndex))); - asm.visitVarInsn(Opcodes.ALOAD, ctx.instanceSlot()); - asm.visitInsn(Opcodes.SWAP); + emitJvmToLong(asm, ctx.globalTypes().get(globalIndex)); asm.visitLdcInsn(globalIndex); - asm.visitInsn(Opcodes.SWAP); - emitInvokeVirtual(asm, INSTANCE_WRITE_GLOBAL); + asm.visitVarInsn(Opcodes.ALOAD, ctx.instanceSlot()); + emitInvokeStatic(asm, WRITE_GLOBAL); } public static void TABLE_GET(AotContext ctx, AnnotatedInstruction ins, MethodVisitor asm) { @@ -772,8 +770,8 @@ private static void emitUnboxResult(MethodVisitor asm, AotContext ctx, List getFunctionTypes(Module module) { } @Override - public Value[] call(int funcId, Value[] args) throws ChicoryException { + public long[] call(int funcId, long[] args) throws ChicoryException { try { - return (Value[]) compiledFunctions[funcId].invokeExact(args); + return (long[]) compiledFunctions[funcId].invokeExact(args); } catch (ChicoryException e) { // propagate ChicoryExceptions throw e; @@ -528,19 +527,19 @@ private static MethodHandle adaptSignature(FunctionType type, MethodHandle handl var argTypes = type.params(); var argHandlers = new MethodHandle[type.params().size()]; for (int i = 0; i < argHandlers.length; i++) { - argHandlers[i] = unboxerHandle(argTypes.get(i)); + argHandlers[i] = longToJvmHandle(argTypes.get(i)); } MethodHandle result = filterArguments(handle, 0, argHandlers); - result = result.asSpreader(Value[].class, argTypes.size()); + result = result.asSpreader(long[].class, argTypes.size()); if (type.returns().isEmpty()) { - return result.asType(result.type().changeReturnType(Value[].class)); + return result.asType(result.type().changeReturnType(long[].class)); } if (type.returns().size() > 1) { return result; } - result = filterReturnValue(result, boxerHandle(type.returns().get(0))); - return filterReturnValue(result, ValueWrapper.HANDLE); + result = filterReturnValue(result, jvmToLongHandle(type.returns().get(0))); + return filterReturnValue(result, LongArrayWrapper.HANDLE); } private static void emitConstructor(ClassVisitor writer) { @@ -592,16 +591,16 @@ private static void compileHostFunction(int funcId, FunctionType type, MethodVis private static void emitBoxArguments(MethodVisitor asm, List types) { int slot = 0; - // box the arguments into Value[] + // box the arguments into long[] asm.visitLdcInsn(types.size()); - asm.visitTypeInsn(Opcodes.ANEWARRAY, getInternalName(Value.class)); + asm.visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_LONG); // long for (int i = 0; i < types.size(); i++) { asm.visitInsn(Opcodes.DUP); asm.visitLdcInsn(i); ValueType valueType = types.get(i); asm.visitVarInsn(loadTypeOpcode(valueType), slot); - emitInvokeStatic(asm, boxer(valueType)); - asm.visitInsn(Opcodes.AASTORE); + emitJvmToLong(asm, valueType); + asm.visitInsn(Opcodes.LASTORE); slot += slotCount(valueType); } } @@ -610,13 +609,13 @@ private static void emitUnboxResult(FunctionType type, MethodVisitor asm) { Class returnType = jvmReturnType(type); if (returnType == void.class) { asm.visitInsn(Opcodes.RETURN); - } else if (returnType == Value[].class) { + } else if (returnType == long[].class) { asm.visitInsn(Opcodes.ARETURN); } else { - // unbox the result from Value[0] + // unbox the result from long[0] asm.visitLdcInsn(0); - asm.visitInsn(Opcodes.AALOAD); - emitInvokeVirtual(asm, unboxer(type.returns().get(0))); + asm.visitInsn(Opcodes.LALOAD); + emitLongToJvm(asm, type.returns().get(0)); asm.visitInsn(returnTypeOpcode(type)); } } @@ -879,7 +878,7 @@ private FunctionType blockType(Instruction ins) { } private static MethodType valueMethodType(List types) { - return methodType(Value[].class, jvmTypes(types)); + return methodType(long[].class, jvmTypes(types)); } private static String valueMethodName(List types) { @@ -891,7 +890,7 @@ private static String valueMethodName(List types) { private static int returnTypeOpcode(FunctionType type) { Class returnType = jvmReturnType(type); - if (returnType == Value[].class) { + if (returnType == long[].class) { return Opcodes.ARETURN; } if (returnType == int.class) { diff --git a/aot/src/main/java/com/dylibso/chicory/aot/AotMethods.java b/aot/src/main/java/com/dylibso/chicory/aot/AotMethods.java index 220b2c07d..dc50fb633 100644 --- a/aot/src/main/java/com/dylibso/chicory/aot/AotMethods.java +++ b/aot/src/main/java/com/dylibso/chicory/aot/AotMethods.java @@ -12,7 +12,6 @@ import com.dylibso.chicory.wasm.exceptions.ChicoryException; import com.dylibso.chicory.wasm.types.Element; import com.dylibso.chicory.wasm.types.FunctionType; -import com.dylibso.chicory.wasm.types.Value; import java.lang.reflect.Method; import java.util.List; @@ -22,7 +21,7 @@ public final class AotMethods { static final Method CALL_INDIRECT; static final Method INSTANCE_CALL_HOST_FUNCTION; static final Method INSTANCE_READ_GLOBAL; - static final Method INSTANCE_WRITE_GLOBAL; + static final Method WRITE_GLOBAL; static final Method INSTANCE_SET_ELEMENT; static final Method MEMORY_COPY; static final Method MEMORY_FILL; @@ -60,15 +59,17 @@ public final class AotMethods { CALL_INDIRECT = AotMethods.class.getMethod( "callIndirect", - Value[].class, + long[].class, int.class, int.class, int.class, Instance.class); INSTANCE_CALL_HOST_FUNCTION = - Instance.class.getMethod("callHostFunction", int.class, Value[].class); + Instance.class.getMethod("callHostFunction", int.class, long[].class); INSTANCE_READ_GLOBAL = Instance.class.getMethod("readGlobal", int.class); - INSTANCE_WRITE_GLOBAL = Instance.class.getMethod("writeGlobal", int.class, Value.class); + WRITE_GLOBAL = + AotMethods.class.getMethod( + "writeGlobal", long.class, int.class, Instance.class); INSTANCE_SET_ELEMENT = Instance.class.getMethod("setElement", int.class, Element.class); MEMORY_COPY = AotMethods.class.getMethod( @@ -165,13 +166,13 @@ public final class AotMethods { private AotMethods() {} @UsedByGeneratedCode - public static Value[] callIndirect( - Value[] args, int typeId, int funcTableIdx, int tableIdx, Instance instance) { + public static long[] callIndirect( + long[] args, int typeId, int funcTableIdx, int tableIdx, Instance instance) { TableInstance table = instance.table(tableIdx); instance = requireNonNullElse(table.instance(funcTableIdx), instance); - int funcId = table.ref(funcTableIdx).asFuncRef(); + int funcId = table.ref(funcTableIdx); if (funcId == REF_NULL_VALUE) { throw new ChicoryException("uninitialized element " + funcTableIdx); } @@ -193,7 +194,7 @@ public static boolean isRefNull(int ref) { @UsedByGeneratedCode public static int tableGet(int index, int tableIndex, Instance instance) { - return OpcodeImpl.TABLE_GET(instance, tableIndex, index).asFuncRef(); + return (int) OpcodeImpl.TABLE_GET(instance, tableIndex, index); } @UsedByGeneratedCode @@ -341,4 +342,9 @@ public static void checkInterruption() { throw new ChicoryException("Thread interrupted"); } } + + @UsedByGeneratedCode + public static void writeGlobal(long value, int index, Instance instance) { + instance.writeGlobal(index, value); + } } diff --git a/aot/src/main/java/com/dylibso/chicory/aot/AotUtil.java b/aot/src/main/java/com/dylibso/chicory/aot/AotUtil.java index 52b098150..2df3ef63f 100644 --- a/aot/src/main/java/com/dylibso/chicory/aot/AotUtil.java +++ b/aot/src/main/java/com/dylibso/chicory/aot/AotUtil.java @@ -1,6 +1,7 @@ package com.dylibso.chicory.aot; import static com.dylibso.chicory.wasm.types.Value.REF_NULL_VALUE; +import static java.lang.invoke.MethodHandles.identity; import static java.lang.invoke.MethodHandles.publicLookup; import static java.lang.invoke.MethodType.methodType; import static org.objectweb.asm.Type.getInternalName; @@ -10,7 +11,6 @@ import com.dylibso.chicory.runtime.Memory; import com.dylibso.chicory.wasm.types.FunctionBody; import com.dylibso.chicory.wasm.types.FunctionType; -import com.dylibso.chicory.wasm.types.Value; import com.dylibso.chicory.wasm.types.ValueType; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -29,35 +29,38 @@ public enum StackSize { TWO } - private static final Method UNBOX_I32; - private static final Method UNBOX_I64; - private static final Method UNBOX_F32; - private static final Method UNBOX_F64; - private static final Method UNBOX_EXTREF; - private static final Method UNBOX_FUNCREF; - private static final Method BOX_I32; - private static final Method BOX_I64; - private static final Method BOX_F32; - private static final Method BOX_F64; - private static final Method BOX_EXTREF; - private static final Method BOX_FUNCREF; + private static final Method LONG_TO_I32; + private static final Method LONG_TO_F32; + private static final Method LONG_TO_F64; + private static final Method I32_TO_LONG; + private static final Method F32_TO_LONG; + private static final Method F64_TO_LONG; + private static final MethodHandle LONG_TO_I32_MH; + private static final MethodHandle LONG_TO_F32_MH; + private static final MethodHandle LONG_TO_F64_MH; + private static final MethodHandle I32_TO_LONG_MH; + private static final MethodHandle F32_TO_LONG_MH; + private static final MethodHandle F64_TO_LONG_MH; static { try { - UNBOX_I32 = Value.class.getMethod("asInt"); - UNBOX_I64 = Value.class.getMethod("asLong"); - UNBOX_F32 = Value.class.getMethod("asFloat"); - UNBOX_F64 = Value.class.getMethod("asDouble"); - UNBOX_EXTREF = Value.class.getMethod("asExtRef"); - UNBOX_FUNCREF = Value.class.getMethod("asFuncRef"); - BOX_I32 = Value.class.getMethod("i32", int.class); - BOX_I64 = Value.class.getMethod("i64", long.class); - BOX_F32 = Value.class.getMethod("fromFloat", float.class); - BOX_F64 = Value.class.getMethod("fromDouble", double.class); - BOX_EXTREF = Value.class.getMethod("externRef", int.class); - BOX_FUNCREF = Value.class.getMethod("funcRef", int.class); + LONG_TO_I32 = ValueConversions.class.getMethod("longToI32", long.class); + LONG_TO_F32 = ValueConversions.class.getMethod("longToF32", long.class); + LONG_TO_F64 = ValueConversions.class.getMethod("longToF64", long.class); + I32_TO_LONG = ValueConversions.class.getMethod("i32ToLong", int.class); + F32_TO_LONG = ValueConversions.class.getMethod("f32ToLong", float.class); + F64_TO_LONG = ValueConversions.class.getMethod("f64ToLong", double.class); + + LONG_TO_I32_MH = publicLookup().unreflect(LONG_TO_I32); + LONG_TO_F32_MH = publicLookup().unreflect(LONG_TO_F32); + LONG_TO_F64_MH = publicLookup().unreflect(LONG_TO_F64); + I32_TO_LONG_MH = publicLookup().unreflect(I32_TO_LONG); + F32_TO_LONG_MH = publicLookup().unreflect(F32_TO_LONG); + F64_TO_LONG_MH = publicLookup().unreflect(F64_TO_LONG); } catch (NoSuchMethodException e) { throw new AssertionError(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); } } @@ -120,57 +123,79 @@ public static ValueType localType(FunctionType type, FunctionBody body, int loca } } - public static Method unboxer(ValueType type) { + public static void emitLongToJvm(MethodVisitor asm, ValueType type) { switch (type) { case I32: - return UNBOX_I32; + case ExternRef: + case FuncRef: + asm.visitInsn(Opcodes.L2I); + return; case I64: - return UNBOX_I64; + return; case F32: - return UNBOX_F32; + emitInvokeStatic(asm, LONG_TO_F32); + return; case F64: - return UNBOX_F64; - case ExternRef: - return UNBOX_EXTREF; - case FuncRef: - return UNBOX_FUNCREF; + emitInvokeStatic(asm, LONG_TO_F64); + return; default: throw new IllegalArgumentException("Unsupported ValueType: " + type.name()); } } - public static Method boxer(ValueType type) { + public static void emitJvmToLong(MethodVisitor asm, ValueType type) { switch (type) { case I32: - return BOX_I32; + case ExternRef: + case FuncRef: + asm.visitInsn(Opcodes.I2L); + return; case I64: - return BOX_I64; + return; case F32: - return BOX_F32; + emitInvokeStatic(asm, F32_TO_LONG); + return; case F64: - return BOX_F64; - case ExternRef: - return BOX_EXTREF; - case FuncRef: - return BOX_FUNCREF; + emitInvokeStatic(asm, F64_TO_LONG); + return; default: throw new IllegalArgumentException("Unsupported ValueType: " + type.name()); } } - public static MethodHandle unboxerHandle(ValueType type) { - try { - return publicLookup().unreflect(unboxer(type)); - } catch (IllegalAccessException e) { - throw new AssertionError(e); + public static MethodHandle longToJvmHandle(ValueType type) { + switch (type) { + case I32: + case ExternRef: + case FuncRef: + return LONG_TO_I32_MH; + case I64: + // filterArguments: + // Null arguments in the array are treated as identity functions + return null; + case F32: + return LONG_TO_F32_MH; + case F64: + return LONG_TO_F64_MH; + default: + throw new IllegalArgumentException("Unsupported ValueType: " + type.name()); } } - public static MethodHandle boxerHandle(ValueType type) { - try { - return publicLookup().unreflect(boxer(type)); - } catch (IllegalAccessException e) { - throw new AssertionError(e); + public static MethodHandle jvmToLongHandle(ValueType type) { + switch (type) { + case I32: + case ExternRef: + case FuncRef: + return I32_TO_LONG_MH; + case I64: + return identity(long.class); + case F32: + return F32_TO_LONG_MH; + case F64: + return F64_TO_LONG_MH; + default: + throw new IllegalArgumentException("Unsupported ValueType: " + type.name()); } } @@ -202,7 +227,7 @@ public static Class jvmReturnType(FunctionType type) { case 1: return jvmType(type.returns().get(0)); default: - return Value[].class; + return long[].class; } } @@ -239,6 +264,21 @@ public static StackSize stackSize(Class clazz) { throw new IllegalArgumentException("Unsupported JVM type: " + clazz); } + public static StackSize stackSize(ValueType type) { + switch (type) { + case I32: + case F32: + case ExternRef: + case FuncRef: + return StackSize.ONE; + case I64: + case F64: + return StackSize.TWO; + default: + throw new IllegalArgumentException("Unsupported type: " + type); + } + } + public static int slotCount(ValueType type) { switch (type) { case I32: diff --git a/aot/src/main/java/com/dylibso/chicory/aot/HostFunctionInvoker.java b/aot/src/main/java/com/dylibso/chicory/aot/HostFunctionInvoker.java index a131ccd8b..aec9aa685 100644 --- a/aot/src/main/java/com/dylibso/chicory/aot/HostFunctionInvoker.java +++ b/aot/src/main/java/com/dylibso/chicory/aot/HostFunctionInvoker.java @@ -3,7 +3,6 @@ import static java.lang.invoke.MethodHandles.lookup; import com.dylibso.chicory.runtime.Instance; -import com.dylibso.chicory.wasm.types.Value; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -15,7 +14,7 @@ final class HostFunctionInvoker { HANDLE = lookup().unreflect( HostFunctionInvoker.class.getMethod( - "invoke", Instance.class, int.class, Value[].class)); + "invoke", Instance.class, int.class, long[].class)); } catch (NoSuchMethodException | IllegalAccessException e) { throw new LinkageError(e.getMessage(), e); } @@ -27,7 +26,7 @@ public static MethodHandle handleFor(Instance instance, int funcId) { return MethodHandles.insertArguments(HANDLE, 0, instance, funcId); } - public static Value[] invoke(Instance instance, int funcId, Value[] args) { + public static long[] invoke(Instance instance, int funcId, long[] args) { return instance.callHostFunction(funcId, args); } } diff --git a/aot/src/main/java/com/dylibso/chicory/aot/ValueWrapper.java b/aot/src/main/java/com/dylibso/chicory/aot/LongArrayWrapper.java similarity index 55% rename from aot/src/main/java/com/dylibso/chicory/aot/ValueWrapper.java rename to aot/src/main/java/com/dylibso/chicory/aot/LongArrayWrapper.java index 97b1d3a9f..fe062f24c 100644 --- a/aot/src/main/java/com/dylibso/chicory/aot/ValueWrapper.java +++ b/aot/src/main/java/com/dylibso/chicory/aot/LongArrayWrapper.java @@ -2,23 +2,22 @@ import static java.lang.invoke.MethodHandles.lookup; -import com.dylibso.chicory.wasm.types.Value; import java.lang.invoke.MethodHandle; -final class ValueWrapper { +final class LongArrayWrapper { public static final MethodHandle HANDLE; static { try { - HANDLE = lookup().unreflect(ValueWrapper.class.getMethod("wrap", Value.class)); + HANDLE = lookup().unreflect(LongArrayWrapper.class.getMethod("wrap", long.class)); } catch (NoSuchMethodException | IllegalAccessException e) { throw new LinkageError(e.getMessage(), e); } } - private ValueWrapper() {} + private LongArrayWrapper() {} - public static Value[] wrap(Value value) { - return new Value[] {value}; + public static long[] wrap(long value) { + return new long[] {value}; } } diff --git a/aot/src/main/java/com/dylibso/chicory/aot/ValueConversions.java b/aot/src/main/java/com/dylibso/chicory/aot/ValueConversions.java new file mode 100644 index 000000000..16d176cf9 --- /dev/null +++ b/aot/src/main/java/com/dylibso/chicory/aot/ValueConversions.java @@ -0,0 +1,34 @@ +package com.dylibso.chicory.aot; + +import com.dylibso.chicory.wasm.types.Value; + +public final class ValueConversions { + + private ValueConversions() {} + + // From long + public static int longToI32(long val) { + return (int) val; + } + + public static float longToF32(long val) { + return Value.longToFloat(val); + } + + public static double longToF64(long val) { + return Value.longToDouble(val); + } + + // To Long + public static long i32ToLong(int val) { + return val; + } + + public static long f32ToLong(float val) { + return Value.floatToLong(val); + } + + public static long f64ToLong(double val) { + return Value.doubleToLong(val); + } +} diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyBrTable.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyBrTable.approved.txt index 3657df70e..b881bbdae 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyBrTable.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyBrTable.approved.txt @@ -59,20 +59,20 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IIILcom/dylibso/chicory/runtime/Instance;)I ICONST_1 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE ICONST_0 ILOAD 1 ILOAD 2 ALOAD 3 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J ICONST_0 - AALOAD - INVOKEVIRTUAL com/dylibso/chicory/wasm/types/Value.asInt ()I + LALOAD + L2I IRETURN MAXSTACK = 5 MAXLOCALS = 4 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyBranching.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyBranching.approved.txt index 3b92e42d5..c5634f1ef 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyBranching.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyBranching.approved.txt @@ -52,20 +52,20 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IIILcom/dylibso/chicory/runtime/Instance;)I ICONST_1 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE ICONST_0 ILOAD 1 ILOAD 2 ALOAD 3 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J ICONST_0 - AALOAD - INVOKEVIRTUAL com/dylibso/chicory/wasm/types/Value.asInt ()I + LALOAD + L2I IRETURN MAXSTACK = 5 MAXLOCALS = 4 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyFloat.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyFloat.approved.txt index fb8ab54e9..1bf42c678 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyFloat.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyFloat.approved.txt @@ -26,12 +26,12 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IILcom/dylibso/chicory/runtime/Instance;)V ICONST_0 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG ICONST_0 ILOAD 0 ILOAD 1 ALOAD 2 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J RETURN MAXSTACK = 5 MAXLOCALS = 3 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyHelloWasi.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyHelloWasi.approved.txt index 8fbe88a37..3025330eb 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyHelloWasi.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyHelloWasi.approved.txt @@ -18,33 +18,33 @@ public final class com/dylibso/chicory/$gen/CompiledModule { ALOAD 5 ICONST_0 ICONST_4 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE DUP ICONST_1 ILOAD 1 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE DUP ICONST_2 ILOAD 2 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE DUP ICONST_3 ILOAD 3 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE - INVOKEVIRTUAL com/dylibso/chicory/runtime/Instance.callHostFunction (I[Lcom/dylibso/chicory/wasm/types/Value;)[Lcom/dylibso/chicory/wasm/types/Value; + I2L + LASTORE + INVOKEVIRTUAL com/dylibso/chicory/runtime/Instance.callHostFunction (I[J)[J ICONST_0 - AALOAD - INVOKEVIRTUAL com/dylibso/chicory/wasm/types/Value.asInt ()I + LALOAD + L2I IRETURN - MAXSTACK = 6 + MAXSTACK = 7 MAXLOCALS = 6 // access flags 0x9 @@ -75,35 +75,35 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IIIIIILcom/dylibso/chicory/runtime/Instance;)I ICONST_4 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE DUP ICONST_1 ILOAD 1 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE DUP ICONST_2 ILOAD 2 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE DUP ICONST_3 ILOAD 3 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE ICONST_0 ILOAD 4 ILOAD 5 ALOAD 6 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J ICONST_0 - AALOAD - INVOKEVIRTUAL com/dylibso/chicory/wasm/types/Value.asInt ()I + LALOAD + L2I IRETURN MAXSTACK = 5 MAXLOCALS = 7 @@ -111,12 +111,12 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_1(IILcom/dylibso/chicory/runtime/Instance;)V ICONST_0 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG ICONST_1 ILOAD 0 ILOAD 1 ALOAD 2 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J RETURN MAXSTACK = 5 MAXLOCALS = 3 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyI32.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyI32.approved.txt index a9332fe1e..8853701ea 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyI32.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyI32.approved.txt @@ -50,12 +50,12 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IILcom/dylibso/chicory/runtime/Instance;)V ICONST_0 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG ICONST_0 ILOAD 0 ILOAD 1 ALOAD 2 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J RETURN MAXSTACK = 5 MAXLOCALS = 3 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyI32Renamed.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyI32Renamed.approved.txt index 25dbedd05..161c6a6ac 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyI32Renamed.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyI32Renamed.approved.txt @@ -50,12 +50,12 @@ public final class FOO { // access flags 0x9 public static call_indirect_0(IILcom/dylibso/chicory/runtime/Instance;)V ICONST_0 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG ICONST_0 ILOAD 0 ILOAD 1 ALOAD 2 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J RETURN MAXSTACK = 5 MAXLOCALS = 3 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyIterFact.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyIterFact.approved.txt index 1d52a177a..6b6002f28 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyIterFact.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyIterFact.approved.txt @@ -51,20 +51,20 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IIILcom/dylibso/chicory/runtime/Instance;)I ICONST_1 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE ICONST_0 ILOAD 1 ILOAD 2 ALOAD 3 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J ICONST_0 - AALOAD - INVOKEVIRTUAL com/dylibso/chicory/wasm/types/Value.asInt ()I + LALOAD + L2I IRETURN MAXSTACK = 5 MAXLOCALS = 4 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyKitchenSink.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyKitchenSink.approved.txt index b5dc67bb3..35b83c0b4 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyKitchenSink.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyKitchenSink.approved.txt @@ -46,20 +46,20 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IIILcom/dylibso/chicory/runtime/Instance;)I ICONST_1 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE ICONST_0 ILOAD 1 ILOAD 2 ALOAD 3 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J ICONST_0 - AALOAD - INVOKEVIRTUAL com/dylibso/chicory/wasm/types/Value.asInt ()I + LALOAD + L2I IRETURN MAXSTACK = 5 MAXLOCALS = 4 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyMemory.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyMemory.approved.txt index 015954d30..f166d4abf 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyMemory.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyMemory.approved.txt @@ -52,20 +52,20 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IIILcom/dylibso/chicory/runtime/Instance;)I ICONST_1 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE ICONST_0 ILOAD 1 ILOAD 2 ALOAD 3 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J ICONST_0 - AALOAD - INVOKEVIRTUAL com/dylibso/chicory/wasm/types/Value.asInt ()I + LALOAD + L2I IRETURN MAXSTACK = 5 MAXLOCALS = 4 @@ -73,20 +73,18 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_1(JIILcom/dylibso/chicory/runtime/Instance;)J ICONST_1 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 LLOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i64 (J)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + LASTORE ICONST_1 ILOAD 2 ILOAD 3 ALOAD 4 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J ICONST_0 - AALOAD - INVOKEVIRTUAL com/dylibso/chicory/wasm/types/Value.asLong ()J + LALOAD LRETURN MAXSTACK = 5 MAXLOCALS = 5 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyStart.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyStart.approved.txt index 04076770c..2440aac35 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyStart.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyStart.approved.txt @@ -18,15 +18,15 @@ public final class com/dylibso/chicory/$gen/CompiledModule { ALOAD 2 ICONST_0 ICONST_1 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE - INVOKEVIRTUAL com/dylibso/chicory/runtime/Instance.callHostFunction (I[Lcom/dylibso/chicory/wasm/types/Value;)[Lcom/dylibso/chicory/wasm/types/Value; + I2L + LASTORE + INVOKEVIRTUAL com/dylibso/chicory/runtime/Instance.callHostFunction (I[J)[J RETURN - MAXSTACK = 6 + MAXSTACK = 7 MAXLOCALS = 3 // access flags 0x9 @@ -43,17 +43,17 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IIILcom/dylibso/chicory/runtime/Instance;)V ICONST_1 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG DUP ICONST_0 ILOAD 0 - INVOKESTATIC com/dylibso/chicory/wasm/types/Value.i32 (I)Lcom/dylibso/chicory/wasm/types/Value; - AASTORE + I2L + LASTORE ICONST_0 ILOAD 1 ILOAD 2 ALOAD 3 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J RETURN MAXSTACK = 5 MAXLOCALS = 4 @@ -61,12 +61,12 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_1(IILcom/dylibso/chicory/runtime/Instance;)V ICONST_0 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG ICONST_1 ILOAD 0 ILOAD 1 ALOAD 2 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J RETURN MAXSTACK = 5 MAXLOCALS = 3 diff --git a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyTrap.approved.txt b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyTrap.approved.txt index 4cad970c6..68321dc5b 100644 --- a/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyTrap.approved.txt +++ b/aot/src/test/resources/com/dylibso/chicory/approvals/ApprovalTest.verifyTrap.approved.txt @@ -46,12 +46,12 @@ public final class com/dylibso/chicory/$gen/CompiledModule { // access flags 0x9 public static call_indirect_0(IILcom/dylibso/chicory/runtime/Instance;)V ICONST_0 - ANEWARRAY com/dylibso/chicory/wasm/types/Value + NEWARRAY T_LONG ICONST_0 ILOAD 0 ILOAD 1 ALOAD 2 - INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([Lcom/dylibso/chicory/wasm/types/Value;IIILcom/dylibso/chicory/runtime/Instance;)[Lcom/dylibso/chicory/wasm/types/Value; + INVOKESTATIC com/dylibso/chicory/aot/AotMethods.callIndirect ([JIIILcom/dylibso/chicory/runtime/Instance;)[J RETURN MAXSTACK = 5 MAXLOCALS = 3 diff --git a/cli/src/main/java/com/dylibso/chicory/cli/Cli.java b/cli/src/main/java/com/dylibso/chicory/cli/Cli.java index 23ece7ef5..33fe40854 100644 --- a/cli/src/main/java/com/dylibso/chicory/cli/Cli.java +++ b/cli/src/main/java/com/dylibso/chicory/cli/Cli.java @@ -6,7 +6,6 @@ import com.dylibso.chicory.wasi.WasiOptions; import com.dylibso.chicory.wasi.WasiPreview1; import com.dylibso.chicory.wasm.Parser; -import com.dylibso.chicory.wasm.types.Value; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; @@ -76,9 +75,9 @@ public void run() { if (functionName != null) { var type = instance.exportType(functionName); var export = instance.export(functionName); - var params = new Value[type.params().size()]; + var params = new long[type.params().size()]; for (var i = 0; i < type.params().size(); i++) { - params[i] = new Value(type.params().get(i), Long.valueOf(arguments[i])); + params[i] = Long.valueOf(arguments[i]); } var result = export.apply(params); @@ -87,7 +86,7 @@ public void run() { if (result == null) { System.out.println(0); } else { - System.out.println(r.asLong()); // Check floating point results + System.out.println(r); // Check floating point results } } } diff --git a/function-processor/src/main/java/com/dylibso/chicory/function/processor/FunctionProcessor.java b/function-processor/src/main/java/com/dylibso/chicory/function/processor/FunctionProcessor.java index 2ae71baa8..901fd1bbe 100644 --- a/function-processor/src/main/java/com/dylibso/chicory/function/processor/FunctionProcessor.java +++ b/function-processor/src/main/java/com/dylibso/chicory/function/processor/FunctionProcessor.java @@ -18,6 +18,7 @@ import com.github.javaparser.ast.expr.ArrayAccessExpr; import com.github.javaparser.ast.expr.ArrayCreationExpr; import com.github.javaparser.ast.expr.ArrayInitializerExpr; +import com.github.javaparser.ast.expr.CastExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.FieldAccessExpr; import com.github.javaparser.ast.expr.IntegerLiteralExpr; @@ -151,19 +152,25 @@ private Expression processMethod( switch (parameter.asType().toString()) { case "int": paramTypes.add(valueType("I32")); - arguments.add(new MethodCallExpr(argExpr, "asInt")); + arguments.add(new CastExpr(parseType("int"), argExpr)); break; case "long": paramTypes.add(valueType("I64")); - arguments.add(new MethodCallExpr(argExpr, "asLong")); + arguments.add(argExpr); break; case "float": paramTypes.add(valueType("F32")); - arguments.add(new MethodCallExpr(argExpr, "asFloat")); + arguments.add( + new MethodCallExpr( + new NameExpr("Value"), "longToFloat", new NodeList<>(argExpr))); break; case "double": paramTypes.add(valueType("F64")); - arguments.add(new MethodCallExpr(argExpr, "asDouble")); + arguments.add( + new MethodCallExpr( + new NameExpr("Value"), + "longToDouble", + new NodeList<>(argExpr))); break; case "java.lang.String": if (annotatedWith(parameter, Buffer.class)) { @@ -175,15 +182,15 @@ private Expression processMethod( new MethodCallExpr(new NameExpr("instance"), "memory"), "readString", new NodeList<>( - new MethodCallExpr(argExpr, "asInt"), - new MethodCallExpr(lenExpr, "asInt")))); + new CastExpr(parseType("int"), argExpr), + new CastExpr(parseType("int"), lenExpr)))); } else if (annotatedWith(parameter, CString.class)) { paramTypes.add(valueType("I32")); arguments.add( new MethodCallExpr( new MethodCallExpr(new NameExpr("instance"), "memory"), "readCString", - new NodeList<>(new MethodCallExpr(argExpr, "asInt")))); + new NodeList<>(new CastExpr(parseType("int"), argExpr)))); } else { log(ERROR, "Missing annotation for WASM type: java.lang.String", parameter); throw new AbortProcessingException(); @@ -204,25 +211,33 @@ private Expression processMethod( // compute return type and conversion String returnName = executable.getReturnType().toString(); NodeList returnType = new NodeList<>(); - String returnExpr = null; + Expression returnExpr = null; switch (returnName) { case "void": break; case "int": returnType.add(valueType("I32")); - returnExpr = "i32"; + returnExpr = new CastExpr(parseType("long"), new NameExpr("result")); break; case "long": returnType.add(valueType("I64")); - returnExpr = "i64"; + returnExpr = new NameExpr("result"); break; case "float": returnType.add(valueType("F32")); - returnExpr = "fromFloat"; + returnExpr = + new MethodCallExpr( + new NameExpr("Value"), + "floatToLong", + new NodeList<>(new NameExpr("result"))); break; case "double": returnType.add(valueType("F64")); - returnExpr = "fromDouble"; + returnExpr = + new MethodCallExpr( + new NameExpr("Value"), + "doubleToLong", + new NodeList<>(new NameExpr("result"))); break; default: log(ERROR, "Unsupported WASM type: " + returnName, executable); @@ -240,16 +255,11 @@ private Expression processMethod( handleBody.addStatement(invocation).addStatement(new ReturnStmt(new NullLiteralExpr())); } else { var result = new VariableDeclarator(parseType(returnName), "result", invocation); - var boxed = - new MethodCallExpr( - new NameExpr("Value"), - returnExpr, - new NodeList<>(new NameExpr("result"))); var wrapped = new ArrayCreationExpr( - parseType("Value"), + parseType("long"), new NodeList<>(new ArrayCreationLevel()), - new ArrayInitializerExpr(new NodeList<>(boxed))); + new ArrayInitializerExpr(new NodeList<>(returnExpr))); handleBody .addStatement(new ExpressionStmt(new VariableDeclarationExpr(result))) .addStatement(new ReturnStmt(wrapped)); @@ -259,7 +269,7 @@ private Expression processMethod( var handle = new LambdaExpr() .addParameter("Instance", "instance") - .addParameter(new Parameter(parseType("Value"), "args").setVarArgs(true)) + .addParameter(new Parameter(parseType("long"), "args").setVarArgs(true)) .setEnclosingParameters(true) .setBody(handleBody); diff --git a/function-processor/src/test/resources/BasicMathGenerated.java b/function-processor/src/test/resources/BasicMathGenerated.java index fef5380ff..5fb3d1c6f 100644 --- a/function-processor/src/test/resources/BasicMathGenerated.java +++ b/function-processor/src/test/resources/BasicMathGenerated.java @@ -10,34 +10,38 @@ @Generated("com.dylibso.chicory.function.processor.FunctionProcessor") public final class BasicMath_ModuleFactory { - private BasicMath_ModuleFactory() {} + private BasicMath_ModuleFactory() { + } public static HostFunction[] toHostFunctions(BasicMath functions) { - return new HostFunction[] { - new HostFunction( - "math", "add", (Instance instance, Value... args) -> { - long result = functions.add(args[0].asInt(), args[1].asInt()); - return new Value[] { Value.i64(result) }; - }, - List.of(ValueType.I32, ValueType.I32), - List.of(ValueType.I64) - ), - new HostFunction( - "math", "square", (Instance instance, Value... args) -> { - double result = functions.pow2(args[0].asFloat()); - return new Value[] { Value.fromDouble(result) }; - }, - List.of(ValueType.F32), - List.of(ValueType.F64) - ), - new HostFunction( - "math", "floor_div", (Instance instance, Value... args) -> { - int result = functions.floorDiv(args[0].asInt(), args[1].asInt()) - return new Value[] { Value.i32(result) }; - }, - List.of(ValueType.I32, ValueType.I32), - List.of(ValueType.I32) - ), - }; + return new HostFunction[] { // + new HostFunction("math", + "add", + (Instance instance, long... args) -> { + long result = functions.add((int) args[0], + (int) args[1]); + return new long[] { result }; + }, + List.of(ValueType.I32, + ValueType.I32), + List.of(ValueType.I64)), // + new HostFunction("math", + "square", + (Instance instance, long... args) -> { + double result = functions.pow2(Value.longToFloat(args[0])); + return new long[] { Value.doubleToLong(result) }; + }, + List.of(ValueType.F32), + List.of(ValueType.F64)), // + new HostFunction("math", + "floor_div", + (Instance instance, long... args) -> { + int result = functions.floorDiv((int) args[0], + (int) args[1]); + return new long[] { (long) result }; + }, + List.of(ValueType.I32, + ValueType.I32), + List.of(ValueType.I32)) }; } } diff --git a/function-processor/src/test/resources/NestedGenerated.java b/function-processor/src/test/resources/NestedGenerated.java index e8b2e9144..f996b3da9 100644 --- a/function-processor/src/test/resources/NestedGenerated.java +++ b/function-processor/src/test/resources/NestedGenerated.java @@ -11,26 +11,29 @@ @Generated("com.dylibso.chicory.function.processor.FunctionProcessor") public final class Nested_ModuleFactory { - private Nested_ModuleFactory() {} + private Nested_ModuleFactory() { + } public static HostFunction[] toHostFunctions(Nested functions) { - return new HostFunction[] { - new HostFunction( - "nested", "print", (Instance instance, Value... args) -> { - functions.print(instance.memory(), args[0].asInt(), args[1].asInt()); - return null; - }, - List.of(ValueType.I32, ValueType.I32), - List.of() - ), - new HostFunction( - "nested", "exit", (Instance instance, Value... args) -> { - functions.exit(); - return null; - }, - List.of(), - List.of() - ), - }; + return new HostFunction[] { // + new HostFunction("nested", + "print", + (Instance instance, long... args) -> { + functions.print(instance.memory(), + (int) args[0], + (int) args[1]); + return null; + }, + List.of(ValueType.I32, + ValueType.I32), + List.of()), // + new HostFunction("nested", + "exit", + (Instance instance, long... args) -> { + functions.exit(); + return null; + }, + List.of(), + List.of()) }; } } diff --git a/function-processor/src/test/resources/NoPackageGenerated.java b/function-processor/src/test/resources/NoPackageGenerated.java index 2f2ef5495..d76fe5e15 100644 --- a/function-processor/src/test/resources/NoPackageGenerated.java +++ b/function-processor/src/test/resources/NoPackageGenerated.java @@ -8,26 +8,29 @@ @Generated("com.dylibso.chicory.function.processor.FunctionProcessor") public final class NoPackage_ModuleFactory { - private Nested_ModuleFactory() {} + private NoPackage_ModuleFactory() { + } public static HostFunction[] toHostFunctions(NoPackage functions) { - return new HostFunction[] { - new HostFunction( - "nopackage", "print", (Instance instance, Value... args) -> { - functions.print(instance.memory(), args[0].asInt(), args[1].asInt()); - return null; - }, - List.of(ValueType.I32, ValueType.I32), - List.of() - ), - new HostFunction( - "nopackage", "exit", (Instance instance, Value... args) -> { - functions.exit(); - return null; - }, - List.of(), - List.of() - ), - }; + return new HostFunction[] { // + new HostFunction("nopackage", + "print", + (Instance instance, long... args) -> { + functions.print(instance.memory(), + (int) args[0], + (int) args[1]); + return null; + }, + List.of(ValueType.I32, + ValueType.I32), + List.of()), // + new HostFunction("nopackage", + "exit", + (Instance instance, long... args) -> { + functions.exit(); + return null; + }, + List.of(), + List.of()) }; } } diff --git a/function-processor/src/test/resources/SimpleGenerated.java b/function-processor/src/test/resources/SimpleGenerated.java index a64ef8156..1321fe90c 100644 --- a/function-processor/src/test/resources/SimpleGenerated.java +++ b/function-processor/src/test/resources/SimpleGenerated.java @@ -10,43 +10,47 @@ @Generated("com.dylibso.chicory.function.processor.FunctionProcessor") public final class Simple_ModuleFactory { - private Simple_ModuleFactory() {} + private Simple_ModuleFactory() { + } public static HostFunction[] toHostFunctions(Simple functions) { - return new HostFunction[] { - new HostFunction( - "simple", "print", (Instance instance, Value... args) -> { - functions.print( - instance.memory().readString(args[0].asInt(), args[1].asInt())); - return null; - }, - List.of(ValueType.I32, ValueType.I32), - List.of() - ), - new HostFunction( - "simple", "printx", (Instance instance, Value... args) -> { - functions.printx(instance.memory().readCString(args[0].asInt())); - return null; - }, - List.of(ValueType.I32), - List.of() - ), - new HostFunction( - "simple", "random_get", (Instance instance, Value... args) -> { - functions.randomGet(instance.memory(), args[0].asInt(), args[1].asInt()); - return null; - }, - List.of(ValueType.I32, ValueType.I32), - List.of() - ), - new HostFunction( - "simple", "exit", (Instance instance, Value... args) -> { - functions.exit(); - return null; - }, - List.of(), - List.of() - ), - }; + return new HostFunction[] { // + new HostFunction("simple", + "print", + (Instance instance, long... args) -> { + functions.print(instance.memory().readString((int) args[0], + (int) args[1])); + return null; + }, + List.of(ValueType.I32, + ValueType.I32), + List.of()), // + new HostFunction("simple", + "printx", + (Instance instance, long... args) -> { + functions.printx(instance.memory().readCString((int) args[0])); + return null; + }, + List.of(ValueType.I32), + List.of()), // + new HostFunction("simple", + "random_get", + (Instance instance, long... args) -> { + functions.randomGet(instance.memory(), + (int) args[0], + (int) args[1]); + return null; + }, + List.of(ValueType.I32, + ValueType.I32), + List.of()), // + new HostFunction("simple", + "exit", + (Instance instance, long... args) -> { + functions.exit(); + return null; + }, + List.of(), + List.of()) }; } } diff --git a/jmh/src/main/java/com/dylibso/chicory/bench/BenchmarkFactorialExecution.java b/jmh/src/main/java/com/dylibso/chicory/bench/BenchmarkFactorialExecution.java index 84af92887..2c5b40163 100644 --- a/jmh/src/main/java/com/dylibso/chicory/bench/BenchmarkFactorialExecution.java +++ b/jmh/src/main/java/com/dylibso/chicory/bench/BenchmarkFactorialExecution.java @@ -4,7 +4,6 @@ import com.dylibso.chicory.runtime.ExportFunction; import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasm.Parser; -import com.dylibso.chicory.wasm.types.Value; import java.io.File; import java.util.concurrent.TimeUnit; import org.openjdk.jmh.annotations.Benchmark; @@ -51,12 +50,12 @@ public void setup() { @Benchmark @BenchmarkMode(Mode.Throughput) public void benchmarkInt(Blackhole bh) { - bh.consume(iterFactInt.apply(Value.i32(input))); + bh.consume(iterFactInt.apply(input)); } @Benchmark @BenchmarkMode(Mode.Throughput) public void benchmarkAot(Blackhole bh) { - bh.consume(iterFactAot.apply(Value.i32(input))); + bh.consume(iterFactAot.apply(input)); } } diff --git a/pom.xml b/pom.xml index 360121cf0..bb6df8504 100644 --- a/pom.xml +++ b/pom.xml @@ -567,6 +567,7 @@ com.dylibso.chicory:wasm-corpus org.junit.jupiter:junit-jupiter-engine + org.ow2.asm:asm-util diff --git a/runtime-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java b/runtime-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java index b0051059a..7dbd9a0c3 100644 --- a/runtime-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java +++ b/runtime-tests/src/test/java/com/dylibso/chicory/testing/Spectest.java @@ -19,7 +19,7 @@ // https://github.com/WebAssembly/spec/blob/ee82c8e50c5106e0cedada0a083d4cc4129034a2/interpreter/host/spectest.ml public final class Spectest { - private static final WasmFunctionHandle noop = (Instance instance, Value... args) -> null; + private static final WasmFunctionHandle noop = (Instance instance, long... args) -> null; private Spectest() {} diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/ConstantEvaluators.java b/runtime/src/main/java/com/dylibso/chicory/runtime/ConstantEvaluators.java index 877af3265..c89f03857 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/ConstantEvaluators.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/ConstantEvaluators.java @@ -71,7 +71,8 @@ public static Value computeConstantValue(Instance instance, List ex "constant expression required, initializer expression" + " cannot reference a mutable global"); } - return instance.readGlobal(idx); + var t = instance.imports().global(idx).instance().getType(); + return new Value(t, instance.readGlobal(idx)); } else { throw new InvalidException( "unknown global " diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/ExportFunction.java b/runtime/src/main/java/com/dylibso/chicory/runtime/ExportFunction.java index 541fb2133..b89cc9d68 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/ExportFunction.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/ExportFunction.java @@ -1,12 +1,11 @@ package com.dylibso.chicory.runtime; import com.dylibso.chicory.wasm.exceptions.ChicoryException; -import com.dylibso.chicory.wasm.types.Value; /** * This represents an Exported function from the Wasm module. */ @FunctionalInterface public interface ExportFunction { - Value[] apply(Value... args) throws ChicoryException; + long[] apply(long... args) throws ChicoryException; } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/GlobalInstance.java b/runtime/src/main/java/com/dylibso/chicory/runtime/GlobalInstance.java index 473ddc7bf..80b93c92a 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/GlobalInstance.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/GlobalInstance.java @@ -2,27 +2,39 @@ import com.dylibso.chicory.wasm.types.MutabilityType; import com.dylibso.chicory.wasm.types.Value; +import com.dylibso.chicory.wasm.types.ValueType; public class GlobalInstance { - private Value value; + private long value; + private final ValueType valueType; private Instance instance; private final MutabilityType mutabilityType; + public GlobalInstance(Value value) { + this(value, MutabilityType.Const); + } + public GlobalInstance(Value value, MutabilityType mutabilityType) { - this.value = value; + this.value = value.raw(); + this.valueType = value.type(); this.mutabilityType = mutabilityType; } - public GlobalInstance(Value value) { - this.value = value; - this.mutabilityType = MutabilityType.Const; + public long getValue() { + return value; } - public Value getValue() { - return value; + public ValueType getType() { + return valueType; } public void setValue(Value value) { + // globals can not be type polimorphic + assert (value.type() == valueType); + this.value = value.raw(); + } + + public void setValue(long value) { this.value = value; } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java b/runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java index b0bde610e..63b6aefab 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/Instance.java @@ -133,7 +133,7 @@ public Instance initialize(boolean start) { } for (int i = 0; i < initializers.size(); i++) { final List init = initializers.get(i); - var index = offset.asInt() + i; + int index = offset.asInt() + i; if (init.stream().filter(e -> e.opcode() != OpCode.END).count() > 1L) { throw new InvalidException( "constant expression required, type mismatch, expected [] but found" @@ -151,17 +151,17 @@ public Instance initialize(boolean start) { + value.type()); } if (ae.type() == ValueType.FuncRef) { - if (value.asFuncRef() != REF_NULL_VALUE) { + if (((int) value.raw()) != REF_NULL_VALUE) { try { - function(value.asFuncRef()); + function(value.raw()); } catch (InvalidException e) { throw new InvalidException("type mismatch, " + e.getMessage(), e); } } - table.setRef(index, value.asFuncRef(), inst); + table.setRef(index, (int) value.raw(), inst); } else { assert ae.type() == ValueType.ExternRef; - table.setRef(index, value.asExtRef(), inst); + table.setRef(index, (int) value.raw(), inst); } } } else if (el instanceof DeclarativeElement) { @@ -233,7 +233,8 @@ public ExportFunction export(String name) { { return args -> { assert (args.length == 0); - return new Value[] {readGlobal(export.index())}; + var v = readGlobal(export.index()); + return new long[] {v}; }; } default: @@ -267,14 +268,21 @@ public GlobalInstance global(int idx) { return globals[idx - importedGlobalsOffset]; } - public void writeGlobal(int idx, Value val) { + public void writeGlobal(int idx, long val) { if (idx < importedGlobalsOffset) { imports.global(idx).instance().setValue(val); } globals[idx - importedGlobalsOffset].setValue(val); } - public Value readGlobal(int idx) { + public ValueType readGlobalType(int idx) { + if (idx < importedGlobalsOffset) { + return imports.global(idx).instance().getType(); + } + return globals[idx - importedGlobalsOffset].getType(); + } + + public long readGlobal(int idx) { if (idx < importedGlobalsOffset) { return imports.global(idx).instance().getValue(); } @@ -336,7 +344,7 @@ public Machine getMachine() { return machine; } - public Value[] callHostFunction(int funcId, Value[] args) { + public long[] callHostFunction(int funcId, long[] args) { var imprt = imports.function(funcId); if (imprt == null) { throw new ChicoryException("Missing host import, number: " + funcId); @@ -430,7 +438,7 @@ private void validateExternalFunctionSignature(FunctionImport imprt, ExternalFun } private void validateHostGlobalType(GlobalImport i, ExternalGlobal g) { - if (i.type() != g.instance().getValue().type() + if (i.type() != g.instance().getType() || i.mutabilityType() != g.instance().getMutabilityType()) { throw new UnlinkableException("incompatible import type"); } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/InterpreterMachine.java b/runtime/src/main/java/com/dylibso/chicory/runtime/InterpreterMachine.java index 93fabd783..4c1e55218 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/InterpreterMachine.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/InterpreterMachine.java @@ -31,16 +31,16 @@ public InterpreterMachine(Instance instance) { } @Override - public Value[] call(int funcId, Value[] args) throws ChicoryException { + public long[] call(int funcId, long[] args) throws ChicoryException { return call(stack, instance, callStack, funcId, args, null, true); } - public static Value[] call( + public static long[] call( MStack stack, Instance instance, Deque callStack, int funcId, - Value[] args, + long[] args, FunctionType callType, boolean popResults) throws ChicoryException { @@ -96,7 +96,7 @@ public static Value[] call( } var totalResults = type.returns().size(); - var results = new Value[totalResults]; + var results = new long[totalResults]; for (var i = totalResults - 1; i >= 0; i--) { results[i] = stack.pop(); } @@ -283,16 +283,16 @@ static void eval(MStack stack, Instance instance, Deque callStack) break; // TODO 32bit and 64 bit operations are the same for now case I32_CONST: - stack.push(Value.i32(operands.get(0))); + stack.push(operands.get(0)); break; case I64_CONST: - stack.push(Value.i64(operands.get(0))); + stack.push(operands.get(0)); break; case F32_CONST: - stack.push(Value.f32(operands.get(0))); + stack.push(operands.get(0)); break; case F64_CONST: - stack.push(Value.f64(operands.get(0))); + stack.push(operands.get(0)); break; case I32_EQ: I32_EQ(stack); @@ -733,10 +733,10 @@ static void eval(MStack stack, Instance instance, Deque callStack) TABLE_GROW(stack, instance, operands); break; case REF_FUNC: - stack.push(Value.funcRef((int) operands.get(0))); + stack.push(operands.get(0)); break; case REF_NULL: - REF_NULL(stack, operands); + REF_NULL(stack); break; case REF_IS_NULL: REF_IS_NULL(stack); @@ -752,676 +752,675 @@ static void eval(MStack stack, Instance instance, Deque callStack) } private static void I32_GE_U(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_GE_U(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_GE_U(a, b)); } private static void I64_GT_U(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_GT_U(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_GT_U(a, b)); } private static void I32_GE_S(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_GE_S(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_GE_S(a, b)); } private static void I64_GE_U(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_GE_U(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_GE_U(a, b)); } private static void I64_GE_S(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_GE_S(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_GE_S(a, b)); } private static void I32_LE_S(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_LE_S(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_LE_S(a, b)); } private static void I32_LE_U(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_LE_U(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_LE_U(a, b)); } private static void I64_LE_S(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_LE_S(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_LE_S(a, b)); } private static void I64_LE_U(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_LE_U(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_LE_U(a, b)); } private static void F32_EQ(MStack stack) { - var b = stack.pop().asFloat(); - var a = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.F32_EQ(a, b))); + var b = Value.longToFloat(stack.pop()); + var a = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.F32_EQ(a, b)); } private static void F64_EQ(MStack stack) { - var b = stack.pop().asDouble(); - var a = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.F64_EQ(a, b))); + var b = Value.longToDouble(stack.pop()); + var a = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.F64_EQ(a, b)); } private static void I32_CLZ(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_CLZ(tos))); + var tos = (int) stack.pop(); + stack.push(OpcodeImpl.I32_CLZ(tos)); } private static void I32_CTZ(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_CTZ(tos))); + var tos = (int) stack.pop(); + stack.push(OpcodeImpl.I32_CTZ(tos)); } private static void I32_POPCNT(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_POPCNT(tos))); + var tos = (int) stack.pop(); + stack.push(OpcodeImpl.I32_POPCNT(tos)); } private static void I32_ADD(MStack stack) { - var a = stack.pop().asInt(); - var b = stack.pop().asInt(); - stack.push(Value.i32(a + b)); + var a = (int) stack.pop(); + var b = (int) stack.pop(); + stack.push(a + b); } private static void I64_ADD(MStack stack) { - var a = stack.pop().asLong(); - var b = stack.pop().asLong(); - stack.push(Value.i64(a + b)); + var a = stack.pop(); + var b = stack.pop(); + stack.push(a + b); } private static void I32_SUB(MStack stack) { - var a = stack.pop().asInt(); - var b = stack.pop().asInt(); - stack.push(Value.i32(b - a)); + var a = (int) stack.pop(); + var b = (int) stack.pop(); + stack.push(b - a); } private static void I64_SUB(MStack stack) { - var a = stack.pop().asLong(); - var b = stack.pop().asLong(); - stack.push(Value.i64(b - a)); + var a = stack.pop(); + var b = stack.pop(); + stack.push(b - a); } private static void I32_MUL(MStack stack) { - var a = stack.pop().asInt(); - var b = stack.pop().asInt(); - stack.push(Value.i32(a * b)); + var a = stack.pop(); + var b = stack.pop(); + stack.push(a * b); } private static void I64_MUL(MStack stack) { - var a = stack.pop().asLong(); - var b = stack.pop().asLong(); - stack.push(Value.i64(a * b)); + var a = stack.pop(); + var b = stack.pop(); + stack.push(a * b); } private static void I32_DIV_S(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_DIV_S(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_DIV_S(a, b)); } private static void I32_DIV_U(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_DIV_U(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_DIV_U(a, b)); } private static void I64_EXTEND_8_S(MStack stack) { - var tos = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_EXTEND_8_S(tos))); + var tos = stack.pop(); + stack.push(OpcodeImpl.I64_EXTEND_8_S(tos)); } private static void I64_EXTEND_16_S(MStack stack) { - var tos = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_EXTEND_16_S(tos))); + var tos = stack.pop(); + stack.push(OpcodeImpl.I64_EXTEND_16_S(tos)); } private static void I64_EXTEND_32_S(MStack stack) { - var tos = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_EXTEND_32_S(tos))); + var tos = stack.pop(); + stack.push(OpcodeImpl.I64_EXTEND_32_S(tos)); } private static void F64_CONVERT_I64_U(MStack stack) { - var tos = stack.pop().asLong(); - stack.push(Value.fromDouble(OpcodeImpl.F64_CONVERT_I64_U(tos))); + var tos = stack.pop(); + stack.push(Value.doubleToLong(OpcodeImpl.F64_CONVERT_I64_U(tos))); } private static void F64_CONVERT_I32_U(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.fromDouble(OpcodeImpl.F64_CONVERT_I32_U(tos))); + var tos = (int) stack.pop(); + stack.push(Value.doubleToLong(OpcodeImpl.F64_CONVERT_I32_U(tos))); } private static void F64_CONVERT_I32_S(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.fromDouble(OpcodeImpl.F64_CONVERT_I32_S(tos))); + var tos = (int) stack.pop(); + stack.push(Value.doubleToLong(OpcodeImpl.F64_CONVERT_I32_S(tos))); } private static void I32_EXTEND_8_S(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_EXTEND_8_S(tos))); + var tos = (int) stack.pop(); + stack.push(OpcodeImpl.I32_EXTEND_8_S(tos)); } private static void F64_NEAREST(MStack stack) { - var val = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_NEAREST(val))); + var val = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_NEAREST(val))); } private static void F32_NEAREST(MStack stack) { - var val = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_NEAREST(val))); + var val = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_NEAREST(val))); } private static void F64_TRUNC(MStack stack) { - var val = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_TRUNC(val))); + var val = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_TRUNC(val))); } private static void F64_CEIL(MStack stack) { - var val = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_CEIL(val))); + var val = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_CEIL(val))); } private static void F32_CEIL(MStack stack) { - var val = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_CEIL(val))); + var val = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_CEIL(val))); } private static void F64_FLOOR(MStack stack) { - var val = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_FLOOR(val))); + var val = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_FLOOR(val))); } private static void F32_FLOOR(MStack stack) { - var val = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_FLOOR(val))); + var val = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_FLOOR(val))); } private static void F64_SQRT(MStack stack) { - var val = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_SQRT(val))); + var val = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_SQRT(val))); } private static void F32_SQRT(MStack stack) { - var val = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_SQRT(val))); + var val = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_SQRT(val))); } private static void F64_MAX(MStack stack) { - var a = stack.pop().asDouble(); - var b = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_MAX(a, b))); + var a = Value.longToDouble(stack.pop()); + var b = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_MAX(a, b))); } private static void F32_MAX(MStack stack) { - var a = stack.pop().asFloat(); - var b = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_MAX(a, b))); + var a = Value.longToFloat(stack.pop()); + var b = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_MAX(a, b))); } private static void F64_MIN(MStack stack) { - var a = stack.pop().asDouble(); - var b = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_MIN(a, b))); + var a = Value.longToDouble(stack.pop()); + var b = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_MIN(a, b))); } private static void F32_MIN(MStack stack) { - var a = stack.pop().asFloat(); - var b = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_MIN(a, b))); + var a = Value.longToFloat(stack.pop()); + var b = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_MIN(a, b))); } private static void F64_DIV(MStack stack) { - var a = stack.pop().asDouble(); - var b = stack.pop().asDouble(); - stack.push(Value.fromDouble(b / a)); + var a = Value.longToDouble(stack.pop()); + var b = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(b / a)); } private static void F32_DIV(MStack stack) { - var a = stack.pop().asFloat(); - var b = stack.pop().asFloat(); - stack.push(Value.fromFloat(b / a)); + var a = Value.longToFloat(stack.pop()); + var b = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(b / a)); } private static void F64_MUL(MStack stack) { - var a = stack.pop().asDouble(); - var b = stack.pop().asDouble(); - stack.push(Value.fromDouble(b * a)); + var a = Value.longToDouble(stack.pop()); + var b = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(b * a)); } private static void F32_MUL(MStack stack) { - var a = stack.pop().asFloat(); - var b = stack.pop().asFloat(); - stack.push(Value.fromFloat(b * a)); + var a = Value.longToFloat(stack.pop()); + var b = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(b * a)); } private static void F64_SUB(MStack stack) { - var a = stack.pop().asDouble(); - var b = stack.pop().asDouble(); - stack.push(Value.fromDouble(b - a)); + var a = Value.longToDouble(stack.pop()); + var b = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(b - a)); } private static void F32_SUB(MStack stack) { - var a = stack.pop().asFloat(); - var b = stack.pop().asFloat(); - stack.push(Value.fromFloat(b - a)); + var a = Value.longToFloat(stack.pop()); + var b = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(b - a)); } private static void F64_ADD(MStack stack) { - var a = stack.pop().asDouble(); - var b = stack.pop().asDouble(); - stack.push(Value.fromDouble(a + b)); + var a = Value.longToDouble(stack.pop()); + var b = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(a + b)); } private static void F32_ADD(MStack stack) { - var a = stack.pop().asFloat(); - var b = stack.pop().asFloat(); - stack.push(Value.fromFloat(a + b)); + var a = Value.longToFloat(stack.pop()); + var b = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(a + b)); } private static void I32_ROTR(MStack stack) { - var c = stack.pop().asInt(); - var v = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_ROTR(v, c))); + var c = (int) stack.pop(); + var v = (int) stack.pop(); + stack.push(OpcodeImpl.I32_ROTR(v, c)); } private static void I32_ROTL(MStack stack) { - var c = stack.pop().asInt(); - var v = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_ROTL(v, c))); + var c = (int) stack.pop(); + var v = (int) stack.pop(); + stack.push(OpcodeImpl.I32_ROTL(v, c)); } private static void I32_SHR_U(MStack stack) { - var c = stack.pop().asInt(); - var v = stack.pop().asInt(); - stack.push(Value.i32(v >>> c)); + var c = (int) stack.pop(); + var v = (int) stack.pop(); + stack.push(v >>> c); } private static void I32_SHR_S(MStack stack) { - var c = stack.pop().asInt(); - var v = stack.pop().asInt(); - stack.push(Value.i32(v >> c)); + var c = (int) stack.pop(); + var v = (int) stack.pop(); + stack.push(v >> c); } private static void I32_SHL(MStack stack) { - var c = stack.pop().asInt(); - var v = stack.pop().asInt(); - stack.push(Value.i32(v << c)); + var c = (int) stack.pop(); + var v = (int) stack.pop(); + stack.push(v << c); } private static void I32_XOR(MStack stack) { - var a = stack.pop().asInt(); - var b = stack.pop().asInt(); - stack.push(Value.i32(a ^ b)); + var a = (int) stack.pop(); + var b = (int) stack.pop(); + stack.push(a ^ b); } private static void I32_OR(MStack stack) { - var a = stack.pop().asInt(); - var b = stack.pop().asInt(); - stack.push(Value.i32(a | b)); + var a = (int) stack.pop(); + var b = (int) stack.pop(); + stack.push(a | b); } private static void I32_AND(MStack stack) { - var a = stack.pop().asInt(); - var b = stack.pop().asInt(); - stack.push(Value.i32(a & b)); + var a = (int) stack.pop(); + var b = (int) stack.pop(); + stack.push(a & b); } private static void I64_POPCNT(MStack stack) { - var tos = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_POPCNT(tos))); + var tos = stack.pop(); + stack.push(OpcodeImpl.I64_POPCNT(tos)); } private static void I64_CTZ(MStack stack) { var tos = stack.pop(); - stack.push(Value.i64(OpcodeImpl.I64_CTZ(tos.asLong()))); + stack.push(OpcodeImpl.I64_CTZ(tos)); } private static void I64_CLZ(MStack stack) { var tos = stack.pop(); - stack.push(Value.i64(OpcodeImpl.I64_CLZ(tos.asLong()))); + stack.push(OpcodeImpl.I64_CLZ(tos)); } private static void I64_ROTR(MStack stack) { - var c = stack.pop().asLong(); - var v = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_ROTR(v, c))); + var c = stack.pop(); + var v = stack.pop(); + stack.push(OpcodeImpl.I64_ROTR(v, c)); } private static void I64_ROTL(MStack stack) { - var c = stack.pop().asLong(); - var v = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_ROTL(v, c))); + var c = stack.pop(); + var v = stack.pop(); + stack.push(OpcodeImpl.I64_ROTL(v, c)); } private static void I64_REM_U(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_REM_U(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_REM_U(a, b)); } private static void I64_REM_S(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_REM_S(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_REM_S(a, b)); } private static void I64_SHR_U(MStack stack) { - var c = stack.pop().asLong(); - var v = stack.pop().asLong(); - stack.push(Value.i64(v >>> c)); + var c = stack.pop(); + var v = stack.pop(); + stack.push(v >>> c); } private static void I64_SHR_S(MStack stack) { - var c = stack.pop().asLong(); - var v = stack.pop().asLong(); - stack.push(Value.i64(v >> c)); + var c = stack.pop(); + var v = stack.pop(); + stack.push(v >> c); } private static void I64_SHL(MStack stack) { - var c = stack.pop().asLong(); - var v = stack.pop().asLong(); - stack.push(Value.i64(v << c)); + var c = stack.pop(); + var v = stack.pop(); + stack.push(v << c); } private static void I64_XOR(MStack stack) { - var a = stack.pop().asLong(); - var b = stack.pop().asLong(); - stack.push(Value.i64(a ^ b)); + var a = stack.pop(); + var b = stack.pop(); + stack.push(a ^ b); } private static void I64_OR(MStack stack) { - var a = stack.pop().asLong(); - var b = stack.pop().asLong(); - stack.push(Value.i64(a | b)); + var a = stack.pop(); + var b = stack.pop(); + stack.push(a | b); } private static void I64_AND(MStack stack) { - var a = stack.pop().asLong(); - var b = stack.pop().asLong(); - stack.push(Value.i64(a & b)); + var a = stack.pop(); + var b = stack.pop(); + stack.push(a & b); } private static void I32_REM_U(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_REM_U(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_REM_U(a, b)); } private static void I32_REM_S(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_REM_S(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_REM_S(a, b)); } private static void I64_DIV_U(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_DIV_U(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_DIV_U(a, b)); } private static void I64_DIV_S(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i64(OpcodeImpl.I64_DIV_S(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_DIV_S(a, b)); } private static void I64_GT_S(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i32(OpcodeImpl.I64_GT_S(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_GT_S(a, b)); } private static void I32_GT_U(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_GT_U(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_GT_U(a, b)); } private static void I32_GT_S(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_GT_S(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_GT_S(a, b)); } private static void I64_LT_U(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i32(OpcodeImpl.I64_LT_U(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_LT_U(a, b)); } private static void I64_LT_S(MStack stack) { - var b = stack.pop().asLong(); - var a = stack.pop().asLong(); - stack.push(Value.i32(OpcodeImpl.I64_LT_S(a, b))); + var b = stack.pop(); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_LT_S(a, b)); } private static void I32_LT_U(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_LT_U(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_LT_U(a, b)); } private static void I32_LT_S(MStack stack) { - var b = stack.pop().asInt(); - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_LT_S(a, b))); + var b = (int) stack.pop(); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_LT_S(a, b)); } private static void I64_EQZ(MStack stack) { - var a = stack.pop().asLong(); - stack.push(Value.i32(OpcodeImpl.I64_EQZ(a))); + var a = stack.pop(); + stack.push(OpcodeImpl.I64_EQZ(a)); } private static void I32_EQZ(MStack stack) { - var a = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_EQZ(a))); + var a = (int) stack.pop(); + stack.push(OpcodeImpl.I32_EQZ(a)); } private static void I64_NE(MStack stack) { - var a = stack.pop().asLong(); - var b = stack.pop().asLong(); - stack.push(Value.i32(OpcodeImpl.I64_NE(a, b))); + var a = stack.pop(); + var b = stack.pop(); + stack.push(OpcodeImpl.I64_NE(a, b)); } private static void I32_NE(MStack stack) { - var a = stack.pop().asInt(); - var b = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_NE(a, b))); + var a = (int) stack.pop(); + var b = (int) stack.pop(); + stack.push(OpcodeImpl.I32_NE(a, b)); } private static void I64_EQ(MStack stack) { - var a = stack.pop().asLong(); - var b = stack.pop().asLong(); - stack.push(Value.i32(OpcodeImpl.I64_EQ(a, b))); + var a = stack.pop(); + var b = stack.pop(); + stack.push(OpcodeImpl.I64_EQ(a, b)); } private static void I32_EQ(MStack stack) { - var a = stack.pop().asInt(); - var b = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_EQ(a, b))); + var a = (int) stack.pop(); + var b = (int) stack.pop(); + stack.push(OpcodeImpl.I32_EQ(a, b)); } private static void MEMORY_SIZE(MStack stack, Instance instance) { var sz = instance.memory().pages(); - stack.push(Value.i32(sz)); + stack.push(sz); } private static void I64_STORE32(MStack stack, Instance instance, Operands operands) { - var value = stack.pop().asLong(); - var ptr = (int) (operands.get(1) + stack.pop().asInt()); + var value = stack.pop(); + var ptr = (int) (operands.get(1) + (int) stack.pop()); instance.memory().writeI32(ptr, (int) value); } private static void I64_STORE8(MStack stack, Instance instance, Operands operands) { - var value = stack.pop().asByte(); - var ptr = (int) (operands.get(1) + stack.pop().asInt()); + var value = (byte) stack.pop(); + var ptr = (int) (operands.get(1) + (int) stack.pop()); instance.memory().writeByte(ptr, value); } private static void F64_PROMOTE_F32(MStack stack) { var tos = stack.pop(); - stack.push(Value.fromDouble(tos.asFloat())); + stack.push(Double.doubleToRawLongBits(Float.intBitsToFloat((int) tos))); } private static void F64_REINTERPRET_I64(MStack stack) { - long tos = stack.pop().asLong(); - stack.push(Value.fromDouble(OpcodeImpl.F64_REINTERPRET_I64(tos))); + long tos = stack.pop(); + stack.push(Value.doubleToLong(OpcodeImpl.F64_REINTERPRET_I64(tos))); } private static void I32_WRAP_I64(MStack stack) { - var tos = stack.pop(); - stack.push(Value.i32(tos.asInt())); + int tos = (int) stack.pop(); + stack.push(tos); } private static void I64_EXTEND_I32_S(MStack stack) { - var tos = stack.pop(); - stack.push(Value.i64(tos.asInt())); + int tos = (int) stack.pop(); + stack.push(tos); } private static void I64_EXTEND_I32_U(MStack stack) { - int tos = stack.pop().asInt(); - stack.push(Value.i64(OpcodeImpl.I64_EXTEND_I32_U(tos))); + var tos = stack.pop(); + stack.push(OpcodeImpl.I64_EXTEND_I32_U((int) tos)); } private static void I32_REINTERPRET_F32(MStack stack) { - float tos = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.I32_REINTERPRET_F32(tos))); + float tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I32_REINTERPRET_F32(tos)); } private static void I64_REINTERPRET_F64(MStack stack) { - double tos = stack.pop().asDouble(); - stack.push(Value.i64(OpcodeImpl.I64_REINTERPRET_F64(tos))); + double tos = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.I64_REINTERPRET_F64(tos)); } private static void F32_REINTERPRET_I32(MStack stack) { - int tos = stack.pop().asInt(); - stack.push(Value.fromFloat(OpcodeImpl.F32_REINTERPRET_I32(tos))); + int tos = (int) stack.pop(); + stack.push(Value.floatToLong(OpcodeImpl.F32_REINTERPRET_I32(tos))); } private static void F32_DEMOTE_F64(MStack stack) { - var val = stack.pop().asDouble(); + var val = Value.longToDouble(stack.pop()); - stack.push(Value.fromFloat((float) val)); + stack.push(Value.floatToLong((float) val)); } private static void F32_CONVERT_I32_S(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.fromFloat(OpcodeImpl.F32_CONVERT_I32_S(tos))); + var tos = (int) stack.pop(); + stack.push(Value.floatToLong(OpcodeImpl.F32_CONVERT_I32_S(tos))); } private static void I32_EXTEND_16_S(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.i32(OpcodeImpl.I32_EXTEND_16_S(tos))); + var tos = (int) stack.pop(); + stack.push(OpcodeImpl.I32_EXTEND_16_S(tos)); } private static void I64_TRUNC_F64_S(MStack stack) { - double tos = stack.pop().asDouble(); - stack.push(Value.i64(OpcodeImpl.I64_TRUNC_F64_S(tos))); + double tos = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.I64_TRUNC_F64_S(tos)); } private static void F32_COPYSIGN(MStack stack) { - var b = stack.pop().asFloat(); - var a = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_COPYSIGN(a, b))); + var b = Value.longToFloat(stack.pop()); + var a = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_COPYSIGN(a, b))); } private static void F32_ABS(MStack stack) { - var val = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_ABS(val))); + var val = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_ABS(val))); } private static void F64_ABS(MStack stack) { - var val = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_ABS(val))); + var val = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_ABS(val))); } private static void F32_NE(MStack stack) { - var b = stack.pop().asFloat(); - var a = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.F32_NE(a, b))); + var b = Value.longToFloat(stack.pop()); + var a = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.F32_NE(a, b)); } private static void F64_NE(MStack stack) { - var b = stack.pop().asDouble(); - var a = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.F64_NE(a, b))); + var b = Value.longToDouble(stack.pop()); + var a = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.F64_NE(a, b)); } private static void F32_LT(MStack stack) { - var b = stack.pop().asFloat(); - var a = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.F32_LT(a, b))); + var b = Value.longToFloat(stack.pop()); + var a = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.F32_LT(a, b)); } private static void F64_LT(MStack stack) { - var b = stack.pop().asDouble(); - var a = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.F64_LT(a, b))); + var b = Value.longToDouble(stack.pop()); + var a = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.F64_LT(a, b)); } private static void F32_LE(MStack stack) { - var b = stack.pop().asFloat(); - var a = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.F32_LE(a, b))); + var b = Value.longToFloat(stack.pop()); + var a = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.F32_LE(a, b)); } private static void F64_LE(MStack stack) { - var b = stack.pop().asDouble(); - var a = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.F64_LE(a, b))); + var b = Value.longToDouble(stack.pop()); + var a = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.F64_LE(a, b)); } private static void F32_GE(MStack stack) { - var b = stack.pop().asFloat(); - var a = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.F32_GE(a, b))); + var b = Value.longToFloat(stack.pop()); + var a = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.F32_GE(a, b)); } private static void F64_GE(MStack stack) { - var b = stack.pop().asDouble(); - var a = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.F64_GE(a, b))); + var b = Value.longToDouble(stack.pop()); + var a = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.F64_GE(a, b)); } private static void F32_GT(MStack stack) { - var b = stack.pop().asFloat(); - var a = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.F32_GT(a, b))); + var b = Value.longToFloat(stack.pop()); + var a = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.F32_GT(a, b)); } private static void F64_GT(MStack stack) { - var b = stack.pop().asDouble(); - var a = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.F64_GT(a, b))); + var b = Value.longToDouble(stack.pop()); + var a = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.F64_GT(a, b)); } private static void F32_CONVERT_I32_U(MStack stack) { - var tos = stack.pop().asInt(); - stack.push(Value.fromFloat(OpcodeImpl.F32_CONVERT_I32_U(tos))); + var tos = (int) stack.pop(); + stack.push(Value.floatToLong(OpcodeImpl.F32_CONVERT_I32_U(tos))); } private static void F32_CONVERT_I64_S(MStack stack) { - var tos = stack.pop().asLong(); - stack.push(Value.fromFloat(OpcodeImpl.F32_CONVERT_I64_S(tos))); + var tos = stack.pop(); + stack.push(Value.floatToLong(OpcodeImpl.F32_CONVERT_I64_S(tos))); } - private static void REF_NULL(MStack stack, Operands operands) { - var type = ValueType.forId((int) operands.get(0)); - stack.push(new Value(type, (long) REF_NULL_VALUE)); + private static void REF_NULL(MStack stack) { + stack.push(REF_NULL_VALUE); } private static void ELEM_DROP(Instance instance, Operands operands) { @@ -1431,10 +1430,7 @@ private static void ELEM_DROP(Instance instance, Operands operands) { private static void REF_IS_NULL(MStack stack) { var val = stack.pop(); - stack.push( - val.equals(Value.EXTREF_NULL) || val.equals(Value.FUNCREF_NULL) - ? Value.TRUE - : Value.FALSE); + stack.push(((val == REF_NULL_VALUE) ? Value.TRUE : Value.FALSE)); } private static void DATA_DROP(Instance instance, Operands operands) { @@ -1443,35 +1439,34 @@ private static void DATA_DROP(Instance instance, Operands operands) { } private static void F64_CONVERT_I64_S(MStack stack) { - var tos = stack.pop().asLong(); - stack.push(Value.fromDouble(OpcodeImpl.F64_CONVERT_I64_S(tos))); + var tos = stack.pop(); + stack.push(Value.doubleToLong(OpcodeImpl.F64_CONVERT_I64_S(tos))); } private static void TABLE_GROW(MStack stack, Instance instance, Operands operands) { var tableidx = (int) operands.get(0); var table = instance.table(tableidx); - var size = stack.pop().asInt(); - var valValue = stack.pop(); - var val = valValue.asExtRef(); + var size = (int) stack.pop(); + var val = (int) stack.pop(); var res = table.grow(size, val, instance); - stack.push(Value.i32(res)); + stack.push(res); } private static void TABLE_SIZE(MStack stack, Instance instance, Operands operands) { var tableidx = (int) operands.get(0); var table = instance.table(tableidx); - stack.push(Value.i32(table.size())); + stack.push(table.size()); } private static void TABLE_FILL(MStack stack, Instance instance, Operands operands) { var tableidx = (int) operands.get(0); - var size = stack.pop().asInt(); - var val = stack.pop().asExtRef(); - var offset = stack.pop().asInt(); + var size = (int) stack.pop(); + var val = (int) stack.pop(); + var offset = (int) stack.pop(); OpcodeImpl.TABLE_FILL(instance, tableidx, size, val, offset); } @@ -1480,9 +1475,9 @@ private static void TABLE_COPY(MStack stack, Instance instance, Operands operand var tableidxSrc = (int) operands.get(1); var tableidxDst = (int) operands.get(0); - var size = stack.pop().asInt(); - var s = stack.pop().asInt(); - var d = stack.pop().asInt(); + var size = (int) stack.pop(); + var s = (int) stack.pop(); + var d = (int) stack.pop(); OpcodeImpl.TABLE_COPY(instance, tableidxSrc, tableidxDst, size, s, d); } @@ -1494,9 +1489,9 @@ private static void MEMORY_COPY(MStack stack, Instance instance, Operands operan throw new WASMRuntimeException( "We don't support non zero index for memory: " + memidxSrc + " " + memidxDst); } - var size = stack.pop().asInt(); - var offset = stack.pop().asInt(); - var destination = stack.pop().asInt(); + var size = (int) stack.pop(); + var offset = (int) stack.pop(); + var destination = (int) stack.pop(); instance.memory().copy(destination, offset, size); } @@ -1504,9 +1499,9 @@ private static void TABLE_INIT(MStack stack, Instance instance, Operands operand var tableidx = (int) operands.get(1); var elementidx = (int) operands.get(0); - var size = stack.pop().asInt(); - var elemidx = stack.pop().asInt(); - var offset = stack.pop().asInt(); + var size = (int) stack.pop(); + var elemidx = (int) stack.pop(); + var offset = (int) stack.pop(); OpcodeImpl.TABLE_INIT(instance, tableidx, elementidx, size, elemidx, offset); } @@ -1517,101 +1512,101 @@ private static void MEMORY_INIT(MStack stack, Instance instance, Operands operan if (memidx != 0) { throw new WASMRuntimeException("We don't support non zero index for memory: " + memidx); } - var size = stack.pop().asInt(); - var offset = stack.pop().asInt(); - var destination = stack.pop().asInt(); + var size = (int) stack.pop(); + var offset = (int) stack.pop(); + var destination = (int) stack.pop(); instance.memory().initPassiveSegment(segmentId, destination, offset, size); } private static void I64_TRUNC_F32_S(MStack stack) { - var tos = stack.pop().asFloat(); - stack.push(Value.i64(OpcodeImpl.I64_TRUNC_F32_S(tos))); + var tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I64_TRUNC_F32_S(tos)); } private static void I32_TRUNC_F64_U(MStack stack) { - double tos = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.I32_TRUNC_F64_U(tos))); + double tos = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.I32_TRUNC_F64_U(tos)); } private static void I32_TRUNC_F64_S(MStack stack) { - var tos = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.I32_TRUNC_F64_S(tos))); + var tos = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.I32_TRUNC_F64_S(tos)); } private static void I64_TRUNC_SAT_F64_U(MStack stack) { - double tos = stack.pop().asDouble(); - stack.push(Value.i64(OpcodeImpl.I64_TRUNC_SAT_F64_U(tos))); + double tos = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.I64_TRUNC_SAT_F64_U(tos)); } private static void I64_TRUNC_SAT_F64_S(MStack stack) { - var tos = stack.pop().asDouble(); - stack.push(Value.i64(OpcodeImpl.I64_TRUNC_SAT_F64_S(tos))); + var tos = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.I64_TRUNC_SAT_F64_S(tos)); } private static void I64_TRUNC_SAT_F32_U(MStack stack) { - var tos = stack.pop().asFloat(); - stack.push(Value.i64(OpcodeImpl.I64_TRUNC_SAT_F32_U(tos))); + var tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I64_TRUNC_SAT_F32_U(tos)); } private static void I64_TRUNC_SAT_F32_S(MStack stack) { - var tos = stack.pop().asFloat(); - stack.push(Value.i64(OpcodeImpl.I64_TRUNC_SAT_F32_S(tos))); + var tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I64_TRUNC_SAT_F32_S(tos)); } private static void I64_TRUNC_F64_U(MStack stack) { - var tos = stack.pop().asDouble(); - stack.push(Value.i64(OpcodeImpl.I64_TRUNC_F64_U(tos))); + var tos = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.I64_TRUNC_F64_U(tos)); } private static void I64_TRUNC_F32_U(MStack stack) { - var tos = stack.pop().asFloat(); - stack.push(Value.i64(OpcodeImpl.I64_TRUNC_F32_U(tos))); + var tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I64_TRUNC_F32_U(tos)); } private static void F32_CONVERT_I64_U(MStack stack) { - var tos = stack.pop().asLong(); - stack.push(Value.fromFloat(OpcodeImpl.F32_CONVERT_I64_U(tos))); + var tos = stack.pop(); + stack.push(Value.floatToLong(OpcodeImpl.F32_CONVERT_I64_U(tos))); } private static void I32_TRUNC_F32_U(MStack stack) { - var tos = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.I32_TRUNC_F32_U(tos))); + var tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I32_TRUNC_F32_U(tos)); } private static void I32_TRUNC_SAT_F64_U(MStack stack) { - double tos = Double.longBitsToDouble(stack.pop().asLong()); - stack.push(Value.i32(OpcodeImpl.I32_TRUNC_SAT_F64_U(tos))); + double tos = Double.longBitsToDouble(stack.pop()); + stack.push(OpcodeImpl.I32_TRUNC_SAT_F64_U(tos)); } private static void I32_TRUNC_SAT_F64_S(MStack stack) { - var tos = stack.pop().asDouble(); - stack.push(Value.i32(OpcodeImpl.I32_TRUNC_SAT_F64_S(tos))); + var tos = Value.longToDouble(stack.pop()); + stack.push(OpcodeImpl.I32_TRUNC_SAT_F64_S(tos)); } private static void I32_TRUNC_SAT_F32_U(MStack stack) { - var tos = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.I32_TRUNC_SAT_F32_U(tos))); + var tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I32_TRUNC_SAT_F32_U(tos)); } private static void I32_TRUNC_SAT_F32_S(MStack stack) { - var tos = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.I32_TRUNC_SAT_F32_S(tos))); + var tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I32_TRUNC_SAT_F32_S(tos)); } private static void I32_TRUNC_F32_S(MStack stack) { - float tos = stack.pop().asFloat(); - stack.push(Value.i32(OpcodeImpl.I32_TRUNC_F32_S(tos))); + float tos = Value.longToFloat(stack.pop()); + stack.push(OpcodeImpl.I32_TRUNC_F32_S(tos)); } private static void F64_COPYSIGN(MStack stack) { - var b = stack.pop().asDouble(); - var a = stack.pop().asDouble(); - stack.push(Value.fromDouble(OpcodeImpl.F64_COPYSIGN(a, b))); + var b = Value.longToDouble(stack.pop()); + var a = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(OpcodeImpl.F64_COPYSIGN(a, b))); } private static void F32_TRUNC(MStack stack) { - var val = stack.pop().asFloat(); - stack.push(Value.fromFloat(OpcodeImpl.F32_TRUNC(val))); + var val = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(OpcodeImpl.F32_TRUNC(val))); } private static void CALL( @@ -1626,13 +1621,13 @@ private static void CALL( } private static void F64_NEG(MStack stack) { - var tos = stack.pop().asDouble(); - stack.push(Value.fromDouble(-tos)); + var tos = Value.longToDouble(stack.pop()); + stack.push(Value.doubleToLong(-tos)); } private static void F32_NEG(MStack stack) { - var tos = stack.pop().asFloat(); - stack.push(Value.fromFloat(-tos)); + var tos = Value.longToFloat(stack.pop()); + stack.push(Value.floatToLong(-tos)); } private static void MEMORY_FILL(MStack stack, Instance instance, Operands operands) { @@ -1640,21 +1635,21 @@ private static void MEMORY_FILL(MStack stack, Instance instance, Operands operan if (memidx != 0) { throw new WASMRuntimeException("We don't support multiple memories just yet"); } - var size = stack.pop().asInt(); - var val = stack.pop().asByte(); - var offset = stack.pop().asInt(); + var size = (int) stack.pop(); + var val = (byte) stack.pop(); + var offset = (int) stack.pop(); var end = (size + offset); instance.memory().fill(val, offset, end); } private static void MEMORY_GROW(MStack stack, Instance instance) { - var size = stack.pop().asInt(); + var size = (int) stack.pop(); var nPages = instance.memory().grow(size); - stack.push(Value.i32(nPages)); + stack.push(nPages); } private static int readMemPtr(MStack stack, Operands operands) { - int offset = stack.pop().asInt(); + int offset = (int) stack.pop(); if (operands.get(1) < 0 || operands.get(1) >= Integer.MAX_VALUE || offset < 0) { throw new WASMRuntimeException("out of bounds memory access"); } @@ -1662,37 +1657,38 @@ private static int readMemPtr(MStack stack, Operands operands) { } private static void F64_STORE(MStack stack, Instance instance, Operands operands) { - var value = stack.pop().asDouble(); + var value = Value.longToDouble(stack.pop()); var ptr = readMemPtr(stack, operands); instance.memory().writeF64(ptr, value); } private static void F32_STORE(MStack stack, Instance instance, Operands operands) { - var value = stack.pop().asFloat(); + var value = Value.longToFloat(stack.pop()); var ptr = readMemPtr(stack, operands); instance.memory().writeF32(ptr, value); } private static void I64_STORE(MStack stack, Instance instance, Operands operands) { - var value = stack.pop().asLong(); + var value = stack.pop(); var ptr = readMemPtr(stack, operands); instance.memory().writeLong(ptr, value); } private static void I64_STORE16(MStack stack, Instance instance, Operands operands) { - var value = stack.pop().asShort(); + var value = (short) stack.pop(); var ptr = readMemPtr(stack, operands); instance.memory().writeShort(ptr, value); } private static void I32_STORE(MStack stack, Instance instance, Operands operands) { - var value = stack.pop().asInt(); + var value = (int) stack.pop(); var ptr = readMemPtr(stack, operands); instance.memory().writeI32(ptr, value); } private static void I64_LOAD32_U(MStack stack, Instance instance, Operands operands) { var ptr = readMemPtr(stack, operands); + // TODO: make all the memory.readThings to return long var val = instance.memory().readU32(ptr); stack.push(val); } @@ -1701,14 +1697,14 @@ private static void I64_LOAD32_S(MStack stack, Instance instance, Operands opera var ptr = readMemPtr(stack, operands); var val = instance.memory().readI32(ptr); // TODO this is a bit hacky - stack.push(Value.i64(val.asInt())); + stack.push(val); } private static void I64_LOAD16_U(MStack stack, Instance instance, Operands operands) { var ptr = readMemPtr(stack, operands); var val = instance.memory().readU16(ptr); // TODO this is a bit hacky - stack.push(Value.i64(val.asInt())); + stack.push(val); } private static void I32_LOAD16_U(MStack stack, Instance instance, Operands operands) { @@ -1721,7 +1717,7 @@ private static void I64_LOAD16_S(MStack stack, Instance instance, Operands opera var ptr = readMemPtr(stack, operands); var val = instance.memory().readI16(ptr); // TODO this is a bit hacky - stack.push(Value.i64(val.asInt())); + stack.push(val); } private static void I32_LOAD16_S(MStack stack, Instance instance, Operands operands) { @@ -1734,7 +1730,7 @@ private static void I64_LOAD8_U(MStack stack, Instance instance, Operands operan var ptr = readMemPtr(stack, operands); var val = instance.memory().readU8(ptr); // TODO a bit hacky - stack.push(Value.i64(val.asInt())); + stack.push(val); } private static void I32_LOAD8_U(MStack stack, Instance instance, Operands operands) { @@ -1747,7 +1743,7 @@ private static void I64_LOAD8_S(MStack stack, Instance instance, Operands operan var ptr = readMemPtr(stack, operands); var val = instance.memory().readI8(ptr); // TODO a bit hacky - stack.push(Value.i64(val.asInt())); + stack.push(val); } private static void I32_LOAD8_S(MStack stack, Instance instance, Operands operands) { @@ -1784,14 +1780,14 @@ private static void TABLE_SET(MStack stack, Instance instance, Operands operands var idx = (int) operands.get(0); var table = instance.table(idx); - var value = stack.pop().asExtRef(); - var i = stack.pop().asInt(); + var value = (int) stack.pop(); + var i = (int) stack.pop(); table.setRef(i, value, instance); } private static void TABLE_GET(MStack stack, Instance instance, Operands operands) { var idx = (int) operands.get(0); - var i = stack.pop().asInt(); + var i = (int) stack.pop(); stack.push(OpcodeImpl.TABLE_GET(instance, idx, i)); } @@ -1809,7 +1805,7 @@ private static void GLOBAL_GET(MStack stack, Instance instance, Operands operand } private static void SELECT(MStack stack) { - var pred = stack.pop().asInt(); + var pred = (int) stack.pop(); var b = stack.pop(); var a = stack.pop(); if (pred == 0) { @@ -1820,7 +1816,7 @@ private static void SELECT(MStack stack) { } private static void SELECT_T(MStack stack) { - var pred = stack.pop().asInt(); + var pred = (int) stack.pop(); var b = stack.pop(); var a = stack.pop(); if (pred == 0) { @@ -1836,8 +1832,8 @@ private static void CALL_INDIRECT( var table = instance.table(tableIdx); var typeId = (int) operands.get(0); - int funcTableIdx = stack.pop().asInt(); - int funcId = table.ref(funcTableIdx).asFuncRef(); + int funcTableIdx = (int) stack.pop(); + int funcId = (int) table.ref(funcTableIdx); var tableInstance = table.instance(funcTableIdx); if (tableInstance != null) { instance = tableInstance; @@ -1892,7 +1888,7 @@ private static void IF( var returnsSize = numberOfValuesToReturn(instance, instruction); frame.pushCtrl(instruction.opcode(), paramsSize, returnsSize, stack.size() - paramsSize); - frame.jumpTo(predValue.asInt() == 0 ? instruction.labelFalse() : instruction.labelTrue()); + frame.jumpTo(predValue == 0 ? instruction.labelFalse() : instruction.labelTrue()); } private static void ctrlJump(StackFrame frame, MStack stack, int n) { @@ -1911,8 +1907,7 @@ private static void BR(StackFrame frame, MStack stack, AnnotatedInstruction inst } private static void BR_TABLE(StackFrame frame, MStack stack, AnnotatedInstruction instruction) { - var predValue = stack.pop(); - var pred = predValue.asInt(); + var pred = (int) stack.pop(); var defaultIdx = instruction.operandCount() - 1; if (pred < 0 || pred >= defaultIdx) { @@ -1926,8 +1921,7 @@ private static void BR_TABLE(StackFrame frame, MStack stack, AnnotatedInstructio } private static void BR_IF(StackFrame frame, MStack stack, AnnotatedInstruction instruction) { - var predValue = stack.pop(); - var pred = predValue.asInt(); + var pred = (int) stack.pop(); if (pred == 0) { frame.jumpTo(instruction.labelFalse()); @@ -1937,28 +1931,13 @@ private static void BR_IF(StackFrame frame, MStack stack, AnnotatedInstruction i } } - static Value[] extractArgsForParams(MStack stack, List params) { + static long[] extractArgsForParams(MStack stack, List params) { if (params == null) { return Value.EMPTY_VALUES; } - var args = new Value[params.size()]; + var args = new long[params.size()]; for (var i = params.size(); i > 0; i--) { var p = stack.pop(); - var t = params.get(i - 1); - if (p.type() != t) { - // Similar to what is happening in WaZero - // https://github.com/tetratelabs/wazero/blob/36676928d22ab92c34299eb0dca7608c92c94b22/internal/wasm/gofunc.go#L109 - switch (t) { - case I32: - case I64: - case F32: - case F64: - p = new Value(t, p.asLong()); - break; - default: - throw new RuntimeException("Type error when extracting args. Found: " + t); - } - } args[i - 1] = p; } return args; diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/MStack.java b/runtime/src/main/java/com/dylibso/chicory/runtime/MStack.java index c087ebd38..5352083fb 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/MStack.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/MStack.java @@ -1,50 +1,48 @@ package com.dylibso.chicory.runtime; -import com.dylibso.chicory.wasm.types.Value; -import java.util.ArrayDeque; -import java.util.Deque; - /** * A temporary class that gives us a little more control over the interface. * It allows us to assert non-nulls as well as throw stack under and overflow exceptions * We should replace with something more idiomatic and performant. */ public class MStack { - private final Deque stack; + public static final int MIN_CAPACITY = 8; - public MStack() { - this.stack = new ArrayDeque<>(); + private int count; + private long[] elements; + + private void increaseCapacity() { + final int newCapacity = elements.length << 1; + + final long[] array = new long[newCapacity]; + System.arraycopy(elements, 0, array, 0, elements.length); + + elements = array; } - public void push(Value v) { - if (v == null) { - throw new RuntimeException("Can't push null value onto stack"); - } - this.stack.push(v); + public MStack() { + this.elements = new long[MIN_CAPACITY]; } - public Value pop() { - var r = this.stack.pollFirst(); - if (r == null) { - throw new RuntimeException("Stack underflow exception"); + public void push(long v) { + elements[count] = v; + count++; + + if (count == elements.length) { + increaseCapacity(); } - return r; } - public Value peek() { - var r = this.stack.peek(); - if (r == null) { - throw new RuntimeException("Stack underflow exception"); - } - return r; + public long pop() { + count--; + return elements[count]; } - public int size() { - return this.stack.size(); + public long peek() { + return elements[count - 1]; } - @Override - public String toString() { - return this.stack.toString(); + public int size() { + return count; } } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/Machine.java b/runtime/src/main/java/com/dylibso/chicory/runtime/Machine.java index 5ba441cc0..f082be4aa 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/Machine.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/Machine.java @@ -1,9 +1,8 @@ package com.dylibso.chicory.runtime; import com.dylibso.chicory.wasm.exceptions.ChicoryException; -import com.dylibso.chicory.wasm.types.Value; public interface Machine { - Value[] call(int funcId, Value[] args) throws ChicoryException; + long[] call(int funcId, long[] args) throws ChicoryException; } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/Memory.java b/runtime/src/main/java/com/dylibso/chicory/runtime/Memory.java index a6c12ebbf..c10801dc2 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/Memory.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/Memory.java @@ -11,7 +11,6 @@ import com.dylibso.chicory.wasm.types.DataSegment; import com.dylibso.chicory.wasm.types.MemoryLimits; import com.dylibso.chicory.wasm.types.PassiveDataSegment; -import com.dylibso.chicory.wasm.types.Value; import com.dylibso.chicory.wasm.types.ValueType; import java.nio.BufferOverflowException; import java.nio.BufferUnderflowException; @@ -180,10 +179,6 @@ public String readCString(int addr) { return readCString(addr, StandardCharsets.UTF_8); } - public void write(int addr, Value data) { - write(addr, data.data()); - } - public void write(int addr, byte[] data) { write(addr, data, 0, data.length); } @@ -234,12 +229,12 @@ public int readInt(int addr) { } } - public Value readI32(int addr) { - return Value.i32(readInt(addr)); + public long readI32(int addr) { + return readInt(addr); } - public Value readU32(int addr) { - return Value.i32(Integer.toUnsignedLong(readInt(addr))); + public long readU32(int addr) { + return Integer.toUnsignedLong(readInt(addr)); } public void writeLong(int addr, long data) { @@ -258,8 +253,8 @@ public long readLong(int addr) { } } - public Value readI64(int addr) { - return Value.i64(readLong(addr)); + public long readI64(int addr) { + return readLong(addr); } public void writeShort(int addr, short data) { @@ -278,13 +273,13 @@ public short readShort(int addr) { } } - public Value readI16(int addr) { - return Value.i32(readShort(addr)); + public long readI16(int addr) { + return readShort(addr); } - public Value readU16(int addr) { + public long readU16(int addr) { try { - return Value.i32(buffer.getShort(addr) & 0xffff); + return buffer.getShort(addr) & 0xffff; } catch (IndexOutOfBoundsException e) { throw new WASMRuntimeException("out of bounds memory access"); } @@ -298,17 +293,17 @@ public void writeByte(int addr, byte data) { } } - public Value readU8(int addr) { + public long readU8(int addr) { try { - return Value.i32(read(addr) & 0xFF); + return read(addr) & 0xFF; } catch (IndexOutOfBoundsException e) { throw new WASMRuntimeException("out of bounds memory access"); } } - public Value readI8(int addr) { + public long readI8(int addr) { try { - return Value.i32(read(addr)); + return read(addr); } catch (IndexOutOfBoundsException e) { throw new WASMRuntimeException("out of bounds memory access"); } @@ -322,9 +317,9 @@ public void writeF32(int addr, float data) { } } - public Value readF32(int addr) { + public long readF32(int addr) { try { - return Value.f32(buffer.getInt(addr)); + return buffer.getInt(addr); } catch (IndexOutOfBoundsException e) { throw new WASMRuntimeException("out of bounds memory access"); } @@ -354,9 +349,9 @@ public double readDouble(int addr) { } } - public Value readF64(int addr) { + public long readF64(int addr) { try { - return Value.f64(buffer.getLong(addr)); + return buffer.getLong(addr); } catch (IndexOutOfBoundsException e) { throw new WASMRuntimeException("out of bounds memory access"); } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/OpcodeImpl.java b/runtime/src/main/java/com/dylibso/chicory/runtime/OpcodeImpl.java index 3812b10bb..ea409b850 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/OpcodeImpl.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/OpcodeImpl.java @@ -7,7 +7,6 @@ import com.dylibso.chicory.runtime.exceptions.WASMRuntimeException; import com.dylibso.chicory.wasm.types.OpCode; import com.dylibso.chicory.wasm.types.PassiveElement; -import com.dylibso.chicory.wasm.types.Value; import com.dylibso.chicory.wasm.types.ValueType; /** @@ -796,7 +795,7 @@ public static double F64_TRUNC(double x) { // ========= Tables ========= - public static Value TABLE_GET(Instance instance, int tableIndex, int index) { + public static int TABLE_GET(Instance instance, int tableIndex, int index) { TableInstance table = instance.table(tableIndex); if (index < 0 || index >= table.limits().max() || index >= table.size()) { throw new WASMRuntimeException("out of bounds table access"); @@ -831,11 +830,11 @@ public static void TABLE_COPY( if (d <= s) { var val = src.ref(s++); var inst = src.instance(d); - dest.setRef(d++, val.asFuncRef(), inst); + dest.setRef(d++, (int) val, inst); } else { var val = src.ref(s + i); var inst = src.instance(d + i); - dest.setRef(d + i, val.asFuncRef(), inst); + dest.setRef(d + i, (int) val, inst); } } } @@ -866,14 +865,15 @@ public static void TABLE_INIT( for (int i = offset; i < end; i++) { var elem = instance.element(elementidx); var val = computeConstantValue(instance, elem.initializers().get(elemidx++)); + var rawValue = (int) val.raw(); if (table.elementType() == ValueType.FuncRef) { - if (val.asFuncRef() > instance.functionCount()) { + if (rawValue > instance.functionCount()) { throw new WASMRuntimeException("out of bounds table access"); } - table.setRef(i, val.asFuncRef(), instance); + table.setRef(i, rawValue, instance); } else { assert table.elementType() == ValueType.ExternRef; - table.setRef(i, val.asExtRef(), instance); + table.setRef(i, rawValue, instance); } } } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/StackFrame.java b/runtime/src/main/java/com/dylibso/chicory/runtime/StackFrame.java index 27d45f305..fa8f0914d 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/StackFrame.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/StackFrame.java @@ -25,12 +25,12 @@ public class StackFrame { private final int funcId; private int pc; - private final Value[] locals; + private final long[] locals; private final Instance instance; private final List ctrlStack = new ArrayList<>(); - public StackFrame(Instance instance, int funcId, Value[] args, List localTypes) { + public StackFrame(Instance instance, int funcId, long[] args, List localTypes) { this(Collections.emptyList(), instance, funcId, args, localTypes); } @@ -38,7 +38,7 @@ public StackFrame( List code, Instance instance, int funcId, - Value[] args, + long[] args, List localTypes) { this.code = code; this.instance = instance; @@ -55,11 +55,11 @@ public StackFrame( } } - void setLocal(int i, Value v) { + void setLocal(int i, long v) { this.locals[i] = v; } - Value local(int i) { + long local(int i) { return locals[i]; } @@ -132,7 +132,7 @@ public void jumpTo(int newPc) { public static void doControlTransfer(CtrlFrame ctrlFrame, MStack stack) { var endResults = ctrlFrame.startValues + ctrlFrame.endValues; // unwind stack - Value[] returns = new Value[endResults]; + long[] returns = new long[endResults]; for (int i = 0; i < returns.length; i++) { if (stack.size() > 0) { returns[i] = stack.pop(); @@ -144,10 +144,8 @@ public static void doControlTransfer(CtrlFrame ctrlFrame, MStack stack) { } for (int i = 0; i < returns.length; i++) { - Value value = returns[returns.length - 1 - i]; - if (value != null) { - stack.push(value); - } + long value = returns[returns.length - 1 - i]; + stack.push(value); } } } diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/TableInstance.java b/runtime/src/main/java/com/dylibso/chicory/runtime/TableInstance.java index 86b1a0729..128ff2c64 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/TableInstance.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/TableInstance.java @@ -6,7 +6,6 @@ import com.dylibso.chicory.wasm.exceptions.UninstantiableException; import com.dylibso.chicory.wasm.types.Limits; import com.dylibso.chicory.wasm.types.Table; -import com.dylibso.chicory.wasm.types.Value; import com.dylibso.chicory.wasm.types.ValueType; import java.util.Arrays; @@ -50,16 +49,11 @@ public int grow(int size, int value, Instance instance) { return oldSize; } - public Value ref(int index) { + public int ref(int index) { if (index < 0 || index >= this.refs.length) { throw new ChicoryException("undefined element"); } - int res = this.refs[index]; - if (this.elementType() == ValueType.FuncRef) { - return Value.funcRef(res); - } else { - return Value.externRef(res); - } + return this.refs[index]; } public void setRef(int index, int value, Instance instance) { diff --git a/runtime/src/main/java/com/dylibso/chicory/runtime/WasmFunctionHandle.java b/runtime/src/main/java/com/dylibso/chicory/runtime/WasmFunctionHandle.java index dfce34e50..2b70815b8 100644 --- a/runtime/src/main/java/com/dylibso/chicory/runtime/WasmFunctionHandle.java +++ b/runtime/src/main/java/com/dylibso/chicory/runtime/WasmFunctionHandle.java @@ -1,11 +1,9 @@ package com.dylibso.chicory.runtime; -import com.dylibso.chicory.wasm.types.Value; - /** * Represents a Java function that can be called from Wasm. */ @FunctionalInterface public interface WasmFunctionHandle { - Value[] apply(Instance instance, Value... args); + long[] apply(Instance instance, long... args); } diff --git a/runtime/src/test/java/com/dylibso/chicory/runtime/InterruptionTest.java b/runtime/src/test/java/com/dylibso/chicory/runtime/InterruptionTest.java index 9960ffd6c..cc91a87d3 100644 --- a/runtime/src/test/java/com/dylibso/chicory/runtime/InterruptionTest.java +++ b/runtime/src/test/java/com/dylibso/chicory/runtime/InterruptionTest.java @@ -8,7 +8,6 @@ import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.wasm.exceptions.ChicoryException; -import com.dylibso.chicory.wasm.types.Value; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.Test; @@ -35,7 +34,7 @@ public void shouldInterruptCall() throws InterruptedException { .getResourceAsStream("compiled/power.c.wasm"))) .build(); var function = instance.export("run"); - assertInterruption(() -> function.apply(Value.i32(100))); + assertInterruption(() -> function.apply(100)); } private static void assertInterruption(Runnable function) throws InterruptedException { diff --git a/runtime/src/test/java/com/dylibso/chicory/runtime/ModuleTest.java b/runtime/src/test/java/com/dylibso/chicory/runtime/ModuleTest.java index 92aa501cd..e86018cbb 100644 --- a/runtime/src/test/java/com/dylibso/chicory/runtime/ModuleTest.java +++ b/runtime/src/test/java/com/dylibso/chicory/runtime/ModuleTest.java @@ -9,7 +9,6 @@ import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.wasm.exceptions.UninstantiableException; import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.Value; import com.dylibso.chicory.wasm.types.ValueType; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -27,36 +26,36 @@ private static Module loadModule(String fileName) { public void shouldWorkFactorial() { var instance = Instance.builder(loadModule("compiled/iterfact.wat.wasm")).build(); var iterFact = instance.export("iterFact"); - var result = iterFact.apply(Value.i32(5))[0]; - assertEquals(120, result.asInt()); + var result = iterFact.apply(5L)[0]; + assertEquals(120L, result); } @Test public void shouldRunABasicAdd() { var instance = Instance.builder(loadModule("compiled/add.wat.wasm")).build(); var add = instance.export("add"); - var result = add.apply(Value.i32(5), Value.i32(6))[0]; - assertEquals(11, result.asInt()); + var result = add.apply(5L, 6L)[0]; + assertEquals(11L, result); } @Test public void shouldSupportBrTable() { var instance = Instance.builder(loadModule("compiled/br_table.wat.wasm")).build(); var switchLike = instance.export("switch_like"); - var result = switchLike.apply(Value.i32(0))[0]; - assertEquals(102, result.asInt()); - result = switchLike.apply(Value.i32(1))[0]; - assertEquals(101, result.asInt()); - result = switchLike.apply(Value.i32(2))[0]; - assertEquals(100, result.asInt()); - result = switchLike.apply(Value.i32(-1))[0]; - assertEquals(103, result.asInt()); - result = switchLike.apply(Value.i32(3))[0]; - assertEquals(103, result.asInt()); - result = switchLike.apply(Value.i32(4))[0]; - assertEquals(103, result.asInt()); - result = switchLike.apply(Value.i32(100))[0]; - assertEquals(103, result.asInt()); + var result = switchLike.apply(0L)[0]; + assertEquals(102L, result); + result = switchLike.apply(1)[0]; + assertEquals(101L, result); + result = switchLike.apply(2)[0]; + assertEquals(100L, result); + result = switchLike.apply(-1)[0]; + assertEquals(103L, result); + result = switchLike.apply(3)[0]; + assertEquals(103L, result); + result = switchLike.apply(4)[0]; + assertEquals(103L, result); + result = switchLike.apply(100)[0]; + assertEquals(103L, result); } @Test @@ -64,15 +63,15 @@ public void shouldExerciseBranches() { var module = Instance.builder(loadModule("compiled/branching.wat.wasm")).build(); var foo = module.export("foo"); - var result = foo.apply(Value.i32(0))[0]; - assertEquals(42, result.asInt()); + var result = foo.apply(0)[0]; + assertEquals(42L, result); - result = foo.apply(Value.i32(1))[0]; - assertEquals(99, result.asInt()); + result = foo.apply(1)[0]; + assertEquals(99L, result); for (var i = 2; i < 100; i++) { - result = foo.apply(Value.i32(i))[0]; - assertEquals(7, result.asInt()); + result = foo.apply(i)[0]; + assertEquals(7L, result); } } @@ -85,11 +84,10 @@ public void shouldConsoleLogWithString() { new HostFunction( "console", "log", - (Instance instance, - Value... args) -> { // decompiled is: console_log(13, 0); + (Instance instance, long... args) -> { // decompiled is: console_log(13, 0); Memory memory = instance.memory(); - var len = args[0].asInt(); - var offset = args[1].asInt(); + int len = (int) args[0]; + int offset = (int) args[1]; var message = memory.readString(offset, len); if (expected.equals(message)) { @@ -118,9 +116,9 @@ public void shouldComputeFactorial() { // don't make this too big we will overflow 32 bits for (var i = 0; i < 10; i++) { - var result = iterFact.apply(Value.i32(i))[0]; + var result = iterFact.apply(i)[0]; // test against an oracle Java implementation - assertEquals(factorial(i), result.asInt()); + assertEquals(factorial(i), result); } } @@ -140,10 +138,10 @@ public void shouldWorkWithStartFunction() { new HostFunction( "env", "gotit", - (Instance instance, Value... args) -> { + (Instance instance, long... args) -> { var val = args[0]; - if (val.asInt() == 42) { + if (val == 42L) { count.incrementAndGet(); } @@ -169,8 +167,8 @@ public void shouldTrapOnUnreachable() { public void shouldSupportGlobals() { var instance = Instance.builder(loadModule("compiled/globals.wat.wasm")).build(); var doit = instance.export("doit"); - var result = doit.apply(Value.i32(32))[0]; - assertEquals(42, result.asInt()); + var result = doit.apply(32)[0]; + assertEquals(42L, result); } @Test @@ -182,11 +180,11 @@ public void shouldCountVowels() { var memory = instance.memory(); var message = "Hello, World!"; var len = message.getBytes(UTF_8).length; - var ptr = alloc.apply(Value.i32(len))[0].asInt(); + int ptr = (int) alloc.apply(len)[0]; memory.writeString(ptr, message); - var result = countVowels.apply(Value.i32(ptr), Value.i32(len)); - dealloc.apply(Value.i32(ptr), Value.i32(len)); - assertEquals(3, result[0].asInt()); + var result = countVowels.apply(ptr, len); + dealloc.apply(ptr, len); + assertEquals(3L, result[0]); } @Test @@ -195,7 +193,7 @@ public void shouldRunBasicCProgram() { var instance = Instance.builder(loadModule("compiled/basic.c.wasm")).build(); var run = instance.export("run"); var result = run.apply()[0]; - assertEquals(42, result.asInt()); + assertEquals(42L, result); } @Test @@ -204,7 +202,7 @@ public void shouldRunComplexFunction() { var instance = Instance.builder(loadModule("compiled/complex.c.wasm")).build(); var run = instance.export("run"); var result = run.apply(); - assertEquals(-679, result[0].asInt()); + assertEquals(-679, (int) result[0]); } @Test @@ -213,34 +211,34 @@ public void shouldRunMemoryProgramInC() { var instance = Instance.builder(loadModule("compiled/memory.c.wasm")).build(); var run = instance.export("run"); var result = run.apply(); - assertEquals(11, result[0].asInt()); + assertEquals(11L, result[0]); } @Test public void shouldWorkWithMemoryOps() { var instance = Instance.builder(loadModule("compiled/memory.wat.wasm")).build(); var run = instance.export("run32"); - var results = run.apply(Value.i32(42)); + var results = run.apply(42); var result = results[0]; - assertEquals(42, result.asInt()); + assertEquals(42L, result); - result = run.apply(Value.i32(Integer.MAX_VALUE))[0]; - assertEquals(Integer.MAX_VALUE, result.asInt()); + result = run.apply(Integer.MAX_VALUE)[0]; + assertEquals(Integer.MAX_VALUE, (int) result); - result = run.apply(Value.i32(Integer.MIN_VALUE))[0]; - assertEquals(Integer.MIN_VALUE, result.asInt()); + result = run.apply(Integer.MIN_VALUE)[0]; + assertEquals(Integer.MIN_VALUE, (int) result); run = instance.export("run64"); - result = run.apply(Value.i64(42))[0]; - assertEquals(42L, result.asLong()); + result = run.apply(42L)[0]; + assertEquals(42L, result); run = instance.export("run64"); - result = run.apply(Value.i64(Long.MIN_VALUE))[0]; - assertEquals(Long.MIN_VALUE, result.asLong()); + result = run.apply(Long.MIN_VALUE)[0]; + assertEquals(Long.MIN_VALUE, result); run = instance.export("run64"); - result = run.apply(Value.i64(Long.MAX_VALUE))[0]; - assertEquals(Long.MAX_VALUE, result.asLong()); + result = run.apply(Long.MAX_VALUE)[0]; + assertEquals(Long.MAX_VALUE, result); } @Test @@ -250,7 +248,7 @@ public void shouldRunKitchenSink() { var instance = Instance.builder(loadModule("compiled/kitchensink.wat.wasm")).build(); var run = instance.export("run"); - assertEquals(6, run.apply(Value.i32(100))[0].asInt()); + assertEquals(6L, run.apply(100)[0]); } @Test @@ -258,7 +256,7 @@ public void shouldOperateMemoryOps() { // check with: wasmtime memories.wat.wasm --invoke run 100 var instance = Instance.builder(loadModule("compiled/memories.wat.wasm")).build(); var run = instance.export("run"); - assertEquals(-25438, run.apply(Value.i32(100))[0].asInt()); + assertEquals(-25438, (int) run.apply(100)[0]); } @Test @@ -267,10 +265,10 @@ public void shouldRunMixedImports() { new HostFunction( "env", "cbrt", - (Instance instance, Value... args) -> { - var x = args[0].asInt(); - var cbrt = Math.cbrt(x); - return new Value[] {Value.fromDouble(cbrt)}; + (Instance instance, long... args) -> { + var x = args[0]; + var cbrt = Math.cbrt((double) x); + return new long[] {Double.doubleToRawLongBits(cbrt)}; }, List.of(ValueType.I32), List.of(ValueType.F64)); @@ -279,9 +277,9 @@ public void shouldRunMixedImports() { new HostFunction( "env", "log", - (Instance instance, Value... args) -> { - var logLevel = args[0].asInt(); - var value = (int) args[1].asDouble(); + (Instance instance, long... args) -> { + var logLevel = args[0]; + var value = (int) Double.longBitsToDouble(args[1]); logResult.set(logLevel + ": " + value); return null; }, @@ -310,7 +308,7 @@ public void issue294_BRIF() { var instance = Instance.builder(loadModule("compiled/issue294_brif.wat.wasm")).build(); var main = instance.export("main"); - assertEquals(5, main.apply(Value.i32(5))[0].asInt()); + assertEquals(5L, main.apply(5)[0]); } @Test @@ -318,7 +316,7 @@ public void issue294_BR() { var instance = Instance.builder(loadModule("compiled/issue294_br.wat.wasm")).build(); var main = instance.export("main"); - assertEquals(4, main.apply()[0].asInt()); + assertEquals(4L, main.apply()[0]); } @Test @@ -326,7 +324,7 @@ public void issue294_BRTABLE() { var instance = Instance.builder(loadModule("compiled/issue294_brtable.wat.wasm")).build(); var main = instance.export("main"); - assertEquals(4, main.apply()[0].asInt()); + assertEquals(4L, main.apply()[0]); } @Test @@ -339,7 +337,7 @@ public void shouldCountNumberOfInstructions() { .build(); var iterFact = instance.export("iterFact"); - iterFact.apply(Value.i32(100)); + iterFact.apply(100L); // current result is: 1109 assertTrue(count.get() > 0); @@ -357,8 +355,8 @@ public void shouldConsumeStackLoopOperations() { var facSsa = instance.export("fac-ssa"); var number = 100; - var result = facSsa.apply(Value.i32(number)); - assertEquals(factorial(number), result[0].asInt()); + var result = facSsa.apply(number); + assertEquals(factorial(number), result[0]); // IIUC: 3 values returning from last CALL + 1 result assertTrue(finalStackSize.get() == 4L); diff --git a/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/JavaTestGen.java b/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/JavaTestGen.java index 806578574..c0bb01f30 100644 --- a/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/JavaTestGen.java +++ b/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/JavaTestGen.java @@ -367,7 +367,7 @@ private List generateAssert(String varName, Command cmd) { var args = (cmd.action().args() != null) ? Arrays.stream(cmd.action().args()) - .map(WasmValue::toWasmValue) + .map(WasmValue::toArgsValue) .collect(Collectors.joining(", ")) : ""; @@ -393,19 +393,9 @@ private List generateAssert(String varName, Command cmd) { for (int i = 0; i < cmd.expected().length; i++) { var expected = cmd.expected()[i]; - var returnVar = expected.toJavaValue(); - var typeConversion = expected.extractType(); - var deltaParam = expected.delta(); - exprs.add( - new NameExpr( - "assertEquals(" - + returnVar - + ", results[" - + i - + "]" - + typeConversion - + deltaParam - + ")")); + var expectedVar = expected.toExpectedValue(); + var resultVar = expected.toResultValue("results[" + i + "]"); + exprs.add(new NameExpr("assertEquals(" + expectedVar + ", " + resultVar + ")")); } return exprs; @@ -421,7 +411,7 @@ private List generateInvoke(String varName, Command cmd) { if (cmd.action().type() == INVOKE) { var args = Arrays.stream(cmd.action().args()) - .map(WasmValue::toWasmValue) + .map(WasmValue::toArgsValue) .collect(Collectors.joining(", ")); invocationMethod = ".apply(" + args + ")"; } else { diff --git a/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/wast/WasmValue.java b/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/wast/WasmValue.java index a7f5d993d..6ec57ba35 100644 --- a/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/wast/WasmValue.java +++ b/test-gen-plugin/src/main/java/com/dylibso/chicory/maven/wast/WasmValue.java @@ -18,7 +18,28 @@ public String value() { return value; } - public String toJavaValue() { + public String toResultValue(String result) { + switch (type) { + case I64: + return result; + case I32: + return "(int) " + result; + case F32: + return "Float.intBitsToFloat((int) " + result + "), 0.0"; + case F64: + return "Double.longBitsToDouble(" + result + "), 0.0"; + case EXTERN_REF: + case FUNC_REF: + if (result.equals("null")) { + return "Value.REF_NULL_VALUE"; + } + return result; + default: + throw new IllegalArgumentException("Type not recognized " + type); + } + } + + public String toExpectedValue() { switch (type) { case I32: return "Integer.parseUnsignedInt(\"" + value + "\")"; @@ -53,13 +74,9 @@ public String toJavaValue() { return "null"; } case EXTERN_REF: - if (value.toString().equals("null")) { - return "Value.EXTREF_NULL"; - } - return value; case FUNC_REF: - if (value.toString().equals("null")) { - return "Value.FUNCREF_NULL"; + if (value.equals("null")) { + return "Value.REF_NULL_VALUE"; } return value; default: @@ -67,61 +84,42 @@ public String toJavaValue() { } } - public String toWasmValue() { + public String toArgsValue() { switch (type) { case I32: - return "Value.i32(" + toJavaValue() + ")"; - case I64: - return "Value.i64(" + toJavaValue() + ")"; case F32: - return "Value.f32(Integer.parseUnsignedInt(\"" + value + "\"))"; + if (value != null) { + switch (value) { + case "nan:canonical": + case "nan:arithmetic": + return "(int) Float.NaN"; + default: + return "Integer.parseUnsignedInt(\"" + value + "\")"; + } + } else { + return "null"; + } + case I64: case F64: - return "Value.f64(Long.parseUnsignedLong(\"" + value + "\"))"; - case EXTERN_REF: - if (value.toString().equals("null")) { - return "Value.EXTREF_NULL"; + if (value != null) { + switch (value) { + case "nan:canonical": + case "nan:arithmetic": + return "(long) Double.NaN"; + default: + return "Long.parseUnsignedLong(\"" + value + "\")"; + } + } else { + return "null"; } - return "Value.externRef(" + value + ")"; + case EXTERN_REF: case FUNC_REF: if (value.toString().equals("null")) { - return "Value.FUNCREF_NULL"; + return "Value.REF_NULL_VALUE"; } - return "Value.funcRef(" + value + ")"; + return value; default: throw new IllegalArgumentException("Type not recognized " + type); } } - - public String extractType() { - if (value == null || value.equals("null")) { - return ""; - } else { - switch (type) { - case I32: - return ".asInt()"; - case I64: - return ".asLong()"; - case F32: - return ".asFloat()"; - case F64: - return ".asDouble()"; - case EXTERN_REF: - return ".asExtRef()"; - case FUNC_REF: - return ".asFuncRef()"; - default: - throw new IllegalArgumentException("Type not recognized " + type); - } - } - } - - public String delta() { - switch (type) { - case F32: - case F64: - return ", 0.0"; - default: - return ""; - } - } } diff --git a/wabt/src/test/java/com/dylibso/chicory/wabt/Wat2WasmTest.java b/wabt/src/test/java/com/dylibso/chicory/wabt/Wat2WasmTest.java index ace052b6e..e8a2d1190 100644 --- a/wabt/src/test/java/com/dylibso/chicory/wabt/Wat2WasmTest.java +++ b/wabt/src/test/java/com/dylibso/chicory/wabt/Wat2WasmTest.java @@ -8,7 +8,6 @@ import com.dylibso.chicory.runtime.Instance; import com.dylibso.chicory.wasi.WasiExitException; import com.dylibso.chicory.wasm.Parser; -import com.dylibso.chicory.wasm.types.Value; import java.io.File; import org.junit.jupiter.api.Test; @@ -37,10 +36,8 @@ public void shouldRunWat2WasmOnString() { var addFunction = moduleInstance.export("add"); var results = - addFunction.apply( - Value.i32(Integer.parseUnsignedInt("1")), - Value.i32(Integer.parseUnsignedInt("41"))); - assertEquals(Integer.parseUnsignedInt("42"), results[0].asInt()); + addFunction.apply(Integer.parseUnsignedInt("1"), Integer.parseUnsignedInt("41")); + assertEquals(Integer.parseUnsignedInt("42"), results[0]); } @Test diff --git a/wasi/src/main/java/com/dylibso/chicory/wasi/WasiPreview1.java b/wasi/src/main/java/com/dylibso/chicory/wasi/WasiPreview1.java index a33b600f4..85cfa8de7 100644 --- a/wasi/src/main/java/com/dylibso/chicory/wasi/WasiPreview1.java +++ b/wasi/src/main/java/com/dylibso/chicory/wasi/WasiPreview1.java @@ -475,8 +475,8 @@ public int fdRead(Memory memory, int fd, int iovs, int iovsLen, int nreadPtr) { int totalRead = 0; for (var i = 0; i < iovsLen; i++) { int base = iovs + (i * 8); - int iovBase = memory.readI32(base).asInt(); - var iovLen = memory.readI32(base + 4).asInt(); + int iovBase = memory.readInt(base); + var iovLen = memory.readInt(base + 4); try { byte[] data = new byte[iovLen]; int read = reader.read(data); @@ -676,8 +676,8 @@ public int fdWrite(Memory memory, int fd, int iovs, int iovsLen, int nwrittenPtr var totalWritten = 0; for (var i = 0; i < iovsLen; i++) { var base = iovs + (i * 8); - var iovBase = memory.readI32(base).asInt(); - var iovLen = memory.readI32(base + 4).asInt(); + var iovBase = memory.readInt(base); + var iovLen = memory.readInt(base + 4); var data = memory.readBytes(iovBase, iovLen); try { int written = writer.write(data); diff --git a/wasi/src/test/java/com/dylibso/chicory/wasi/WasiPreview1Test.java b/wasi/src/test/java/com/dylibso/chicory/wasi/WasiPreview1Test.java index 690ecff78..f62145872 100644 --- a/wasi/src/test/java/com/dylibso/chicory/wasi/WasiPreview1Test.java +++ b/wasi/src/test/java/com/dylibso/chicory/wasi/WasiPreview1Test.java @@ -14,7 +14,6 @@ import com.dylibso.chicory.wasm.Module; import com.dylibso.chicory.wasm.Parser; import com.dylibso.chicory.wasm.types.MemoryLimits; -import com.dylibso.chicory.wasm.types.Value; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.List; @@ -108,18 +107,17 @@ public void shouldUseQuickJsProvider() { var ptr = quickjs.export("canonical_abi_realloc") .apply( - Value.i32(0), // original_ptr - Value.i32(0), // original_size - Value.i32(1), // alignment - Value.i32(jsCode.length) // new size + 0, // original_ptr + 0, // original_size + 1, // alignment + jsCode.length // new size )[0]; - quickjs.memory().write(ptr.asInt(), jsCode); - var aggregatedCodePtr = - quickjs.export("compile_src").apply(ptr, Value.i64(jsCode.length))[0]; + quickjs.memory().write((int) ptr, jsCode); + var aggregatedCodePtr = quickjs.export("compile_src").apply(ptr, jsCode.length)[0]; - var codePtr = quickjs.memory().readI32(aggregatedCodePtr.asInt()); // 32 bit - var codeLength = quickjs.memory().readU32(aggregatedCodePtr.asInt() + 4); + var codePtr = quickjs.memory().readI32((int) aggregatedCodePtr); // 32 bit + var codeLength = quickjs.memory().readU32((int) aggregatedCodePtr + 4); quickjs.export("eval_bytecode").apply(codePtr, codeLength); @@ -166,9 +164,9 @@ public void shouldRunTinyGoModule() { var module = loadModule("compiled/sum.go.tiny.wasm"); var instance = Instance.builder(module).withExternalValues(imports).build(); var sum = instance.export("add"); - var result = sum.apply(Value.i32(20), Value.i32(22))[0]; + var result = sum.apply(20, 22)[0]; - assertEquals(result.asInt(), 42); + assertEquals(result, 42); } @Test diff --git a/wasm/src/main/java/com/dylibso/chicory/wasm/types/Value.java b/wasm/src/main/java/com/dylibso/chicory/wasm/types/Value.java index 85ebfe3fb..55930780b 100644 --- a/wasm/src/main/java/com/dylibso/chicory/wasm/types/Value.java +++ b/wasm/src/main/java/com/dylibso/chicory/wasm/types/Value.java @@ -2,32 +2,71 @@ import static java.util.Objects.requireNonNull; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.util.Objects; public class Value { - public static final Value TRUE = Value.i32(1); - - public static final Value FALSE = Value.i32(0); - + public static final long TRUE = 1L; + public static final long FALSE = 0L; public static final int REF_NULL_VALUE = -1; public static final Value EXTREF_NULL = Value.externRef(REF_NULL_VALUE); public static final Value FUNCREF_NULL = Value.funcRef(REF_NULL_VALUE); - - public static final Value[] EMPTY_VALUES = new Value[0]; + public static final long[] EMPTY_VALUES = new long[0]; private final ValueType type; private final long data; + public long raw() { + return data; + } + + public ValueType type() { + return type; + } + + public static long floatToLong(float data) { + return Float.floatToRawIntBits(data); + } + + public static float longToFloat(long data) { + return Float.intBitsToFloat((int) data); + } + + public static long doubleToLong(double data) { + return Double.doubleToRawLongBits(data); + } + + public static double longToDouble(long data) { + return Double.longBitsToDouble(data); + } + public static Value fromFloat(float data) { - return Value.f32(Float.floatToRawIntBits(data)); + return Value.f32(floatToLong(data)); + } + + public int asInt() { + assert (type == ValueType.I32); + return (int) data; + } + + public long asLong() { + assert (type == ValueType.I64); + return data; + } + + public float asFloat() { + assert (type == ValueType.F32); + return longToFloat(data); + } + + public double asDouble() { + assert (type == ValueType.F64); + return longToDouble(data); } public static Value fromDouble(double data) { - return Value.f64(Double.doubleToRawLongBits(data)); + return Value.f64(doubleToLong(data)); } public static Value i32(int data) { @@ -50,176 +89,52 @@ public static Value f64(long data) { return new Value(ValueType.F64, data); } - public static Value externRef(int data) { + public static Value externRef(long data) { return new Value(ValueType.ExternRef, data); } - public static Value funcRef(int data) { + public static Value funcRef(long data) { return new Value(ValueType.FuncRef, data); } - public Value(ValueType type, int value) { - this.type = requireNonNull(ensure32bitValueType(type), "type"); - this.data = value; - } - public Value(ValueType type, long value) { this.type = requireNonNull(type, "type"); data = value; } - private static ValueType ensure32bitValueType(ValueType type) { - switch (type) { - case I32: - case F32: - case ExternRef: - case FuncRef: - return type; - default: - throw new IllegalArgumentException("Invalid type for 32 bit value: " + type); - } - } - /** * Create a zeroed value for the particular type. * * @param valueType must be a valid zeroable type. * @return a zero. */ - public static Value zero(ValueType valueType) { + public static long zero(ValueType valueType) { switch (valueType) { case I32: - return Value.i32(0); case F32: - return Value.f32(0); case I64: - return Value.i64(0); case F64: - return Value.f64(0); + return 0L; case FuncRef: - return Value.FUNCREF_NULL; case ExternRef: - return Value.EXTREF_NULL; + return REF_NULL_VALUE; default: throw new IllegalArgumentException( "Can't create a zero value for type " + valueType); } } - // TODO memoize these - public int asInt() { - switch (type) { - case I64: - case F64: - case I32: - case F32: - return (int) data; - default: - throw new IllegalArgumentException( - "Can't turn wasm value of type " + type + " to a int"); - } - } - - // The unsigned representation of the int, stored in a long - // so there are enough bits - public long asUInt() { - switch (type) { - case I32: - case F32: - case I64: - case F64: - return data & 0xFFFFFFFFL; - default: - throw new IllegalArgumentException( - "Can't turn wasm value of type " + type + " to a uint"); - } - } - - public long asLong() { - switch (type) { - case I32: - case F32: - case I64: - case F64: - return data; - default: - throw new IllegalArgumentException( - "Can't turn wasm value of type " + type + " to a long"); - } - } - - // TODO memoize these - public byte asByte() { - switch (type) { - case I32: - case F32: - case I64: - case F64: - return (byte) (data & 0xff); - default: - throw new IllegalArgumentException( - "Can't turn wasm value of type " + type + " to a byte"); - } - } - - public short asShort() { - switch (type) { - case I32: - case I64: - return (short) (data & 0xffff); - default: - throw new IllegalArgumentException( - "Can't turn wasm value of type " + type + " to a short"); - } - } - - public int asExtRef() { - return (int) data; - } - - public int asFuncRef() { - return (int) data; - } - - public float asFloat() { - return Float.intBitsToFloat(asInt()); - } - - public double asDouble() { - return Double.longBitsToDouble(asLong()); - } - - public ValueType type() { - return type; - } - - public byte[] data() { - switch (type) { - case I64: - case F64: - ByteBuffer buffer = ByteBuffer.allocate(8); - buffer.order(ByteOrder.LITTLE_ENDIAN); - buffer.putLong(data); - return buffer.array(); - default: - ByteBuffer buffer2 = ByteBuffer.allocate(4); - buffer2.order(ByteOrder.LITTLE_ENDIAN); - buffer2.putInt((int) data); - return buffer2.array(); - } - } - @Override public String toString() { switch (type) { case I32: - return asInt() + "@i32"; + return ((int) data) + "@i32"; case I64: - return asLong() + "@i64"; + return data + "@i64"; case F32: - return asFloat() + "@f32"; + return longToFloat(data) + "@f32"; case F64: - return asDouble() + "@f64"; + return longToDouble(data) + "@f64"; case FuncRef: return "func[" + (int) data + "]"; case ExternRef: diff --git a/wasm/src/test/java/com/dylibso/chicory/wasm/types/ValueTest.java b/wasm/src/test/java/com/dylibso/chicory/wasm/types/ValueTest.java index 52fc6fb68..35bec5c12 100644 --- a/wasm/src/test/java/com/dylibso/chicory/wasm/types/ValueTest.java +++ b/wasm/src/test/java/com/dylibso/chicory/wasm/types/ValueTest.java @@ -1,10 +1,8 @@ package com.dylibso.chicory.wasm.types; -import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; @@ -28,25 +26,19 @@ public void shouldConvertFloats() { var f32Ref = 0.12345678f; var f32 = Value.f32(1039980265L); assertEquals(f32Ref, f32.asFloat(), 0.0); - assertArrayEquals(f32.data(), Value.fromFloat(f32Ref).data()); + assertEquals(f32.raw(), Value.fromFloat(f32Ref).raw()); var f64Ref = 0.123456789012345d; var f64 = Value.f64(4593560419847042606L); assertEquals(f64Ref, f64.asDouble(), 0.0); - assertArrayEquals(f64.data(), Value.fromDouble(f64Ref).data()); + assertEquals(f64.raw(), Value.fromDouble(f64Ref).raw()); } @Test public void validConstruction() { - new Value(ValueType.I32, 42); assertTrue(true); } - @Test - public void invalidConstruction() { - assertThrows(IllegalArgumentException.class, () -> new Value(ValueType.I64, 42)); - } - @Test public void equalsContract() {