diff --git a/build-time-compiler/src/main/java/run/endive/build/time/compiler/Generator.java b/build-time-compiler/src/main/java/run/endive/build/time/compiler/Generator.java index 1aacbf2cd..1e47938c7 100644 --- a/build-time-compiler/src/main/java/run/endive/build/time/compiler/Generator.java +++ b/build-time-compiler/src/main/java/run/endive/build/time/compiler/Generator.java @@ -40,6 +40,7 @@ import run.endive.runtime.CompiledModule; import run.endive.runtime.Instance; import run.endive.runtime.Machine; +import run.endive.wasm.MalformedException; import run.endive.wasm.Parser; import run.endive.wasm.WasmModule; import run.endive.wasm.WasmWriter; @@ -155,7 +156,9 @@ public void generateMetaWasm(Set interpretedFunctions) throws IOExcepti int count = module.codeSection().functionBodyCount(); writeVarUInt32(out, count); var actual = readVarUInt32(source); - assert count == actual; + if (count != actual) { + throw new MalformedException("wrong number of function bodies"); + } for (int i = 0; i < count; i++) { var funcId = importFuncs + i; if (interpretedFunctions.contains(funcId)) { @@ -177,7 +180,10 @@ public void generateMetaWasm(Set interpretedFunctions) throws IOExcepti var bodySize = (int) readVarUInt32(source); source.position(source.position() + bodySize - 1); var end_op = source.get(); - assert end_op == OpCode.END.opcode(); + if (end_op != OpCode.END.opcode()) { + throw new MalformedException( + "unexpected end opcode: " + end_op); + } // Write an empty function body writeVarUInt32(out, 3); // function size in bytes diff --git a/compiler/src/main/java/run/endive/compiler/internal/Emitters.java b/compiler/src/main/java/run/endive/compiler/internal/Emitters.java index 7b336649f..7c10aabe2 100644 --- a/compiler/src/main/java/run/endive/compiler/internal/Emitters.java +++ b/compiler/src/main/java/run/endive/compiler/internal/Emitters.java @@ -38,6 +38,7 @@ import run.endive.runtime.Instance; import run.endive.runtime.OpCodeIdentifier; import run.endive.runtime.WasmException; +import run.endive.wasm.WasmEngineException; import run.endive.wasm.WasmModule; import run.endive.wasm.types.FunctionType; import run.endive.wasm.types.ValType; @@ -104,13 +105,15 @@ public static ValType valType(long id, Context ctx) { } private static void assertTempSlotInRange(Context ctx, int slotsNeeded) { - assert ctx.tempSlot() + slotsNeeded <= ctx.trySaveBaseSlot() - : "temp slot overflow: need " - + slotsNeeded - + " slots at " - + ctx.tempSlot() - + " but try-save starts at " - + ctx.trySaveBaseSlot(); + if (ctx.tempSlot() + slotsNeeded > ctx.trySaveBaseSlot()) { + throw new WasmEngineException( + "temp slot overflow: need " + + slotsNeeded + + " slots at " + + ctx.tempSlot() + + " but try-save starts at " + + ctx.trySaveBaseSlot()); + } } /** diff --git a/runtime/src/main/java/run/endive/runtime/GlobalInstance.java b/runtime/src/main/java/run/endive/runtime/GlobalInstance.java index 35573be3b..aec4ca19e 100644 --- a/runtime/src/main/java/run/endive/runtime/GlobalInstance.java +++ b/runtime/src/main/java/run/endive/runtime/GlobalInstance.java @@ -89,7 +89,10 @@ public ValType getType() { } public void setValue(Value value) { - assert (value.type() == valType); + if (value.type() != valType) { + throw new IllegalArgumentException( + "Value has wrong type; expected " + valType + " got " + value.type()); + } this.valueLow = value.raw(); } diff --git a/runtime/src/main/java/run/endive/runtime/InterpreterMachine.java b/runtime/src/main/java/run/endive/runtime/InterpreterMachine.java index 5a8b062ff..6849fa0f5 100644 --- a/runtime/src/main/java/run/endive/runtime/InterpreterMachine.java +++ b/runtime/src/main/java/run/endive/runtime/InterpreterMachine.java @@ -3215,7 +3215,7 @@ protected static StackFrame THROW_REF( frame = callStack.peek(); // peek, don't pop - keep catcher on callStack } } - throw new RuntimeException("unreacheable"); + throw new RuntimeException("unreachable"); } private static void BLOCK( diff --git a/runtime/src/main/java/run/endive/runtime/OpcodeImpl.java b/runtime/src/main/java/run/endive/runtime/OpcodeImpl.java index 9db8a019b..450c68128 100644 --- a/runtime/src/main/java/run/endive/runtime/OpcodeImpl.java +++ b/runtime/src/main/java/run/endive/runtime/OpcodeImpl.java @@ -917,9 +917,12 @@ public static long unboxFromTable(int tableValue, Instance instance, ValType ele impl = java.lang.invoke.VarHandle::fullFence; } catch (NoSuchMethodError e) { try { - // Suppress IntelliJ warning about module-info.java needing `requires jdk.unsupported` for - // `sun.misc.Unsafe`. This code here is only a fallback when `VarHandle::fullFence` is unavailable, - // which is only the case for Java < 9 (and therefore module-info.java is irrelevant). + // Suppress IntelliJ warning about module-info.java needing `requires + // jdk.unsupported` for + // `sun.misc.Unsafe`. This code here is only a fallback when `VarHandle::fullFence` + // is unavailable, + // which is only the case for Java < 9 (and therefore module-info.java is + // irrelevant). @SuppressWarnings("Java9ReflectionClassVisibility") Class unsafeClass = Class.forName("sun.misc.Unsafe"); var theUnsafeField = unsafeClass.getDeclaredField("theUnsafe"); diff --git a/wasm/src/main/java/run/endive/wasm/Parser.java b/wasm/src/main/java/run/endive/wasm/Parser.java index 3eda7a7c9..ce5383706 100644 --- a/wasm/src/main/java/run/endive/wasm/Parser.java +++ b/wasm/src/main/java/run/endive/wasm/Parser.java @@ -785,7 +785,9 @@ private static TableSection parseTableSection(ByteBuffer buffer, TypeSection typ var firstByte = (int) readVarUInt32(buffer); if (firstByte == 0x40) { var secondByte = readVarUInt32(buffer); - assert secondByte == 0x00; + if (secondByte != 0x00) { + throw new MalformedException("incorrect second byte"); + } var tableType = readValueType(buffer, typeSection); var limits = readTableLimits(buffer); var init = parseExpression(buffer); diff --git a/wasm/src/main/java/run/endive/wasm/Validator.java b/wasm/src/main/java/run/endive/wasm/Validator.java index bf52b0e3d..994b44c1b 100644 --- a/wasm/src/main/java/run/endive/wasm/Validator.java +++ b/wasm/src/main/java/run/endive/wasm/Validator.java @@ -1033,7 +1033,9 @@ void validateFunction(int funcIdx, FunctionBody body, FunctionType functionType) } var type = module.typeSection().getType(getTagType(tagNumber).typeIdx()); popVals(type.params()); - assert (type.returns().size() == 0); + if (!type.returns().isEmpty()) { + throw new InvalidException("expected no returns"); + } unreachable(); break; } diff --git a/wasm/src/main/java/run/endive/wasm/types/AnnotatedInstruction.java b/wasm/src/main/java/run/endive/wasm/types/AnnotatedInstruction.java index d6034d3df..15959d4d6 100644 --- a/wasm/src/main/java/run/endive/wasm/types/AnnotatedInstruction.java +++ b/wasm/src/main/java/run/endive/wasm/types/AnnotatedInstruction.java @@ -4,7 +4,6 @@ import java.util.Objects; import java.util.Optional; import java.util.OptionalInt; - import run.endive.wasm.InvalidException; /* @@ -156,10 +155,14 @@ public AnnotatedInstruction build() { case END: case IF: case TRY_TABLE: - assert (scope.isPresent()); + if (scope.isEmpty()) { + throw new InvalidException("unknown scope"); + } break; default: - assert (scope.isEmpty()); + if (scope.isPresent()) { + throw new InvalidException("scope is not empty"); + } break; } switch (base.opcode()) { @@ -180,8 +183,9 @@ public AnnotatedInstruction build() { } break; default: - assert (labelTrue.isEmpty()); - assert (labelFalse.isEmpty()); + if (!(labelTrue.isEmpty() && labelFalse.isEmpty())) { + throw new InvalidException("labels are not empty"); + } break; } switch (base.opcode()) { @@ -191,7 +195,9 @@ public AnnotatedInstruction build() { } break; default: - assert (labelTable.isEmpty()); + if (labelTable.isPresent()) { + throw new InvalidException("label table is not empty"); + } break; } switch (base.opcode()) { @@ -201,7 +207,9 @@ public AnnotatedInstruction build() { } break; default: - assert (catches.isEmpty()); + if (catches.isPresent()) { + throw new InvalidException("catches is not empty"); + } break; } diff --git a/wasm/src/main/java/run/endive/wasm/types/CatchOpCode.java b/wasm/src/main/java/run/endive/wasm/types/CatchOpCode.java index 2a951fd70..2969fa3c1 100644 --- a/wasm/src/main/java/run/endive/wasm/types/CatchOpCode.java +++ b/wasm/src/main/java/run/endive/wasm/types/CatchOpCode.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import run.endive.wasm.WasmEngineException; public enum CatchOpCode { CATCH(0x00), @@ -98,7 +99,9 @@ public static List decode(long[] operands) { } } } - assert (result.size() == length); + if (result.size() != length) { + throw new WasmEngineException("wrong result size"); + } return result; } diff --git a/wasm/src/main/java/run/endive/wasm/types/NameCustomSection.java b/wasm/src/main/java/run/endive/wasm/types/NameCustomSection.java index 582116cd7..fe7bdb78f 100644 --- a/wasm/src/main/java/run/endive/wasm/types/NameCustomSection.java +++ b/wasm/src/main/java/run/endive/wasm/types/NameCustomSection.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Optional; import java.util.function.ToIntFunction; +import run.endive.wasm.WasmEngineException; /** * The "name" custom section. @@ -74,7 +75,9 @@ public static NameCustomSection parse(byte[] bytes) { // todo: IDs 4 and 10 are reserved for the Host GC spec switch (id) { case 0: - assert (moduleName == null); + if (moduleName != null) { + throw new WasmEngineException("duplicate module name"); + } moduleName = readName(slice); break; case 1: diff --git a/wasm/src/main/java/run/endive/wasm/types/RecType.java b/wasm/src/main/java/run/endive/wasm/types/RecType.java index 05b82430b..4748b6e2b 100644 --- a/wasm/src/main/java/run/endive/wasm/types/RecType.java +++ b/wasm/src/main/java/run/endive/wasm/types/RecType.java @@ -21,7 +21,9 @@ public boolean isLegacy() { } public FunctionType legacy() { - assert subTypes.length == 1; + if (!isLegacy()) { + throw new IllegalStateException("type is not legacy"); + } return subTypes[0].compType().funcType(); } diff --git a/wasm/src/main/java/run/endive/wasm/types/Value.java b/wasm/src/main/java/run/endive/wasm/types/Value.java index adb717a79..a0627d843 100644 --- a/wasm/src/main/java/run/endive/wasm/types/Value.java +++ b/wasm/src/main/java/run/endive/wasm/types/Value.java @@ -65,23 +65,30 @@ public static Value fromFloat(float data) { return Value.f32(floatToLong(data)); } + private void expectType(ValType expected) { + if (type != expected) { + throw new IllegalStateException( + "Expected value to have type " + expected + " but is " + type); + } + } + public int asInt() { - assert (type == ValType.I32); + expectType(ValType.I32); return (int) data; } public long asLong() { - assert (type == ValType.I64); + expectType(ValType.I64); return data; } public float asFloat() { - assert (type == ValType.F32); + expectType(ValType.F32); return longToFloat(data); } public double asDouble() { - assert (type == ValType.F64); + expectType(ValType.F64); return longToDouble(data); } @@ -332,7 +339,7 @@ public String toString() { case ValType.ID.RefNull: return "refnull[" + (int) data + "]"; default: - throw new AssertionError("Unhandled type: " + type); + return data + "@" + type; } } diff --git a/wasm/src/test/java/run/endive/wasm/types/ValTypeTest.java b/wasm/src/test/java/run/endive/wasm/types/ValTypeTest.java index 080e10519..e1744a607 100644 --- a/wasm/src/test/java/run/endive/wasm/types/ValTypeTest.java +++ b/wasm/src/test/java/run/endive/wasm/types/ValTypeTest.java @@ -33,7 +33,7 @@ public void roundtrip() { for (var vt : cases) { long id = vt.id(); ValType roundTrip = ValType.builder().fromId(id).build(); - assert vt.equals(roundTrip) : "Failed to roundtrip: " + vt; + assertEquals(vt, roundTrip); } }