From 41c5a21c0e812a50624c41d3d34af50c80de1971 Mon Sep 17 00:00:00 2001 From: Stanca Serban Date: Thu, 21 Dec 2023 06:36:41 +0200 Subject: [PATCH] Backed out changeset d53c38086d1b (bug 1853454) for causing spidermonkey build bustages in try-table.js. CLOSED TREE --- js/public/WasmFeatures.h | 13 +- js/src/jit-test/tests/wasm/exnref/directives.txt | 1 - js/src/jit-test/tests/wasm/exnref/throw-ref.js | 41 --- js/src/jit-test/tests/wasm/exnref/try-table.js | 200 ------------ js/src/wasm/WasmBCClass.h | 6 - js/src/wasm/WasmBaselineCompile.cpp | 237 -------------- js/src/wasm/WasmBinary.h | 15 - js/src/wasm/WasmConstants.h | 8 - js/src/wasm/WasmDump.cpp | 6 - js/src/wasm/WasmException.h | 14 - js/src/wasm/WasmIonCompile.cpp | 381 ++++------------------- js/src/wasm/WasmOpIter.cpp | 4 - js/src/wasm/WasmOpIter.h | 136 +------- js/src/wasm/WasmTypeDef.h | 3 - js/src/wasm/WasmValType.cpp | 8 - js/src/wasm/WasmValType.h | 13 +- js/src/wasm/WasmValidate.cpp | 13 - js/src/wasm/WasmValue.cpp | 9 - 18 files changed, 68 insertions(+), 1040 deletions(-) delete mode 100644 js/src/jit-test/tests/wasm/exnref/directives.txt delete mode 100644 js/src/jit-test/tests/wasm/exnref/throw-ref.js delete mode 100644 js/src/jit-test/tests/wasm/exnref/try-table.js diff --git a/js/public/WasmFeatures.h b/js/public/WasmFeatures.h index f2089f7fba63..b6b63e606b8d 100644 --- a/js/public/WasmFeatures.h +++ b/js/public/WasmFeatures.h @@ -132,22 +132,11 @@ enum class WasmFeatureStage { /* compile predicate */ true, \ /* compiler predicate */ AnyCompilerAvailable(cx), \ /* flag predicate */ true, \ - /* flag force enable */ WasmExnRefFlag(cx), \ + /* flag force enable */ false, \ /* flag fuzz enable */ true, \ /* shell flag */ "exceptions", \ /* preference name */ "exceptions") \ FEATURE( \ - /* capitalized name */ ExnRef, \ - /* lower case name */ exnref, \ - /* stage */ WasmFeatureStage::Experimental, \ - /* compile predicate */ true, \ - /* compiler predicate */ AnyCompilerAvailable(cx), \ - /* flag predicate */ true, \ - /* flag force enable */ false, \ - /* flag fuzz enable */ true, \ - /* shell flag */ "exnref", \ - /* preference name */ "exnref ") \ - FEATURE( \ /* capitalized name */ FunctionReferences, \ /* lower case name */ functionReferences, \ /* stage */ WasmFeatureStage::Tentative, \ diff --git a/js/src/jit-test/tests/wasm/exnref/directives.txt b/js/src/jit-test/tests/wasm/exnref/directives.txt deleted file mode 100644 index bc17009ea814..000000000000 --- a/js/src/jit-test/tests/wasm/exnref/directives.txt +++ /dev/null @@ -1 +0,0 @@ -|jit-test| --wasm-exnref; test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--wasm-test-serialization; test-also=--test-wasm-await-tier2; include:wasm.js; skip-if: !wasmExnRefEnabled() diff --git a/js/src/jit-test/tests/wasm/exnref/throw-ref.js b/js/src/jit-test/tests/wasm/exnref/throw-ref.js deleted file mode 100644 index 2454a4f5008e..000000000000 --- a/js/src/jit-test/tests/wasm/exnref/throw-ref.js +++ /dev/null @@ -1,41 +0,0 @@ -wasmFailValidateText(`(module - (func - throw_ref - ) -)`, /popping value from empty stack/); - -wasmValidateText(`(module - (func (param exnref) - local.get 0 - throw_ref - ) -)`); - -// Can rethrow a value -{ - let {test} = wasmEvalText(`(module - (tag $a) - (func (export "test") - try_table (result exnref) (catch_all_ref 0) - throw $a - unreachable - end - throw_ref - ) - )`).exports; - - assertErrorMessage(test, WebAssembly.Exception, /.*/); -} - -// Traps on null -{ - let {test} = wasmEvalText(`(module - (tag $a) - (func (export "test") - ref.null exn - throw_ref - ) - )`).exports; - - assertErrorMessage(test, WebAssembly.RuntimeError, /null/); -} diff --git a/js/src/jit-test/tests/wasm/exnref/try-table.js b/js/src/jit-test/tests/wasm/exnref/try-table.js deleted file mode 100644 index 1970f8d41ff3..000000000000 --- a/js/src/jit-test/tests/wasm/exnref/try-table.js +++ /dev/null @@ -1,200 +0,0 @@ -// A try_table acts like a block label -{ - let {test} = wasmEvalText(`(module - (func (export "test") (result i32) - try_table - br 0 - (return i32.const 0) - end - (return i32.const 1) - ) - )`).exports; - assertEq(test(), 1); -} - -// A try_table can have results -{ - let {test} = wasmEvalText(`(module - (func (export "test") (result i32) - try_table (result i32) - i32.const 1 - br 0 - end - ) - )`).exports; - assertEq(test(), 1); -} - -// A try_table can have params -{ - let {test} = wasmEvalText(`(module - (func (export "test") (result i32) - i32.const 1 - try_table (param i32) - return - end - (return i32.const 0) - ) - )`).exports; - assertEq(test(), 1); -} - -// Test try_table catching exceptions -{ - let {test} = wasmEvalText(`(module - (tag $A (param i32)) - (tag $B (param i32)) - (tag $C) - - (table funcref (elem $throwA $throwB $throwC $doNothing)) - - (type $empty (func)) - (func $throwA - i32.const 1 - throw $A - ) - (func $throwB - i32.const 2 - throw $B - ) - (func $throwC - throw $C - ) - (func $doNothing) - - (func (export "test") (param i32) (result i32) - block $handleA (result i32 exnref) - block $handleB (result i32 exnref) - block $handleUnknown (result exnref) - try_table - (catch_ref $A $handleA) - (catch_ref $B $handleB) - (catch_all_ref $handleUnknown) - - (call_indirect (type $empty) - local.get 0) - end - (; nothing threw ;) - i32.const -1 - return - end - (; $handleUnknown ;) - drop - i32.const 3 - return - end - (; $handleB ;) - drop - return - end - (; $handleA ;) - drop - return - ) - )`).exports; - // Throwing A results in 1 from the payload from the catch - assertEq(test(0), 1); - // Throwing B results in 2 from the payload from the catch - assertEq(test(1), 2); - // Throwing C results in 3 from the constant in the catch_all - assertEq(test(2), 3); - // Not throwing anything gets -1 from the fallthrough - assertEq(test(3), -1); -} - -// Test try_table catching exceptions without capturing the exnref -{ - let {test} = wasmEvalText(`(module - (tag $A (param i32)) - (tag $B (param i32)) - (tag $C) - - (table funcref (elem $throwA $throwB $throwC $doNothing)) - - (type $empty (func)) - (func $throwA - i32.const 1 - throw $A - ) - (func $throwB - i32.const 2 - throw $B - ) - (func $throwC - throw $C - ) - (func $doNothing) - - (func (export "test") (param i32) (result i32) - block $handleA (result i32) - block $handleB (result i32) - block $handleUnknown - try_table - (catch $A $handleA) - (catch $B $handleB) - (catch_all $handleUnknown) - - (call_indirect (type $empty) - local.get 0) - end - (; nothing threw ;) - i32.const -1 - return - end - (; $handleUnknown ;) - i32.const 3 - return - end - (; $handleB ;) - return - end - (; $handleA ;) - return - ) - )`).exports; - // Throwing A results in 1 from the payload from the catch - assertEq(test(0), 1); - // Throwing B results in 2 from the payload from the catch - assertEq(test(1), 2); - // Throwing C results in 3 from the constant in the catch_all - assertEq(test(2), 3); - // Not throwing anything gets -1 from the fallthrough - assertEq(test(3), -1); -} - -// Test try_table catching and rethrowing JS exceptions -{ - let tag = new WebAssembly.Tag({parameters: []}); - let exn = new WebAssembly.Exception(tag, []); - let values = [...WasmExternrefValues, exn]; - function throwJS(value) { - throw value; - } - let {test} = wasmEvalText(`(module - (import "" "tag" (tag $tag)) - (import "" "throwJS" (func $throwJS (param externref))) - (func (export "test") (param externref) - try_table (result exnref) (catch_ref $tag 0) (catch_all_ref 0) - local.get 0 - call $throwJS - return - end - throw_ref - ) - )`, {"": {tag, throwJS}}).exports; - - for (let value of values) { - // TODO: A JS null value should become a non-null exnref that can be - // rethrown without a trap. - if (value === null) { - continue; - } - - try { - test(value); - assertEq(true, false); - } catch (thrownValue) { - assertEq(thrownValue, value); - } - } -} diff --git a/js/src/wasm/WasmBCClass.h b/js/src/wasm/WasmBCClass.h index d75ae2abc59c..a92440a97e37 100644 --- a/js/src/wasm/WasmBCClass.h +++ b/js/src/wasm/WasmBCClass.h @@ -81,9 +81,6 @@ struct Control { deadOnArrival(false), deadThenBranch(false), tryNoteIndex(0) {} - - Control(Control&&) = default; - Control(const Control&) = delete; }; // A vector of Nothing values, used for reading opcodes. @@ -1397,12 +1394,10 @@ struct BaseCompiler final { [[nodiscard]] bool emitBodyDelegateThrowPad(); [[nodiscard]] bool emitTry(); - [[nodiscard]] bool emitTryTable(); [[nodiscard]] bool emitCatch(); [[nodiscard]] bool emitCatchAll(); [[nodiscard]] bool emitDelegate(); [[nodiscard]] bool emitThrow(); - [[nodiscard]] bool emitThrowRef(); [[nodiscard]] bool emitRethrow(); [[nodiscard]] bool emitEnd(); [[nodiscard]] bool emitBr(); @@ -1459,7 +1454,6 @@ struct BaseCompiler final { [[nodiscard]] bool endIfThen(ResultType type); [[nodiscard]] bool endIfThenElse(ResultType type); [[nodiscard]] bool endTryCatch(ResultType type); - [[nodiscard]] bool endTryTable(ResultType type); void doReturn(ContinuationKind kind); void pushReturnValueOfCall(const FunctionCall& call, MIRType type); diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index 811513bbbfa3..3b2cfe0ff413 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -3804,12 +3804,6 @@ bool BaseCompiler::emitEnd() { } iter_.popEnd(); break; - case LabelKind::TryTable: - if (!endTryTable(type)) { - return false; - } - iter_.popEnd(); - break; } return true; @@ -4066,201 +4060,6 @@ bool BaseCompiler::emitTry() { return true; } -bool BaseCompiler::emitTryTable() { - ResultType params; - TryTableCatchVector catches; - if (!iter_.readTryTable(¶ms, &catches)) { - return false; - } - - if (deadCode_) { - return true; - } - - // Simplifies jumping out, but it is also necessary so that control - // can re-enter the catch handler without restoring registers. - sync(); - - initControl(controlItem(), params); - // Be conservative for BCE due to complex control flow in try blocks. - controlItem().bceSafeOnExit = 0; - - // Emit a landing pad that exceptions will jump into. Jump over it for now. - Label skip; - masm.jump(&skip); - - StackHeight prePadHeight = fr.stackHeight(); - uint32_t padOffset = masm.currentOffset(); - uint32_t padStackHeight = masm.framePushed(); - - // Store the Instance that was left in InstanceReg by the exception - // handling mechanism, that is this frame's Instance but with the exception - // filled in Instance::pendingException. - fr.storeInstancePtr(InstanceReg); - - // Ensure we don't take the result register that we'll need for passing - // results to the branch target. - // - // TODO: future proof this code for multiple result registers. - ResultType resultRegs = ResultType::Single(RefType::extern_()); - needIntegerResultRegisters(resultRegs); - // Load exception pointer from Instance and make sure that it is - // saved before the following call will clear it. - RegRef exn; - RegRef exnTag; - consumePendingException(&exn, &exnTag); - - // Get a register to hold the tags for each catch - RegRef catchTag = needRef(); - // Get a register for unpacking exceptions - RegPtr data = needPtr(); - freeIntegerResultRegisters(resultRegs); - - bool hadCatchAll = false; - for (const TryTableCatch& tryTableCatch : catches) { - ResultType labelParams = ResultType::Vector(tryTableCatch.labelType); - - Control& target = controlItem(tryTableCatch.labelRelativeDepth); - target.bceSafeOnExit = 0; - - // Handle a catch_all by jumping to the target block - if (tryTableCatch.tagIndex == CatchAllIndex) { - // Capture the exnref if it has been requested - if (tryTableCatch.captureExnRef) { - pushRef(exn); - } - popBlockResults(labelParams, target.stackHeight, ContinuationKind::Jump); - masm.jump(&target.label); - // The registers holding the join values are free for the remainder of - // this block. - freeResultRegisters(labelParams); - // Free the exn register, as code assumes that it's consumed by the final - // catch_all. - if (!tryTableCatch.captureExnRef) { - freeRef(exn); - } - - // Break from the loop and skip the implicit rethrow that's needed - // if we didn't have a catch_all - hadCatchAll = true; - break; - } - - const TagType& tagType = *moduleEnv_.tags[tryTableCatch.tagIndex].type; - const TagOffsetVector& tagOffsets = tagType.argOffsets(); - ResultType tagParams = tagType.resultType(); - - Label skip; - loadTag(RegPtr(InstanceReg), tryTableCatch.tagIndex, catchTag); - masm.branchPtr(Assembler::NotEqual, exnTag, catchTag, &skip); - - // Unpack the tag and jump to the block - masm.loadPtr(Address(exn, (int32_t)WasmExceptionObject::offsetOfData()), - data); - // This method can increase stk_.length() by an unbounded amount, so we need - // to perform an allocation here to accomodate the variable number of - // values. There is enough headroom for the fixed number of values. The - // general case is handled in emitBody. - if (!stk_.reserve(stk_.length() + labelParams.length())) { - return false; - } - - for (uint32_t i = 0; i < tagParams.length(); i++) { - int32_t offset = tagOffsets[i]; - switch (tagParams[i].kind()) { - case ValType::I32: { - RegI32 reg = needI32(); - masm.load32(Address(data, offset), reg); - pushI32(reg); - break; - } - case ValType::I64: { - RegI64 reg = needI64(); - masm.load64(Address(data, offset), reg); - pushI64(reg); - break; - } - case ValType::F32: { - RegF32 reg = needF32(); - masm.loadFloat32(Address(data, offset), reg); - pushF32(reg); - break; - } - case ValType::F64: { - RegF64 reg = needF64(); - masm.loadDouble(Address(data, offset), reg); - pushF64(reg); - break; - } - case ValType::V128: { -#ifdef ENABLE_WASM_SIMD - RegV128 reg = needV128(); - masm.loadUnalignedSimd128(Address(data, offset), reg); - pushV128(reg); - break; -#else - MOZ_CRASH("No SIMD support"); -#endif - } - case ValType::Ref: { - RegRef reg = needRef(); - masm.loadPtr(Address(data, offset), reg); - pushRef(reg); - break; - } - } - } - - // Capture the exnref if it has been requested - if (tryTableCatch.captureExnRef) { - pushRef(exn); - } - popBlockResults(labelParams, target.stackHeight, ContinuationKind::Jump); - masm.jump(&target.label); - // The registers holding the join values are free for the remainder of this - // block. - freeResultRegisters(labelParams); - - masm.bind(&skip); - - // Re-assert ownership of the exnref register for the next branch of the - // try switch. - if (tryTableCatch.captureExnRef) { - needRef(exn); - } - } - - if (!hadCatchAll) { - // If none of the tag checks succeed and there is no catch_all, - // then we rethrow the exception. - if (!throwFrom(exn)) { - return false; - } - } else { - // `exn` should be consumed by the catch_all code so it doesn't leak - MOZ_ASSERT(isAvailableRef(exn)); - } - - freePtr(data); - freeRef(catchTag); - freeRef(exnTag); - - // Reset stack height for skip. - fr.setStackHeight(prePadHeight); - - masm.bind(&skip); - - if (!startTryNote(&controlItem().tryNoteIndex)) { - return false; - } - // The landing pad begins at this point - TryNoteVector& tryNotes = masm.tryNotes(); - TryNote& tryNote = tryNotes[controlItem().tryNoteIndex]; - tryNote.setLandingPad(padOffset, padStackHeight); - - return true; -} - void BaseCompiler::emitCatchSetup(LabelKind kind, Control& tryCatch, const ResultType& resultType) { // Catch ends the try or last catch, so we finish this like endIfThen. @@ -4661,12 +4460,6 @@ bool BaseCompiler::endTryCatch(ResultType type) { return pushBlockResults(type); } -bool BaseCompiler::endTryTable(ResultType type) { - // Mark the end of the try body. This may insert a nop. - finishTryNote(controlItem().tryNoteIndex); - return endBlock(type); -} - bool BaseCompiler::emitThrow() { uint32_t tagIndex; BaseNothingVector unused_argValues{}; @@ -4772,26 +4565,6 @@ bool BaseCompiler::emitThrow() { return throwFrom(exn); } -bool BaseCompiler::emitThrowRef() { - Nothing unused{}; - - if (!iter_.readThrowRef(&unused)) { - return false; - } - - if (deadCode_) { - return true; - } - - RegRef exn = popRef(); - Label ok; - masm.branchWasmAnyRefIsNull(false, exn, &ok); - trap(Trap::NullPointerDereference); - masm.bind(&ok); - deadCode_ = true; - return throwFrom(exn); -} - bool BaseCompiler::emitRethrow() { uint32_t relativeDepth; if (!iter_.readRethrow(&relativeDepth)) { @@ -9904,16 +9677,6 @@ bool BaseCompiler::emitBody() { return iter_.unrecognizedOpcode(&op); } CHECK_NEXT(emitRethrow()); - case uint16_t(Op::ThrowRef): - if (!moduleEnv_.exnrefEnabled()) { - return iter_.unrecognizedOpcode(&op); - } - CHECK_NEXT(emitThrowRef()); - case uint16_t(Op::TryTable): - if (!moduleEnv_.exnrefEnabled()) { - return iter_.unrecognizedOpcode(&op); - } - CHECK_NEXT(emitTryTable()); case uint16_t(Op::Br): CHECK_NEXT(emitBr()); case uint16_t(Op::BrIf): diff --git a/js/src/wasm/WasmBinary.h b/js/src/wasm/WasmBinary.h index b2be20b4a7df..3713dc1dbb1e 100644 --- a/js/src/wasm/WasmBinary.h +++ b/js/src/wasm/WasmBinary.h @@ -636,7 +636,6 @@ inline ValType Decoder::uncheckedReadValType(const TypeContext& types) { switch (code) { case uint8_t(TypeCode::FuncRef): case uint8_t(TypeCode::ExternRef): - case uint8_t(TypeCode::ExnRef): return RefType::fromTypeCode(TypeCode(code), true); case uint8_t(TypeCode::Ref): case uint8_t(TypeCode::NullableRef): { @@ -684,13 +683,6 @@ inline bool Decoder::readPackedType(const TypeContext& types, *type = RefType::fromTypeCode(TypeCode(code), true); return true; } - case uint8_t(TypeCode::ExnRef): { - if (!features.exnref) { - return fail("exnref not enabled"); - } - *type = RefType::fromTypeCode(TypeCode(code), true); - return true; - } case uint8_t(TypeCode::Ref): case uint8_t(TypeCode::NullableRef): { #ifdef ENABLE_WASM_FUNCTION_REFERENCES @@ -767,13 +759,6 @@ inline bool Decoder::readHeapType(const TypeContext& types, case uint8_t(TypeCode::ExternRef): *type = RefType::fromTypeCode(TypeCode(code), nullable); return true; - case uint8_t(TypeCode::ExnRef): { - if (!features.exnref) { - return fail("exnref not enabled"); - } - *type = RefType::fromTypeCode(TypeCode(code), nullable); - return true; - } #ifdef ENABLE_WASM_GC case uint8_t(TypeCode::AnyRef): case uint8_t(TypeCode::I31Ref): diff --git a/js/src/wasm/WasmConstants.h b/js/src/wasm/WasmConstants.h index 0ce741b2d0b2..fa61fa36b913 100644 --- a/js/src/wasm/WasmConstants.h +++ b/js/src/wasm/WasmConstants.h @@ -100,9 +100,6 @@ enum class TypeCode { // A reference to any array value. ArrayRef = 0x6a, // SLEB128(-0x16) - // A reference to an exception value. - ExnRef = 0x69, // SLEB128(-0x17) - // A null reference in the any hierarchy. NullAnyRef = 0x71, // SLEB128(-0x0F) @@ -268,7 +265,6 @@ enum class Op { Catch = 0x07, Throw = 0x08, Rethrow = 0x09, - ThrowRef = 0x0a, End = 0x0b, Br = 0x0c, BrIf = 0x0d, @@ -292,9 +288,6 @@ enum class Op { SelectNumeric = 0x1b, SelectTyped = 0x1c, - // Additional exception operators - TryTable = 0x1f, - // Variable access LocalGet = 0x20, LocalSet = 0x21, @@ -1148,7 +1141,6 @@ static_assert(uint64_t(MaxArrayPayloadBytes) < // These limits pertain to our WebAssembly implementation only. -static const unsigned MaxTryTableCatches = 10000; static const unsigned MaxBrTableElems = 1000000; static const unsigned MaxCodeSectionBytes = MaxModuleBytes; diff --git a/js/src/wasm/WasmDump.cpp b/js/src/wasm/WasmDump.cpp index c0a931556b3f..ce6dcf9819fc 100644 --- a/js/src/wasm/WasmDump.cpp +++ b/js/src/wasm/WasmDump.cpp @@ -96,9 +96,6 @@ void wasm::Dump(RefType type, GenericPrinter& out) { case RefType::Array: literal = "arrayref"; break; - case RefType::Exn: - literal = "exnref"; - break; case RefType::TypeRef: { MOZ_CRASH("type ref should not be possible here"); } @@ -140,9 +137,6 @@ void wasm::Dump(RefType type, GenericPrinter& out) { case RefType::Array: heapType = "array"; break; - case RefType::Exn: - heapType = "exn"; - break; case RefType::TypeRef: { uintptr_t typeAddress = (uintptr_t)type.typeDef(); out.printf("(ref %s0x%" PRIxPTR ")", type.isNullable() ? "null " : "", diff --git a/js/src/wasm/WasmException.h b/js/src/wasm/WasmException.h index 06d9529c17bb..d9cfcfb8b025 100644 --- a/js/src/wasm/WasmException.h +++ b/js/src/wasm/WasmException.h @@ -25,20 +25,6 @@ namespace wasm { static const uint32_t CatchAllIndex = UINT32_MAX; static_assert(CatchAllIndex > MaxTags); -struct TryTableCatch { - // The tag index for this catch, or CatchAllIndex for a catch_all. - uint32_t tagIndex; - // The relative depth of where to branch to when catching an exception. - uint32_t labelRelativeDepth; - // Whether the exnref that is caught should be captured and passed to the - // branch target. - bool captureExnRef; - // The params that the target branch at `labelRelativeDepth` expects. This - // includes any exnref that should or should not be captured. - ValTypeVector labelType; -}; -using TryTableCatchVector = Vector; - } // namespace wasm } // namespace js diff --git a/js/src/wasm/WasmIonCompile.cpp b/js/src/wasm/WasmIonCompile.cpp index bb43677bb462..88d6b3909dd9 100644 --- a/js/src/wasm/WasmIonCompile.cpp +++ b/js/src/wasm/WasmIonCompile.cpp @@ -63,33 +63,18 @@ using DefVector = Vector; using ControlInstructionVector = Vector; -struct TryControl { - // Branches to bind to the try's landing pad. - ControlInstructionVector landingPadPatches; - // For `try_table`, the list of tagged catches and labels to branch to. - TryTableCatchVector catches; - // Whether this try is in the body and should catch any thrown exception. - bool inBody; - - TryControl() : inBody(false) {} - - // Reset the try control for when it is cached in FunctionCompiler. - void reset() { - landingPadPatches.clearAndFree(); - catches.clearAndFree(); - inBody = false; - } -}; -using UniqueTryControl = UniquePtr; -using VectorUniqueTryControl = Vector; - struct Control { MBasicBlock* block; - UniqueTryControl tryControl; + // For a try-catch ControlItem, when its block's Labelkind is Try, this + // collects branches to later bind and create the try's landing pad. + ControlInstructionVector tryPadPatches; + + Control() : block(nullptr) {} + + explicit Control(MBasicBlock* block) : block(block) {} - Control() : block(nullptr), tryControl(nullptr) {} - Control(Control&&) = default; - Control(const Control&) = delete; + public: + void setBlock(MBasicBlock* newBlock) { block = newBlock; } }; // [SMDOC] WebAssembly Exception Handling in Ion @@ -255,10 +240,6 @@ class FunctionCompiler { uint32_t loopDepth_; uint32_t blockDepth_; ControlFlowPatchVectorVector blockPatches_; - // Control flow patches created by `delegate` instructions that target the - // outermost label of this function. These will be bound to a pad that will - // do a rethrow in `emitBodyDelegateThrowPad`. - ControlInstructionVector bodyDelegatePadPatches_; // Instance pointer argument to the current function. MWasmParameter* instancePointer_; @@ -267,9 +248,6 @@ class FunctionCompiler { // Reference to masm.tryNotes_ wasm::TryNoteVector& tryNotes_; - // Cache of TryControl to minimize heap allocations - VectorUniqueTryControl tryControlCache_; - public: FunctionCompiler(const ModuleEnvironment& moduleEnv, Decoder& decoder, const FuncCompileInput& func, const ValTypeVector& locals, @@ -306,24 +284,6 @@ class FunctionCompiler { return moduleEnv_.isAsmJS() ? BytecodeOffset() : iter_.bytecodeOffset(); } - // Try to get a free TryControl from the cache, or allocate a new one. - [[nodiscard]] UniqueTryControl newTryControl() { - if (tryControlCache_.empty()) { - return UniqueTryControl(js_new()); - } - UniqueTryControl tryControl = std::move(tryControlCache_.back()); - tryControlCache_.popBack(); - return tryControl; - } - - // Release the TryControl to the cache. - void freeTryControl(UniqueTryControl&& tryControl) { - // Ensure that it's in a consistent state - tryControl->reset(); - // Ignore any OOM, as we'll fail later - (void)tryControlCache_.append(std::move(tryControl)); - } - [[nodiscard]] bool init() { // Prepare the entry block for MIR generation: @@ -2399,19 +2359,16 @@ class FunctionCompiler { } CallSiteDesc desc(lineOrBytecode, CallSiteDesc::Symbolic); - MInstruction* ins; - ins = MWasmCallUncatchable::NewBuiltinInstanceMethodCall( + auto* ins = MWasmCallUncatchable::NewBuiltinInstanceMethodCall( alloc(), desc, builtin.identity, builtin.failureMode, call.instanceArg_, call.regArgs_, StackArgAreaSizeUnaligned(builtin)); if (!ins) { return false; } + curBlock_->add(ins); - if (!def) { - return true; - } - return collectUnaryCallResult(builtin.retType, def); + return def ? collectUnaryCallResult(builtin.retType, def) : true; } #ifdef ENABLE_WASM_FUNCTION_REFERENCES @@ -2759,22 +2716,13 @@ class FunctionCompiler { continue; } Control& control = iter().controlItem(depth); - if (!control.tryControl) { - continue; - } - for (MControlInstruction* patch : control.tryControl->landingPadPatches) { + for (MControlInstruction* patch : control.tryPadPatches) { MBasicBlock* block = patch->block(); if (block->loopDepth() >= loopEntry->loopDepth()) { fixupRedundantPhis(block); } } } - for (MControlInstruction* patch : bodyDelegatePadPatches_) { - MBasicBlock* block = patch->block(); - if (block->loopDepth() >= loopEntry->loopDepth()) { - fixupRedundantPhis(block); - } - } // Discard redundant phis and add to the free list. for (MPhiIterator phi = loopEntry->phisBegin(); @@ -2989,16 +2937,8 @@ class FunctionCompiler { /********************************************************** Exceptions ***/ - bool inTryBlockFrom(uint32_t fromRelativeDepth, uint32_t* relativeDepth) { - return iter().controlFindInnermostFrom( - [](LabelKind kind, const Control& control) { - return control.tryControl != nullptr && control.tryControl->inBody; - }, - fromRelativeDepth, relativeDepth); - } - bool inTryBlock(uint32_t* relativeDepth) { - return inTryBlockFrom(0, relativeDepth); + return iter().controlFindInnermost(LabelKind::Try, relativeDepth); } bool inTryCode() { @@ -3054,8 +2994,9 @@ class FunctionCompiler { [[nodiscard]] bool addPadPatch(MControlInstruction* ins, size_t relativeTryDepth) { - Control& control = iter().controlItem(relativeTryDepth); - return control.tryControl->landingPadPatches.emplaceBack(ins); + Control& tryControl = iter().controlItem(relativeTryDepth); + ControlInstructionVector& padPatches = tryControl.tryPadPatches; + return padPatches.emplaceBack(ins); } [[nodiscard]] bool endWithPadPatch(uint32_t relativeTryDepth) { @@ -3071,20 +3012,15 @@ class FunctionCompiler { } // Find where we are delegating the pad patches to. - ControlInstructionVector* targetPatches; uint32_t targetRelativeDepth; - if (inTryBlockFrom(relativeDepth, &targetRelativeDepth)) { - targetPatches = &iter() - .controlItem(targetRelativeDepth) - .tryControl->landingPadPatches; - } else { + if (!iter().controlFindInnermostFrom(LabelKind::Try, relativeDepth, + &targetRelativeDepth)) { MOZ_ASSERT(relativeDepth <= blockDepth_ - 1); - targetPatches = &bodyDelegatePadPatches_; + targetRelativeDepth = blockDepth_ - 1; } - // Append the delegate's pad patches to the target's. for (MControlInstruction* ins : patches) { - if (!targetPatches->emplaceBack(ins)) { + if (!addPadPatch(ins, targetRelativeDepth)) { return false; } } @@ -3130,15 +3066,15 @@ class FunctionCompiler { } // Create a landing pad for a try block if there are any throwing - // instructions. This is also used for the implicit rethrow landing pad used - // for delegate instructions that target the outermost label. - [[nodiscard]] bool createTryLandingPadIfNeeded( - ControlInstructionVector& landingPadPatches, MBasicBlock** landingPad) { + // instructions. + [[nodiscard]] bool createTryLandingPadIfNeeded(Control& control, + MBasicBlock** landingPad) { // If there are no pad-patches for this try control, it means there are no // instructions in the try code that could throw an exception. In this // case, all the catches are dead code, and the try code ends up equivalent // to a plain wasm block. - if (landingPadPatches.empty()) { + ControlInstructionVector& patches = control.tryPadPatches; + if (patches.empty()) { *landingPad = nullptr; return true; } @@ -3146,14 +3082,14 @@ class FunctionCompiler { // Otherwise, if there are (pad-) branches from places in the try code that // may throw an exception, bind these branches to a new landing pad // block. This is done similarly to what is done in bindBranches. - MControlInstruction* ins = landingPadPatches[0]; + MControlInstruction* ins = patches[0]; MBasicBlock* pred = ins->block(); if (!newBlock(pred, landingPad)) { return false; } ins->replaceSuccessor(0, *landingPad); - for (size_t i = 1; i < landingPadPatches.length(); i++) { - ins = landingPadPatches[i]; + for (size_t i = 1; i < patches.length(); i++) { + ins = patches[i]; pred = ins->block(); if (!(*landingPad)->addPredecessor(alloc(), pred)) { return false; @@ -3162,129 +3098,20 @@ class FunctionCompiler { } // Set up the slots in the landing pad block. - if (!setupLandingPadSlots(landingPad)) { + if (!setupLandingPadSlots(*landingPad)) { return false; } // Clear the now bound pad patches. - landingPadPatches.clear(); - return true; - } - - [[nodiscard]] bool createTryTableLandingPad(TryControl* tryControl) { - MBasicBlock* landingPad; - if (!createTryLandingPadIfNeeded(tryControl->landingPadPatches, - &landingPad)) { - return false; - } - - // If there is no landing pad created, no exceptions were possibly thrown - // and we don't need to do anything here. - if (!landingPad) { - return true; - } - - MBasicBlock* originalBlock = curBlock_; - curBlock_ = landingPad; - - bool hadCatchAll = false; - for (const TryTableCatch& tryTableCatch : tryControl->catches) { - MOZ_ASSERT(numPushed(curBlock_) == 2); - - // Handle a catch_all by jumping to the target block - if (tryTableCatch.tagIndex == CatchAllIndex) { - // Get the exception from the slots we pushed when adding - // control flow patches. - curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - - // Capture the exnref value if we need to - DefVector values; - if (tryTableCatch.captureExnRef && !values.append(exception)) { - return false; - } - - // Branch to the catch_all code - if (!br(tryTableCatch.labelRelativeDepth, values)) { - return false; - } - - // Break from the loop and skip the implicit rethrow that's needed - // if we didn't have a catch_all - hadCatchAll = true; - break; - } - - // Handle a tagged catch by doing a compare and branch on the tag index, - // jumping to a catch block if they match, or else to a fallthrough block - // to continue the landing pad. - MBasicBlock* catchBlock = nullptr; - MBasicBlock* fallthroughBlock = nullptr; - if (!newBlock(curBlock_, &catchBlock) || - !newBlock(curBlock_, &fallthroughBlock)) { - return false; - } - - // Get the exception and its tag from the slots we pushed when adding - // control flow patches. - MDefinition* exceptionTag = curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - - // Branch to the catch block if the exception's tag matches this catch - // block's tag. - MDefinition* catchTag = loadTag(tryTableCatch.tagIndex); - MDefinition* matchesCatchTag = compare(exceptionTag, catchTag, JSOp::Eq, - MCompare::Compare_WasmAnyRef); - curBlock_->end( - MTest::New(alloc(), matchesCatchTag, catchBlock, fallthroughBlock)); - - // Set up the catch block by extracting the values from the exception - // object. - curBlock_ = catchBlock; - - // Remove the tag and exception slots from the block, they are no - // longer necessary. - curBlock_->pop(); - exception = curBlock_->pop(); - MOZ_ASSERT(numPushed(curBlock_) == 0); - - // Extract the exception values for the catch block - DefVector values; - if (!loadExceptionValues(exception, tryTableCatch.tagIndex, &values)) { - return false; - } - if (tryTableCatch.captureExnRef && !values.append(exception)) { - return false; - } - - if (!br(tryTableCatch.labelRelativeDepth, values)) { - return false; - } - - curBlock_ = fallthroughBlock; - } - - // If there was no catch_all, we must rethrow this exception. - if (!hadCatchAll) { - MOZ_ASSERT(numPushed(curBlock_) == 2); - MDefinition* tag = curBlock_->pop(); - MDefinition* exception = curBlock_->pop(); - MOZ_ASSERT(numPushed(curBlock_) == 0); - - if (!throwFrom(exception, tag)) { - return false; - } - } - - curBlock_ = originalBlock; + patches.clear(); return true; } // Consume the pending exception state from instance, and set up the slots // of the landing pad with the exception state. - [[nodiscard]] bool setupLandingPadSlots(MBasicBlock** landingPad) { + [[nodiscard]] bool setupLandingPadSlots(MBasicBlock* landingPad) { MBasicBlock* prevBlock = curBlock_; - curBlock_ = *landingPad; + curBlock_ = landingPad; // Load the pending exception and tag MInstruction* exception; @@ -3299,37 +3126,18 @@ class FunctionCompiler { // Push the exception and its tag on the stack to make them available // to the landing pad blocks. - if (!curBlock_->ensureHasSlots(2)) { + if (!landingPad->ensureHasSlots(2)) { return false; } - curBlock_->push(exception); - curBlock_->push(tag); - *landingPad = curBlock_; + landingPad->push(exception); + landingPad->push(tag); curBlock_ = prevBlock; return true; } - [[nodiscard]] bool startTry() { - Control& control = iter().controlItem(); - control.block = curBlock_; - control.tryControl = newTryControl(); - if (!control.tryControl) { - return false; - } - control.tryControl->inBody = true; - return startBlock(); - } - - [[nodiscard]] bool startTryTable(TryTableCatchVector&& catches) { - Control& control = iter().controlItem(); - control.block = curBlock_; - control.tryControl = newTryControl(); - if (!control.tryControl) { - return false; - } - control.tryControl->inBody = true; - control.tryControl->catches = std::move(catches); + [[nodiscard]] bool startTry(MBasicBlock** curBlock) { + *curBlock = curBlock_; return startBlock(); } @@ -3355,11 +3163,8 @@ class FunctionCompiler { // Finish the previous block (either a try or catch block) and then setup a // new catch block. - [[nodiscard]] bool switchToCatch(Control& control, LabelKind fromKind, + [[nodiscard]] bool switchToCatch(Control& control, const LabelKind& fromKind, uint32_t tagIndex) { - // Mark this control node as being no longer in the body of the try - control.tryControl->inBody = false; - // If there is no control block, then either: // - the entry of the try block is dead code, or // - there is no landing pad for the try-catch. @@ -3379,8 +3184,7 @@ class FunctionCompiler { // guaranteed to happen once and only once before processing catch blocks. if (fromKind == LabelKind::Try) { MBasicBlock* padBlock = nullptr; - if (!createTryLandingPadIfNeeded(control.tryControl->landingPadPatches, - &padBlock)) { + if (!createTryLandingPadIfNeeded(control, &padBlock)) { return false; } // Set the control block for this try-catch to the landing pad. @@ -3449,7 +3253,7 @@ class FunctionCompiler { // Remove the tag and exception slots from the block, they are no // longer necessary. curBlock_->pop(); - exception = curBlock_->pop(); + curBlock_->pop(); // Extract the exception values for the catch block DefVector values; @@ -3506,14 +3310,12 @@ class FunctionCompiler { // specify a relativeDepth of '1' to delegate outside of the still // active try block. uint32_t relativeDepth = 1; - if (!delegatePadPatches(control.tryControl->landingPadPatches, - relativeDepth)) { + if (!delegatePadPatches(control.tryPadPatches, relativeDepth)) { return false; } break; } case LabelKind::Catch: { - MOZ_ASSERT(!control.tryControl->inBody); // This is a try without a catch_all, we must have a rethrow at the end // of the landing pad (if any). MBasicBlock* padBlock = control.block; @@ -3529,11 +3331,9 @@ class FunctionCompiler { } break; } - case LabelKind::CatchAll: { - MOZ_ASSERT(!control.tryControl->inBody); + case LabelKind::CatchAll: // This is a try with a catch_all, and requires no special handling. break; - } default: MOZ_CRASH(); } @@ -3542,21 +3342,10 @@ class FunctionCompiler { return finishBlock(defs); } - [[nodiscard]] bool finishTryTable(Control& control, DefVector* defs) { - // Mark this control as no longer in the body of the try - control.tryControl->inBody = false; - // Create a landing pad for all of the catches - if (!createTryTableLandingPad(control.tryControl.get())) { - return false; - } - // Finish the block, joining the try and catch blocks - return finishBlock(defs); - } - [[nodiscard]] bool emitBodyDelegateThrowPad(Control& control) { // Create a landing pad for any throwing instructions MBasicBlock* padBlock; - if (!createTryLandingPadIfNeeded(bodyDelegatePadPatches_, &padBlock)) { + if (!createTryLandingPadIfNeeded(control, &padBlock)) { return false; } @@ -3649,27 +3438,6 @@ class FunctionCompiler { return throwFrom(exception, tag); } - [[nodiscard]] bool emitThrowRef(MDefinition* exnRef) { - if (inDeadCode()) { - return true; - } - - // The exception must be non-null - if (!refAsNonNull(exnRef)) { - return false; - } - - // If there is no surrounding catching block, call an instance method to - // throw the exception. - if (!emitInstanceCall1(readBytecodeOffset(), SASigThrowException, exnRef)) { - return false; - } - unreachableTrap(); - - curBlock_ = nullptr; - return true; - } - [[nodiscard]] bool throwFrom(MDefinition* exn, MDefinition* tag) { if (inDeadCode()) { return true; @@ -4980,7 +4748,7 @@ static bool EmitLoop(FunctionCompiler& f) { f.addInterruptCheck(); - f.iter().controlItem().block = loopHeader; + f.iter().controlItem().setBlock(loopHeader); return true; } @@ -4996,7 +4764,7 @@ static bool EmitIf(FunctionCompiler& f) { return false; } - f.iter().controlItem().block = elseBlock; + f.iter().controlItem().setBlock(elseBlock); return true; } @@ -5037,7 +4805,6 @@ static bool EmitEnd(FunctionCompiler& f) { DefVector postJoinDefs; switch (kind) { case LabelKind::Body: - MOZ_ASSERT(!control.tryControl); if (!f.emitBodyDelegateThrowPad(control)) { return false; } @@ -5051,21 +4818,18 @@ static bool EmitEnd(FunctionCompiler& f) { MOZ_ASSERT(f.iter().controlStackEmpty()); return f.iter().endFunction(f.iter().end()); case LabelKind::Block: - MOZ_ASSERT(!control.tryControl); if (!f.finishBlock(&postJoinDefs)) { return false; } f.iter().popEnd(); break; case LabelKind::Loop: - MOZ_ASSERT(!control.tryControl); if (!f.closeLoop(block, &postJoinDefs)) { return false; } f.iter().popEnd(); break; case LabelKind::Then: { - MOZ_ASSERT(!control.tryControl); // If we didn't see an Else, create a trivial else block so that we create // a diamond anyway, to preserve Ion invariants. if (!f.switchToElse(block, &block)) { @@ -5083,7 +4847,6 @@ static bool EmitEnd(FunctionCompiler& f) { break; } case LabelKind::Else: - MOZ_ASSERT(!control.tryControl); if (!f.joinIfElse(block, &postJoinDefs)) { return false; } @@ -5092,19 +4855,9 @@ static bool EmitEnd(FunctionCompiler& f) { case LabelKind::Try: case LabelKind::Catch: case LabelKind::CatchAll: - MOZ_ASSERT(control.tryControl); if (!f.finishTryCatch(kind, control, &postJoinDefs)) { return false; } - f.freeTryControl(std::move(control.tryControl)); - f.iter().popEnd(); - break; - case LabelKind::TryTable: - MOZ_ASSERT(control.tryControl); - if (!f.finishTryTable(control, &postJoinDefs)) { - return false; - } - f.freeTryControl(std::move(control.tryControl)); f.iter().popEnd(); break; } @@ -5191,7 +4944,13 @@ static bool EmitTry(FunctionCompiler& f) { return false; } - return f.startTry(); + MBasicBlock* curBlock = nullptr; + if (!f.startTry(&curBlock)) { + return false; + } + + f.iter().controlItem().setBlock(curBlock); + return true; } static bool EmitCatch(FunctionCompiler& f) { @@ -5233,16 +4992,6 @@ static bool EmitCatchAll(FunctionCompiler& f) { return f.switchToCatch(f.iter().controlItem(), kind, CatchAllIndex); } -static bool EmitTryTable(FunctionCompiler& f) { - ResultType params; - TryTableCatchVector catches; - if (!f.iter().readTryTable(¶ms, &catches)) { - return false; - } - - return f.startTryTable(std::move(catches)); -} - static bool EmitDelegate(FunctionCompiler& f) { uint32_t relativeDepth; ResultType resultType; @@ -5253,18 +5002,15 @@ static bool EmitDelegate(FunctionCompiler& f) { Control& control = f.iter().controlItem(); MBasicBlock* block = control.block; - MOZ_ASSERT(control.tryControl); // Unless the entire try-delegate is dead code, delegate any pad-patches from // this try to the next try-block above relativeDepth. if (block) { - ControlInstructionVector& delegatePadPatches = - control.tryControl->landingPadPatches; + ControlInstructionVector& delegatePadPatches = control.tryPadPatches; if (!f.delegatePadPatches(delegatePadPatches, relativeDepth)) { return false; } } - f.freeTryControl(std::move(control.tryControl)); f.iter().popDelegate(); // Push the results of the previous block, and join control flow with @@ -5293,15 +5039,6 @@ static bool EmitThrow(FunctionCompiler& f) { return f.emitThrow(tagIndex, argValues); } -static bool EmitThrowRef(FunctionCompiler& f) { - MDefinition* exnRef; - if (!f.iter().readThrowRef(&exnRef)) { - return false; - } - - return f.emitThrowRef(exnRef); -} - static bool EmitRethrow(FunctionCompiler& f) { uint32_t relativeDepth; if (!f.iter().readRethrow(&relativeDepth)) { @@ -8071,16 +7808,6 @@ static bool EmitBodyExprs(FunctionCompiler& f) { return f.iter().unrecognizedOpcode(&op); } CHECK(EmitRethrow(f)); - case uint16_t(Op::ThrowRef): - if (!f.moduleEnv().exnrefEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitThrowRef(f)); - case uint16_t(Op::TryTable): - if (!f.moduleEnv().exnrefEnabled()) { - return f.iter().unrecognizedOpcode(&op); - } - CHECK(EmitTryTable(f)); case uint16_t(Op::Br): CHECK(EmitBr(f)); case uint16_t(Op::BrIf): diff --git a/js/src/wasm/WasmOpIter.cpp b/js/src/wasm/WasmOpIter.cpp index 102d39639cd3..e83a543efbcf 100644 --- a/js/src/wasm/WasmOpIter.cpp +++ b/js/src/wasm/WasmOpIter.cpp @@ -282,10 +282,6 @@ OpKind wasm::Classify(OpBytes op) { return OpKind::Rethrow; case Op::Try: return OpKind::Try; - case Op::ThrowRef: - return OpKind::ThrowRef; - case Op::TryTable: - return OpKind::TryTable; case Op::MemorySize: return OpKind::MemorySize; case Op::MemoryGrow: diff --git a/js/src/wasm/WasmOpIter.h b/js/src/wasm/WasmOpIter.h index e18bd928e112..7d1eedaadd21 100644 --- a/js/src/wasm/WasmOpIter.h +++ b/js/src/wasm/WasmOpIter.h @@ -42,7 +42,6 @@ enum class LabelKind : uint8_t { Try, Catch, CatchAll, - TryTable, }; // The type of values on the operand stack during validation. This is either a @@ -229,10 +228,8 @@ enum class OpKind { CatchAll, Delegate, Throw, - ThrowRef, Rethrow, Try, - TryTable, CallBuiltinModuleFunc, }; @@ -630,8 +627,6 @@ class MOZ_STACK_CLASS OpIter : private Policy { ResultType* defaultBranchType, ValueVector* branchValues, Value* index); [[nodiscard]] bool readTry(ResultType* type); - [[nodiscard]] bool readTryTable(ResultType* type, - TryTableCatchVector* catches); [[nodiscard]] bool readCatch(LabelKind* kind, uint32_t* tagIndex, ResultType* paramType, ResultType* resultType, ValueVector* tryResults); @@ -643,7 +638,6 @@ class MOZ_STACK_CLASS OpIter : private Policy { ValueVector* tryResults); void popDelegate(); [[nodiscard]] bool readThrow(uint32_t* tagIndex, ValueVector* argValues); - [[nodiscard]] bool readThrowRef(Value* exnRef); [[nodiscard]] bool readRethrow(uint32_t* relativeDepth); [[nodiscard]] bool readUnreachable(); [[nodiscard]] bool readDrop(); @@ -881,22 +875,24 @@ class MOZ_STACK_CLASS OpIter : private Policy { // Return the depth of the control stack. size_t controlStackDepth() const { return controlStack_.length(); } - // Find the innermost control item matching a predicate, starting to search - // from a certain relative depth, and returning true if such innermost - // control item is found. The relative depth of the found item is returned - // via a parameter. - template - bool controlFindInnermostFrom(Predicate predicate, uint32_t fromRelativeDepth, + // Find the innermost control item of a specific kind, starting to search from + // a certain relative depth, and returning true if such innermost control item + // is found. The relative depth of the found item is returned via a parameter. + bool controlFindInnermostFrom(LabelKind kind, uint32_t fromRelativeDepth, uint32_t* foundRelativeDepth) { int32_t fromAbsoluteDepth = controlStack_.length() - fromRelativeDepth - 1; for (int32_t i = fromAbsoluteDepth; i >= 0; i--) { - if (predicate(controlStack_[i].kind(), controlStack_[i].controlItem())) { + if (controlStack_[i].kind() == kind) { *foundRelativeDepth = controlStack_.length() - 1 - i; return true; } } return false; } + + bool controlFindInnermost(LabelKind kind, uint32_t* foundRelativeDepth) { + return controlFindInnermostFrom(kind, 0, foundRelativeDepth); + } }; template @@ -1608,107 +1604,6 @@ inline bool OpIter::readTry(ResultType* paramType) { return pushControl(LabelKind::Try, type); } -enum class TryTableCatchFlags : uint8_t { - CaptureExnRef = 0x1, - CatchAll = 0x1 << 1, - AllowedMask = uint8_t(CaptureExnRef) | uint8_t(CatchAll), -}; - -template -inline bool OpIter::readTryTable(ResultType* paramType, - TryTableCatchVector* catches) { - MOZ_ASSERT(Classify(op_) == OpKind::TryTable); - - BlockType type; - if (!readBlockType(&type)) { - return false; - } - - *paramType = type.params(); - if (!pushControl(LabelKind::TryTable, type)) { - return false; - } - - uint32_t catchesLength; - if (!readVarU32(&catchesLength)) { - return fail("failed to read catches length"); - } - - if (catchesLength > MaxTryTableCatches) { - return fail("too many catches"); - } - - if (!catches->reserve(catchesLength)) { - return false; - } - - for (uint32_t i = 0; i < catchesLength; i++) { - TryTableCatch tryTableCatch; - - // Decode the flags - uint8_t flags; - if (!readFixedU8(&flags)) { - return fail("expected flags"); - } - if ((flags & ~uint8_t(TryTableCatchFlags::AllowedMask)) != 0) { - return fail("invalid try_table catch flags"); - } - - // Decode if this catch wants to capture an exnref - tryTableCatch.captureExnRef = - (flags & uint8_t(TryTableCatchFlags::CaptureExnRef)) != 0; - - // Decode the tag, if any - if ((flags & uint8_t(TryTableCatchFlags::CatchAll)) != 0) { - tryTableCatch.tagIndex = CatchAllIndex; - } else { - if (!readVarU32(&tryTableCatch.tagIndex)) { - return fail("expected tag index"); - } - if (tryTableCatch.tagIndex >= env_.tags.length()) { - return fail("tag index out of range"); - } - } - - // Decode the target branch and construct the type we need to compare - // against the branch - if (!readVarU32(&tryTableCatch.labelRelativeDepth)) { - return fail("unable to read catch depth"); - } - - // Tagged catches will unpack the exception package and pass it to the - // branch - if (tryTableCatch.tagIndex != CatchAllIndex) { - const TagType& tagType = *env_.tags[tryTableCatch.tagIndex].type; - ResultType tagResult = tagType.resultType(); - if (!tagResult.cloneToVector(&tryTableCatch.labelType)) { - return false; - } - } - - // Any captured exnref is the final parameter - if (tryTableCatch.captureExnRef && - !tryTableCatch.labelType.append(ValType(RefType::exn()))) { - return false; - } - - Control* block; - if (!getControl(tryTableCatch.labelRelativeDepth, &block)) { - return false; - } - - ResultType blockTargetType = block->branchTargetType(); - if (!checkIsSubtypeOf(ResultType::Vector(tryTableCatch.labelType), - blockTargetType)) { - return false; - } - - catches->infallibleAppend(std::move(tryTableCatch)); - } - - return true; -} - template inline bool OpIter::readCatch(LabelKind* kind, uint32_t* tagIndex, ResultType* paramType, @@ -1766,6 +1661,7 @@ inline bool OpIter::readCatchAll(LabelKind* kind, ResultType* paramType, block.switchToCatchAll(); // Reset local state to the beginning of the 'try' block. unsetLocals_.resetToBlock(controlStack_.length() - 1); + return true; } @@ -1827,18 +1723,6 @@ inline bool OpIter::readThrow(uint32_t* tagIndex, } template -inline bool OpIter::readThrowRef(Value* exnRef) { - MOZ_ASSERT(Classify(op_) == OpKind::ThrowRef); - - if (!popWithType(ValType(RefType::exn()), exnRef)) { - return false; - } - - afterUnconditionalBranch(); - return true; -} - -template inline bool OpIter::readRethrow(uint32_t* relativeDepth) { MOZ_ASSERT(Classify(op_) == OpKind::Rethrow); diff --git a/js/src/wasm/WasmTypeDef.h b/js/src/wasm/WasmTypeDef.h index abada72783a5..f380a4b48d6b 100644 --- a/js/src/wasm/WasmTypeDef.h +++ b/js/src/wasm/WasmTypeDef.h @@ -1347,8 +1347,6 @@ inline RefTypeHierarchy RefType::hierarchy() const { case RefType::Extern: case RefType::NoExtern: return RefTypeHierarchy::Extern; - case RefType::Exn: - return RefTypeHierarchy::Exn; case RefType::Any: case RefType::None: case RefType::I31: @@ -1374,7 +1372,6 @@ inline TableRepr RefType::tableRepr() const { switch (hierarchy()) { case RefTypeHierarchy::Any: case RefTypeHierarchy::Extern: - case RefTypeHierarchy::Exn: return TableRepr::Ref; case RefTypeHierarchy::Func: return TableRepr::Func; diff --git a/js/src/wasm/WasmValType.cpp b/js/src/wasm/WasmValType.cpp index 06a7c5c2100d..3ac14044dc7f 100644 --- a/js/src/wasm/WasmValType.cpp +++ b/js/src/wasm/WasmValType.cpp @@ -51,8 +51,6 @@ RefType RefType::topType() const { case RefType::Extern: case RefType::NoExtern: return RefType::extern_(); - case RefType::Exn: - return RefType::exn(); case RefType::TypeRef: switch (typeDef()->kind()) { case TypeDefKind::Array: @@ -298,9 +296,6 @@ UniqueChars wasm::ToString(RefType type, const TypeContext* types) { case RefType::Extern: literal = "externref"; break; - case RefType::Exn: - literal = "exnref"; - break; case RefType::Any: literal = "anyref"; break; @@ -341,9 +336,6 @@ UniqueChars wasm::ToString(RefType type, const TypeContext* types) { case RefType::Extern: heapType = "extern"; break; - case RefType::Exn: - heapType = "exn"; - break; case RefType::Any: heapType = "any"; break; diff --git a/js/src/wasm/WasmValType.h b/js/src/wasm/WasmValType.h index ea928b4b2248..d1c6abdd3386 100644 --- a/js/src/wasm/WasmValType.h +++ b/js/src/wasm/WasmValType.h @@ -302,7 +302,7 @@ enum class TableRepr { Ref, Func }; // An enum that describes the different type hierarchies. -enum class RefTypeHierarchy { Func, Extern, Exn, Any }; +enum class RefTypeHierarchy { Func, Extern, Any }; // The RefType carries more information about types t for which t.isRefType() // is true. @@ -312,7 +312,6 @@ class RefType { enum Kind { Func = uint8_t(TypeCode::FuncRef), Extern = uint8_t(TypeCode::ExternRef), - Exn = uint8_t(TypeCode::ExnRef), Any = uint8_t(TypeCode::AnyRef), NoFunc = uint8_t(TypeCode::NullFuncRef), NoExtern = uint8_t(TypeCode::NullExternRef), @@ -365,7 +364,6 @@ class RefType { switch (ptc_.typeCode()) { case TypeCode::FuncRef: case TypeCode::ExternRef: - case TypeCode::ExnRef: case TypeCode::AnyRef: case TypeCode::EqRef: case TypeCode::I31Ref: @@ -384,7 +382,6 @@ class RefType { static RefType func() { return RefType(Func, true); } static RefType extern_() { return RefType(Extern, true); } - static RefType exn() { return RefType(Exn, true); } static RefType any() { return RefType(Any, true); } static RefType nofunc() { return RefType(NoFunc, true); } static RefType noextern() { return RefType(NoExtern, true); } @@ -467,7 +464,6 @@ class FieldTypeTraits { #endif case TypeCode::FuncRef: case TypeCode::ExternRef: - case TypeCode::ExnRef: #ifdef ENABLE_WASM_GC case TypeCode::AnyRef: case TypeCode::EqRef: @@ -545,7 +541,6 @@ class ValTypeTraits { #endif case TypeCode::FuncRef: case TypeCode::ExternRef: - case TypeCode::ExnRef: #ifdef ENABLE_WASM_GC case TypeCode::AnyRef: case TypeCode::EqRef: @@ -716,8 +711,6 @@ class PackedType : public T { bool isExternRef() const { return tc_.typeCode() == TypeCode::ExternRef; } - bool isExnRef() const { return tc_.typeCode() == TypeCode::ExnRef; } - bool isAnyRef() const { return tc_.typeCode() == TypeCode::AnyRef; } bool isNoFunc() const { return tc_.typeCode() == TypeCode::NullFuncRef; } @@ -744,9 +737,9 @@ class PackedType : public T { // Returns whether the type has a representation in JS. bool isExposable() const { #if defined(ENABLE_WASM_SIMD) - return kind() != Kind::V128 && !isExnRef(); + return kind() != Kind::V128; #else - return !isExnRef(); + return true; #endif } diff --git a/js/src/wasm/WasmValidate.cpp b/js/src/wasm/WasmValidate.cpp index ed3766492a23..5a50b091a412 100644 --- a/js/src/wasm/WasmValidate.cpp +++ b/js/src/wasm/WasmValidate.cpp @@ -1331,19 +1331,6 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, uint32_t unusedDepth; CHECK(iter.readRethrow(&unusedDepth)); } - case uint16_t(Op::ThrowRef): { - if (!env.exnrefEnabled()) { - return iter.unrecognizedOpcode(&op); - } - CHECK(iter.readThrowRef(¬hing)); - } - case uint16_t(Op::TryTable): { - if (!env.exnrefEnabled()) { - return iter.unrecognizedOpcode(&op); - } - TryTableCatchVector catches; - CHECK(iter.readTryTable(&unusedType, &catches)); - } case uint16_t(Op::ThreadPrefix): { // Though thread ops can be used on nonshared memories, we make them // unavailable if shared memory has been disabled in the prefs, for diff --git a/js/src/wasm/WasmValue.cpp b/js/src/wasm/WasmValue.cpp index 0d10733c9def..d1e2a49ade77 100644 --- a/js/src/wasm/WasmValue.cpp +++ b/js/src/wasm/WasmValue.cpp @@ -128,9 +128,6 @@ bool wasm::CheckRefType(JSContext* cx, RefType targetType, HandleValue v, return CheckFuncRefValue(cx, v, fnval); case RefType::Extern: return AnyRef::fromJSValue(cx, v, refval); - case RefType::Exn: - // Break to the non-exposable case - break; case RefType::Any: return CheckAnyRefValue(cx, v, refval); case RefType::NoFunc: @@ -683,9 +680,6 @@ bool wasm::ToWebAssemblyValue(JSContext* cx, HandleValue val, FieldType type, case RefType::Extern: return ToWebAssemblyValue_externref(cx, val, (void**)loc, mustWrite64); - case RefType::Exn: - // Break to the non-exposable case - break; case RefType::Any: return ToWebAssemblyValue_anyref(cx, val, (void**)loc, mustWrite64); @@ -846,9 +840,6 @@ bool wasm::ToJSValue(JSContext* cx, const void* src, FieldType type, case RefTypeHierarchy::Func: return ToJSValue_funcref( cx, *reinterpret_cast(src), dst); - case RefTypeHierarchy::Exn: - // Break to the non-exposable case - break; case RefTypeHierarchy::Extern: return ToJSValue_externref( cx, *reinterpret_cast(src), dst); -- 2.11.4.GIT