From 9568ca75145a19b2e801042a787cd23771029e65 Mon Sep 17 00:00:00 2001 From: Matthias Liedtke Date: Mon, 18 Mar 2024 10:36:29 +0100 Subject: [PATCH 01/17] deps: V8: cherry-pick 5f1342c20b59 Original commit message: [wasm][exnref] Fix broken abstract casts ref.test, ref.cast, br_on_cast, br_on_cast_fail allow arbitrary heap types, so they also allow exnref and noexnref. This CL also fixes the missing type checks in the js to wasm wrapper. Bug: v8:14398 Change-Id: Ieefb9a8e99d3d7a4b175db60f55b7fa9a96c5203 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5372489 Reviewed-by: Thibaud Michaud Commit-Queue: Matthias Liedtke Cr-Commit-Position: refs/heads/main@{#92867} Refs: https://github.com/v8/v8/commit/5f1342c20b5932c170c4c113dd4e78f6e25fdad3 --- common.gypi | 2 +- .../turboshaft/wasm-lowering-reducer.h | 6 +- deps/v8/src/compiler/wasm-compiler.cc | 5 +- deps/v8/src/compiler/wasm-gc-lowering.cc | 4 +- deps/v8/src/wasm/baseline/liftoff-compiler.cc | 3 + deps/v8/src/wasm/function-body-decoder-impl.h | 3 +- deps/v8/src/wasm/graph-builder-interface.cc | 2 + deps/v8/src/wasm/wrappers.cc | 5 +- deps/v8/test/mjsunit/wasm/gc-casts-exnref.js | 232 ++++++++++++++++++ deps/v8/test/mjsunit/wasm/gc-casts-invalid.js | 7 + .../mjsunit/wasm/js-wrapper-typechecks.js | 4 +- .../test/mjsunit/wasm/wasm-module-builder.js | 2 + 12 files changed, 262 insertions(+), 13 deletions(-) create mode 100644 deps/v8/test/mjsunit/wasm/gc-casts-exnref.js diff --git a/common.gypi b/common.gypi index b7d84c3ead830f..51609a897aceb9 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.39', + 'v8_embedder_string': '-node.40', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/compiler/turboshaft/wasm-lowering-reducer.h b/deps/v8/src/compiler/turboshaft/wasm-lowering-reducer.h index 82c3356fcd93d2..dc255c01fc6160 100644 --- a/deps/v8/src/compiler/turboshaft/wasm-lowering-reducer.h +++ b/deps/v8/src/compiler/turboshaft/wasm-lowering-reducer.h @@ -556,7 +556,8 @@ class WasmLoweringReducer : public Next { // The none-types only perform a null check. They need no control flow. if (to_rep == wasm::HeapType::kNone || to_rep == wasm::HeapType::kNoExtern || - to_rep == wasm::HeapType::kNoFunc) { + to_rep == wasm::HeapType::kNoFunc || + to_rep == wasm::HeapType::kNoExn) { result = __ IsNull(object, config.from); break; } @@ -628,7 +629,8 @@ class WasmLoweringReducer : public Next { // The none-types only perform a null check. if (to_rep == wasm::HeapType::kNone || to_rep == wasm::HeapType::kNoExtern || - to_rep == wasm::HeapType::kNoFunc) { + to_rep == wasm::HeapType::kNoFunc || + to_rep == wasm::HeapType::kNoExn) { __ TrapIfNot(__ IsNull(object, config.from), OpIndex::Invalid(), TrapId::kTrapIllegalCast); break; diff --git a/deps/v8/src/compiler/wasm-compiler.cc b/deps/v8/src/compiler/wasm-compiler.cc index 16f1f1470b782c..14bc728ba5a7e8 100644 --- a/deps/v8/src/compiler/wasm-compiler.cc +++ b/deps/v8/src/compiler/wasm-compiler.cc @@ -7325,6 +7325,8 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { // TODO(14034): Add more fast paths? case wasm::HeapType::kExtern: case wasm::HeapType::kNoExtern: + case wasm::HeapType::kExn: + case wasm::HeapType::kNoExn: if (type.kind() == wasm::kRef) { Node* null_value = gasm_->LoadImmutable( MachineType::Pointer(), gasm_->LoadRootRegister(), @@ -7345,9 +7347,6 @@ class WasmWrapperGraphBuilder : public WasmGraphBuilder { return input; case wasm::HeapType::kString: return BuildCheckString(input, js_context, type); - case wasm::HeapType::kExn: - case wasm::HeapType::kNoExn: - return input; case wasm::HeapType::kNone: case wasm::HeapType::kNoFunc: case wasm::HeapType::kI31: diff --git a/deps/v8/src/compiler/wasm-gc-lowering.cc b/deps/v8/src/compiler/wasm-gc-lowering.cc index 1bcb07abd638da..647059daf21e78 100644 --- a/deps/v8/src/compiler/wasm-gc-lowering.cc +++ b/deps/v8/src/compiler/wasm-gc-lowering.cc @@ -224,7 +224,7 @@ Reduction WasmGCLowering::ReduceWasmTypeCheckAbstract(Node* node) { // The none-types only perform a null check. They need no control flow. if (to_rep == wasm::HeapType::kNone || to_rep == wasm::HeapType::kNoExtern || - to_rep == wasm::HeapType::kNoFunc) { + to_rep == wasm::HeapType::kNoFunc || to_rep == wasm::HeapType::kNoExn) { result = IsNull(object, config.from); break; } @@ -398,7 +398,7 @@ Reduction WasmGCLowering::ReduceWasmTypeCastAbstract(Node* node) { // The none-types only perform a null check. if (to_rep == wasm::HeapType::kNone || to_rep == wasm::HeapType::kNoExtern || - to_rep == wasm::HeapType::kNoFunc) { + to_rep == wasm::HeapType::kNoFunc || to_rep == wasm::HeapType::kNoExn) { gasm_.TrapUnless(IsNull(object, config.from), TrapId::kTrapIllegalCast); UpdateSourcePosition(gasm_.effect(), node); break; diff --git a/deps/v8/src/wasm/baseline/liftoff-compiler.cc b/deps/v8/src/wasm/baseline/liftoff-compiler.cc index c185d7273629fd..78e7247456754d 100644 --- a/deps/v8/src/wasm/baseline/liftoff-compiler.cc +++ b/deps/v8/src/wasm/baseline/liftoff-compiler.cc @@ -6580,6 +6580,7 @@ class LiftoffCompiler { case HeapType::kNone: case HeapType::kNoExtern: case HeapType::kNoFunc: + case HeapType::kNoExn: DCHECK(null_succeeds); return AssertNullTypecheck(decoder, obj, result_val); case HeapType::kAny: @@ -6674,6 +6675,7 @@ class LiftoffCompiler { case HeapType::kNone: case HeapType::kNoExtern: case HeapType::kNoFunc: + case HeapType::kNoExn: DCHECK(null_succeeds); return BrOnNull(decoder, obj, depth, /*pass_null_along_branch*/ true, nullptr); @@ -6707,6 +6709,7 @@ class LiftoffCompiler { case HeapType::kNone: case HeapType::kNoExtern: case HeapType::kNoFunc: + case HeapType::kNoExn: DCHECK(null_succeeds); return BrOnNonNull(decoder, obj, nullptr, depth, /*drop_null_on_fallthrough*/ false); diff --git a/deps/v8/src/wasm/function-body-decoder-impl.h b/deps/v8/src/wasm/function-body-decoder-impl.h index 4fccfd08c220dc..b0aa65983ee6cb 100644 --- a/deps/v8/src/wasm/function-body-decoder-impl.h +++ b/deps/v8/src/wasm/function-body-decoder-impl.h @@ -4659,7 +4659,8 @@ class WasmFullDecoder : public WasmDecoder { ((!null_succeeds || !obj.type.is_nullable()) && (expected_type.representation() == HeapType::kNone || expected_type.representation() == HeapType::kNoFunc || - expected_type.representation() == HeapType::kNoExtern)); + expected_type.representation() == HeapType::kNoExtern || + expected_type.representation() == HeapType::kNoExn)); } bool TypeCheckAlwaysFails(Value obj, uint32_t ref_index) { // All old casts / checks treat null as failure. diff --git a/deps/v8/src/wasm/graph-builder-interface.cc b/deps/v8/src/wasm/graph-builder-interface.cc index f55d1fbd28e43a..0ee5c9ceb71909 100644 --- a/deps/v8/src/wasm/graph-builder-interface.cc +++ b/deps/v8/src/wasm/graph-builder-interface.cc @@ -1803,6 +1803,7 @@ class WasmGraphBuildingInterface { case HeapType::kNone: case HeapType::kNoExtern: case HeapType::kNoFunc: + case HeapType::kNoExn: DCHECK(null_succeeds); // This is needed for BrOnNull. {value_on_branch} is on the value stack // and BrOnNull interacts with the values on the stack. @@ -1841,6 +1842,7 @@ class WasmGraphBuildingInterface { case HeapType::kNone: case HeapType::kNoExtern: case HeapType::kNoFunc: + case HeapType::kNoExn: DCHECK(null_succeeds); // We need to store a node in the stack where the decoder so far only // pushed a value and expects the `BrOnCastFailAbstract` to set it. diff --git a/deps/v8/src/wasm/wrappers.cc b/deps/v8/src/wasm/wrappers.cc index 279779aa1df112..9746edd205cbb9 100644 --- a/deps/v8/src/wasm/wrappers.cc +++ b/deps/v8/src/wasm/wrappers.cc @@ -857,6 +857,8 @@ class WasmWrapperTSGraphBuilder : public WasmGraphBuilderBase { // TODO(14034): Add more fast paths? case wasm::HeapType::kExtern: case wasm::HeapType::kNoExtern: + case wasm::HeapType::kExn: + case wasm::HeapType::kNoExn: if (type.kind() == wasm::kRef) { IF (__ TaggedEqual(input, LOAD_ROOT(NullValue))) { CallRuntime(__ phase_zone(), Runtime::kWasmThrowJSTypeError, {}, @@ -867,9 +869,6 @@ class WasmWrapperTSGraphBuilder : public WasmGraphBuilderBase { return input; case wasm::HeapType::kString: return BuildCheckString(input, context, type); - case wasm::HeapType::kExn: - case wasm::HeapType::kNoExn: - return input; case wasm::HeapType::kNone: case wasm::HeapType::kNoFunc: case wasm::HeapType::kI31: diff --git a/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js b/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js new file mode 100644 index 00000000000000..f7b19ec40ceb49 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js @@ -0,0 +1,232 @@ +// Copyright 2024 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --experimental-wasm-exnref --no-experimental-wasm-inlining + +d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js'); + +let getExnRef = function() { + let tag = new WebAssembly.Tag({parameters:[]}); + return new WebAssembly.Exception(tag, []); +}; + +(function RefTestExnRef() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let tag = builder.addTag(makeSig([], [])); + + builder.addFunction('testExnRef', + makeSig([kWasmExnRef], [kWasmI32, kWasmI32])) + .addBody([ + kExprLocalGet, 0, kGCPrefix, kExprRefTest, kExnRefCode, + kExprLocalGet, 0, kGCPrefix, kExprRefTest, kNullExnRefCode, + ]).exportFunc(); + + builder.addFunction('testNullExnRef', + makeSig([kWasmExnRef], [kWasmI32, kWasmI32])) + .addBody([ + kExprLocalGet, 0, kGCPrefix, kExprRefTestNull, kExnRefCode, + kExprLocalGet, 0, kGCPrefix, kExprRefTestNull, kNullExnRefCode, + ]).exportFunc(); + + let instance = builder.instantiate(); + let wasm = instance.exports; + assertEquals([0, 0], wasm.testExnRef(null)); + assertEquals([1, 0], wasm.testExnRef(getExnRef())); + assertEquals([1, 1], wasm.testNullExnRef(null)); + assertEquals([1, 0], wasm.testNullExnRef(getExnRef())); +})(); + +(function RefCastExnRef() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + + builder.addFunction('castToExnRef', + makeSig([kWasmExnRef], [kWasmExnRef])) + .addBody([kExprLocalGet, 0, kGCPrefix, kExprRefCast, kExnRefCode]) + .exportFunc(); + builder.addFunction('castToNullExnRef', + makeSig([kWasmExnRef], [kWasmExnRef])) + .addBody([kExprLocalGet, 0, kGCPrefix, kExprRefCast, kNullExnRefCode]) + .exportFunc(); + builder.addFunction('castNullToExnRef', + makeSig([kWasmExnRef], [kWasmExnRef])) + .addBody([kExprLocalGet, 0, kGCPrefix, kExprRefCastNull, kExnRefCode]) + .exportFunc(); + builder.addFunction('castNullToNullExnRef', + makeSig([kWasmExnRef], [kWasmExnRef])) + .addBody([kExprLocalGet, 0, kGCPrefix, kExprRefCastNull, kNullExnRefCode]) + .exportFunc(); + + let instance = builder.instantiate(); + let wasm = instance.exports; + + let exnRef = getExnRef(); + assertTraps(kTrapIllegalCast, () => wasm.castToExnRef(null)); + assertEquals(exnRef, wasm.castToExnRef(exnRef)); + assertTraps(kTrapIllegalCast, () => wasm.castToNullExnRef(null)); + assertTraps(kTrapIllegalCast, () => wasm.castToNullExnRef(exnRef)); + + assertSame(null, wasm.castNullToExnRef(null)); + assertEquals(exnRef, wasm.castNullToExnRef(exnRef)); + assertSame(null, wasm.castNullToNullExnRef(null)); + assertTraps(kTrapIllegalCast, () => wasm.castNullToNullExnRef(exnRef)); +})(); + +(function BrOnCastExnRef() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + + builder.addFunction('castToExnRef', + makeSig([kWasmExnRef], [kWasmI32])) + .addBody([ + kExprBlock, kWasmRef, kExnRefCode, + kExprLocalGet, 0, + ...wasmBrOnCast( + 0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmExnRef)), + kExprI32Const, 0, + kExprReturn, + kExprEnd, + kExprDrop, + kExprI32Const, 1, + kExprReturn, + ]) + .exportFunc(); + builder.addFunction('castToNullExnRef', + makeSig([kWasmExnRef], [kWasmI32])) + .addBody([ + kExprBlock, kWasmRef, kNullExnRefCode, + kExprLocalGet, 0, + ...wasmBrOnCast( + 0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmNullExnRef)), + kExprI32Const, 0, + kExprReturn, + kExprEnd, + kExprDrop, + kExprI32Const, 1, + kExprReturn, + ]) + .exportFunc(); + + builder.addFunction('castNullToExnRef', + makeSig([kWasmExnRef], [kWasmI32])) + .addBody([ + kExprBlock, kWasmRefNull, kExnRefCode, + kExprLocalGet, 0, + ...wasmBrOnCast(0, + wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmExnRef)), + kExprI32Const, 0, + kExprReturn, + kExprEnd, + kExprDrop, + kExprI32Const, 1, + kExprReturn, + ]) + .exportFunc(); + builder.addFunction('castNullToNullExnRef', + makeSig([kWasmExnRef], [kWasmI32])) + .addBody([ + kExprBlock, kWasmRefNull, kNullExnRefCode, + kExprLocalGet, 0, + ...wasmBrOnCast(0, + wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmNullExnRef)), + kExprI32Const, 0, + kExprReturn, + kExprEnd, + kExprDrop, + kExprI32Const, 1, + kExprReturn, + ]) + .exportFunc(); + + builder.addFunction('castFailToExnRef', + makeSig([kWasmExnRef], [kWasmI32])) + .addBody([ + kExprBlock, kWasmRefNull, kExnRefCode, + kExprLocalGet, 0, + ...wasmBrOnCastFail(0, + wasmRefNullType(kWasmExnRef), wasmRefType(kWasmExnRef)), + kExprI32Const, 0, + kExprReturn, + kExprEnd, + kExprDrop, + kExprI32Const, 1, + kExprReturn, + ]) + .exportFunc(); + builder.addFunction('castFailToNullExnRef', + makeSig([kWasmExnRef], [kWasmI32])) + .addBody([ + kExprBlock, kWasmRefNull, kExnRefCode, + kExprLocalGet, 0, + ...wasmBrOnCastFail(0, + wasmRefNullType(kWasmExnRef), wasmRefType(kWasmNullExnRef)), + kExprI32Const, 0, + kExprReturn, + kExprEnd, + kExprDrop, + kExprI32Const, 1, + kExprReturn, + ]) + .exportFunc(); + + builder.addFunction('castFailNullToExnRef', + makeSig([kWasmExnRef], [kWasmI32])) + .addBody([ + kExprBlock, kWasmRef, kExnRefCode, + kExprLocalGet, 0, + ...wasmBrOnCastFail(0, + wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmExnRef)), + kExprI32Const, 0, + kExprReturn, + kExprEnd, + kExprDrop, + kExprI32Const, 1, + kExprReturn, + ]) + .exportFunc(); + builder.addFunction('castFailNullToNullExnRef', + makeSig([kWasmExnRef], [kWasmI32])) + .addBody([ + kExprBlock, kWasmRef, kExnRefCode, + kExprLocalGet, 0, + ...wasmBrOnCastFail(0, + wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmNullExnRef)), + kExprI32Const, 0, + kExprReturn, + kExprEnd, + kExprDrop, + kExprI32Const, 1, + kExprReturn, + ]) + .exportFunc(); + + let instance = builder.instantiate(); + let wasm = instance.exports; + let exnRef = getExnRef(); + + assertEquals(0, wasm.castToExnRef(null)); + assertEquals(1, wasm.castToExnRef(exnRef)); + + assertEquals(0, wasm.castToNullExnRef(null)); + assertEquals(0, wasm.castToNullExnRef(exnRef)); + + assertEquals(1, wasm.castNullToExnRef(null)); + assertEquals(1, wasm.castNullToExnRef(exnRef)); + + assertEquals(1, wasm.castNullToNullExnRef(null)); + assertEquals(0, wasm.castNullToNullExnRef(exnRef)); + + assertEquals(1, wasm.castFailToExnRef(null)); + assertEquals(0, wasm.castFailToExnRef(exnRef)); + + assertEquals(1, wasm.castFailToNullExnRef(null)); + assertEquals(1, wasm.castFailToNullExnRef(exnRef)); + + assertEquals(0, wasm.castFailNullToExnRef(null)); + assertEquals(0, wasm.castFailNullToExnRef(exnRef)); + + assertEquals(0, wasm.castFailNullToNullExnRef(null)); + assertEquals(1, wasm.castFailNullToNullExnRef(exnRef)); +})(); diff --git a/deps/v8/test/mjsunit/wasm/gc-casts-invalid.js b/deps/v8/test/mjsunit/wasm/gc-casts-invalid.js index 3d2f25905e229d..dcb12615e9a14b 100644 --- a/deps/v8/test/mjsunit/wasm/gc-casts-invalid.js +++ b/deps/v8/test/mjsunit/wasm/gc-casts-invalid.js @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Flags: --experimental-wasm-exnref + d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js'); (function TestRefTestInvalid() { @@ -20,6 +22,11 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js'); [wasmRefType(sig), kExternRefCode], [kWasmAnyRef, kExternRefCode], [kWasmAnyRef, kFuncRefCode], + [kWasmAnyRef, kExnRefCode], + [wasmRefType(sig), kExnRefCode], + [kWasmNullExternRef, kExnRefCode], + [wasmRefType(array), kNullExnRefCode], + [kWasmNullFuncRef, kNullExnRefCode], ]; let casts = [ kExprRefTest, diff --git a/deps/v8/test/mjsunit/wasm/js-wrapper-typechecks.js b/deps/v8/test/mjsunit/wasm/js-wrapper-typechecks.js index 3a5c626732eddd..04a9581547dee0 100644 --- a/deps/v8/test/mjsunit/wasm/js-wrapper-typechecks.js +++ b/deps/v8/test/mjsunit/wasm/js-wrapper-typechecks.js @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js'); +// Flags: --experimental-wasm-exnref +d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js'); (function testNonNullRefWrapperNullCheck() { print(arguments.callee.name); @@ -12,6 +13,7 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js'); 'any': kWasmAnyRef, 'func': kWasmFuncRef, 'array': kWasmArrayRef, + 'exn': kWasmExnRef, })) { print(`- ${name}`); let builder = new WasmModuleBuilder(); diff --git a/deps/v8/test/mjsunit/wasm/wasm-module-builder.js b/deps/v8/test/mjsunit/wasm/wasm-module-builder.js index cdd67a31d33852..271b6a583ebff0 100644 --- a/deps/v8/test/mjsunit/wasm/wasm-module-builder.js +++ b/deps/v8/test/mjsunit/wasm/wasm-module-builder.js @@ -133,6 +133,7 @@ let kWasmI31Ref = -0x14; let kWasmStructRef = -0x15; let kWasmArrayRef = -0x16; let kWasmExnRef = -0x17; +let kWasmNullExnRef = -0x0c; let kWasmStringRef = -0x19; let kWasmStringViewWtf8 = -0x1a; let kWasmStringViewWtf16 = -0x1e; @@ -151,6 +152,7 @@ let kNullFuncRefCode = kWasmNullFuncRef & kLeb128Mask; let kStructRefCode = kWasmStructRef & kLeb128Mask; let kArrayRefCode = kWasmArrayRef & kLeb128Mask; let kExnRefCode = kWasmExnRef & kLeb128Mask; +let kNullExnRefCode = kWasmNullExnRef & kLeb128Mask; let kNullRefCode = kWasmNullRef & kLeb128Mask; let kStringRefCode = kWasmStringRef & kLeb128Mask; let kStringViewWtf8Code = kWasmStringViewWtf8 & kLeb128Mask; From 00480c98ff9e841c051717e4cb53afc131a9f607 Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Thu, 21 Mar 2024 11:09:53 +0000 Subject: [PATCH 02/17] deps: V8: cherry-pick b2f3aea23a01 Original commit message: [wasm][exnref] Do not allow exnref at the wasm/JS boundary R=mliedtke@chromium.org Bug: v8:14398 Change-Id: I5bb75a83e9de9f838d8e530c77c89aa031f473f9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5381603 Reviewed-by: Matthias Liedtke Commit-Queue: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#92944} Refs: https://github.com/v8/v8/commit/b2f3aea23a015430f02b5241fa9897f8088d9aa7 --- common.gypi | 2 +- deps/v8/src/wasm/wasm-js.cc | 18 ++- deps/v8/src/wasm/wasm-objects.cc | 9 +- deps/v8/src/wasm/wasm-opcodes.cc | 1 + deps/v8/test/mjsunit/wasm/exnref-global.js | 23 ++- deps/v8/test/mjsunit/wasm/exnref.js | 5 +- deps/v8/test/mjsunit/wasm/gc-casts-exnref.js | 139 +++++++++++++----- .../wasm-spec-tests/wasm-spec-tests.status | 4 + 8 files changed, 145 insertions(+), 56 deletions(-) diff --git a/common.gypi b/common.gypi index 51609a897aceb9..9ab011f5cddd08 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.40', + 'v8_embedder_string': '-node.41', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index c6d20d790c8504..127dbc091cb84a 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -2445,9 +2445,9 @@ void WebAssemblyTableGrowImpl(const v8::FunctionCallbackInfo& info) { namespace { void WasmObjectToJSReturnValue(v8::ReturnValue& return_value, i::Handle value, - i::wasm::HeapType type, i::Isolate* isolate, + i::wasm::ValueType type, i::Isolate* isolate, ErrorThrower* thrower) { - switch (type.representation()) { + switch (type.heap_type().representation()) { case internal::wasm::HeapType::kStringViewWtf8: thrower->TypeError("%s", "stringview_wtf8 has no JS representation"); break; @@ -2457,6 +2457,10 @@ void WasmObjectToJSReturnValue(v8::ReturnValue& return_value, case internal::wasm::HeapType::kStringViewIter: thrower->TypeError("%s", "stringview_iter has no JS representation"); break; + case internal::wasm::HeapType::kExn: + case internal::wasm::HeapType::kNoExn: + thrower->TypeError("invalid type %s", type.name().c_str()); + break; default: { return_value.Set(Utils::ToLocal(i::wasm::WasmToJSObject(isolate, value))); break; @@ -2490,8 +2494,8 @@ void WebAssemblyTableGetImpl(const v8::FunctionCallbackInfo& info) { i::WasmTableObject::Get(i_isolate, receiver, index); v8::ReturnValue return_value = info.GetReturnValue(); - WasmObjectToJSReturnValue(return_value, result, receiver->type().heap_type(), - i_isolate, &thrower); + WasmObjectToJSReturnValue(return_value, result, receiver->type(), i_isolate, + &thrower); } // WebAssembly.Table.set(num, any) @@ -2767,8 +2771,7 @@ void WebAssemblyExceptionGetArgImpl( case i::wasm::kRefNull: { i::Handle obj = handle(values->get(decode_index), i_isolate); ReturnValue return_value = info.GetReturnValue(); - return WasmObjectToJSReturnValue(return_value, obj, - signature->get(index).heap_type(), + return WasmObjectToJSReturnValue(return_value, obj, signature->get(index), i_isolate, &thrower); } case i::wasm::kRtt: @@ -2836,8 +2839,7 @@ void WebAssemblyGlobalGetValueCommon( case i::wasm::kRef: case i::wasm::kRefNull: { WasmObjectToJSReturnValue(return_value, receiver->GetRef(), - receiver->type().heap_type(), i_isolate, - &thrower); + receiver->type(), i_isolate, &thrower); break; } case i::wasm::kRtt: diff --git a/deps/v8/src/wasm/wasm-objects.cc b/deps/v8/src/wasm/wasm-objects.cc index ab1e4841a9f156..889de39fa5b16f 100644 --- a/deps/v8/src/wasm/wasm-objects.cc +++ b/deps/v8/src/wasm/wasm-objects.cc @@ -2547,6 +2547,12 @@ MaybeHandle JSToWasmObject(Isolate* isolate, Handle value, case HeapType::kStringViewIter: *error_message = "stringview_iter has no JS representation"; return {}; + case HeapType::kExn: + *error_message = "invalid type (ref null exn)"; + return {}; + case HeapType::kNoExn: + *error_message = "invalid type (ref null noexn)"; + return {}; default: { HeapType::Representation repr = expected_canonical.heap_representation_non_shared(); @@ -2589,8 +2595,7 @@ MaybeHandle JSToWasmObject(Isolate* isolate, Handle value, return {}; } case HeapType::kExn: - if (!IsNull(*value, isolate)) return value; - *error_message = "null is not allowed for (ref exn)"; + *error_message = "invalid type (ref exn)"; return {}; case HeapType::kStruct: { if (IsWasmStruct(*value)) { diff --git a/deps/v8/src/wasm/wasm-opcodes.cc b/deps/v8/src/wasm/wasm-opcodes.cc index 61a7f8414d6db9..b383e0f1ec919f 100644 --- a/deps/v8/src/wasm/wasm-opcodes.cc +++ b/deps/v8/src/wasm/wasm-opcodes.cc @@ -33,6 +33,7 @@ bool IsJSCompatibleSignature(const FunctionSig* sig) { // Rtts are internal-only. They should never be part of a signature. DCHECK(!type.is_rtt()); if (type == kWasmS128) return false; + if (type == kWasmExnRef) return false; if (type.is_object_reference()) { switch (type.heap_representation_non_shared()) { case HeapType::kStringViewWtf8: diff --git a/deps/v8/test/mjsunit/wasm/exnref-global.js b/deps/v8/test/mjsunit/wasm/exnref-global.js index 8584ac8126c6dc..3f9b1e1aa30021 100644 --- a/deps/v8/test/mjsunit/wasm/exnref-global.js +++ b/deps/v8/test/mjsunit/wasm/exnref-global.js @@ -28,12 +28,15 @@ let kSig_e_v = makeSig([], [kWasmExnRef]); print(arguments.callee.name); let builder = new WasmModuleBuilder(); let g = builder.addGlobal(kWasmExnRef, false, false); - builder.addFunction('push_and_return_exnref', kSig_e_v) - .addBody([kExprGlobalGet, g.index]) + builder.addFunction('push_and_check_exnref', kSig_i_v) + .addBody([ + kExprGlobalGet, g.index, + kExprRefIsNull, kExnRefCode, + ]) .exportFunc(); let instance = builder.instantiate(); - assertEquals(null, instance.exports.push_and_return_exnref()); + assertEquals(1, instance.exports.push_and_check_exnref()); })(); // Test custom initialization index for a global "exnref" variable. @@ -44,8 +47,16 @@ let kSig_e_v = makeSig([], [kWasmExnRef]); builder.addFunction('push_and_return_exnref', kSig_e_v) .addBody([kExprGlobalGet, g_index]) .exportFunc(); - let exception = { x: "my fancy exception" }; - let instance = builder.instantiate({ "m": { "exn": exception }}); + assertThrows(() => builder.instantiate({ "m": { "exn": {} }}), WebAssembly.LinkError); + assertThrows(() => builder.instantiate({ "m": { "exn": null }}), WebAssembly.LinkError); +})(); - assertSame(exception, instance.exports.push_and_return_exnref()); +(function TestGlobalExnRefJsApi() { + print(arguments.callee.name); + + let builder = new WasmModuleBuilder(); + let g_index = builder.addGlobal(kWasmExnRef, true, false).exportAs('g'); + let instance = builder.instantiate(); + assertThrows(() => new WebAssembly.Global({value: "exnref", mutable: true}, null), TypeError); + assertThrows(() => { instance.exports.g.value; }, TypeError); })(); diff --git a/deps/v8/test/mjsunit/wasm/exnref.js b/deps/v8/test/mjsunit/wasm/exnref.js index 68030588e68838..36dfe701f6d243 100644 --- a/deps/v8/test/mjsunit/wasm/exnref.js +++ b/deps/v8/test/mjsunit/wasm/exnref.js @@ -611,12 +611,11 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); kExprEnd, kExprReturn, kExprEnd, - kExprGlobalSet, g.index, + kExprThrowRef ]).exportFunc(); let instance = builder.instantiate(); - instance.exports.catch_all_ref(); - assertTrue(instance.exports.g.value instanceof WebAssembly.Exception); + assertThrows(instance.exports.catch_all_ref, WebAssembly.Exception); })(); (function TestCatchRefTwoParams() { diff --git a/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js b/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js index f7b19ec40ceb49..ba1f30a4dee26c 100644 --- a/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js +++ b/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js @@ -7,82 +7,142 @@ d8.file.execute('test/mjsunit/wasm/wasm-module-builder.js'); let getExnRef = function() { - let tag = new WebAssembly.Tag({parameters:[]}); + let tag = new WebAssembly.Tag({parameters: []}); return new WebAssembly.Exception(tag, []); -}; +} + +// Helper module to produce an exnref or convert a JS value to an exnref. +let helper = (function () { + let builder = new WasmModuleBuilder(); + let tag_index = builder.addTag(kSig_v_v); + let throw_index = builder.addImport('m', 'import', kSig_v_r); + builder.addFunction('get_exnref', makeSig([], [kWasmExnRef])) + .addBody([ + kExprTryTable, kWasmVoid, 1, + kCatchAllRef, 0, + kExprThrow, tag_index, + kExprEnd, + kExprUnreachable, + ]).exportFunc(); + builder.addFunction('to_exnref', makeSig([kWasmExternRef], [kWasmExnRef])) + .addBody([ + kExprTryTable, kWasmVoid, 1, + kCatchAllRef, 0, + kExprLocalGet, 0, + kExprCallFunction, throw_index, + kExprEnd, + kExprUnreachable, + ]).exportFunc(); + function throw_js(r) { throw r; } + let instance = builder.instantiate({m: {import: throw_js}}); + return instance; +})(); (function RefTestExnRef() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); - let tag = builder.addTag(makeSig([], [])); + let get_exnref = builder.addImport('m', 'get_exnref', makeSig([], [kWasmExnRef])); builder.addFunction('testExnRef', - makeSig([kWasmExnRef], [kWasmI32, kWasmI32])) + makeSig([], [kWasmI32, kWasmI32, kWasmI32, kWasmI32])) + .addLocals(kWasmExnRef, 1) .addBody([ - kExprLocalGet, 0, kGCPrefix, kExprRefTest, kExnRefCode, - kExprLocalGet, 0, kGCPrefix, kExprRefTest, kNullExnRefCode, + kExprLocalGet, 0, + kGCPrefix, kExprRefTest, kExnRefCode, + kExprLocalGet, 0, + kGCPrefix, kExprRefTest, kNullExnRefCode, + kExprCallFunction, get_exnref, + kGCPrefix, kExprRefTest, kExnRefCode, + kExprCallFunction, get_exnref, + kGCPrefix, kExprRefTest, kNullExnRefCode, ]).exportFunc(); builder.addFunction('testNullExnRef', - makeSig([kWasmExnRef], [kWasmI32, kWasmI32])) + makeSig([], [kWasmI32, kWasmI32, kWasmI32, kWasmI32])) + .addLocals(kWasmExnRef, 1) .addBody([ - kExprLocalGet, 0, kGCPrefix, kExprRefTestNull, kExnRefCode, - kExprLocalGet, 0, kGCPrefix, kExprRefTestNull, kNullExnRefCode, + kExprLocalGet, 0, + kGCPrefix, kExprRefTestNull, kExnRefCode, + kExprLocalGet, 0, + kGCPrefix, kExprRefTestNull, kNullExnRefCode, + kExprCallFunction, get_exnref, + kGCPrefix, kExprRefTestNull, kExnRefCode, + kExprCallFunction, get_exnref, + kGCPrefix, kExprRefTestNull, kNullExnRefCode, ]).exportFunc(); - let instance = builder.instantiate(); + + let instance = builder.instantiate({m: {get_exnref: helper.exports.get_exnref}}); let wasm = instance.exports; - assertEquals([0, 0], wasm.testExnRef(null)); - assertEquals([1, 0], wasm.testExnRef(getExnRef())); - assertEquals([1, 1], wasm.testNullExnRef(null)); - assertEquals([1, 0], wasm.testNullExnRef(getExnRef())); + assertEquals([0, 0, 1, 0], wasm.testExnRef()); + assertEquals([1, 1, 1, 0], wasm.testNullExnRef()); })(); (function RefCastExnRef() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); + let to_exnref = builder.addImport('m', 'to_exnref', makeSig([kWasmExternRef], [kWasmExnRef])); builder.addFunction('castToExnRef', - makeSig([kWasmExnRef], [kWasmExnRef])) - .addBody([kExprLocalGet, 0, kGCPrefix, kExprRefCast, kExnRefCode]) + makeSig([kWasmExternRef], [])) + .addBody([ + kExprLocalGet, 0, + kExprCallFunction, to_exnref, + kGCPrefix, kExprRefCast, kExnRefCode, + kExprThrowRef]) .exportFunc(); builder.addFunction('castToNullExnRef', - makeSig([kWasmExnRef], [kWasmExnRef])) - .addBody([kExprLocalGet, 0, kGCPrefix, kExprRefCast, kNullExnRefCode]) + makeSig([kWasmExternRef], [])) + .addBody([ + kExprLocalGet, 0, + kExprCallFunction, to_exnref, + kGCPrefix, kExprRefCast, kNullExnRefCode, + kExprDrop]) .exportFunc(); builder.addFunction('castNullToExnRef', - makeSig([kWasmExnRef], [kWasmExnRef])) - .addBody([kExprLocalGet, 0, kGCPrefix, kExprRefCastNull, kExnRefCode]) + makeSig([kWasmExternRef], [])) + .addBody([ + kExprLocalGet, 0, + kExprCallFunction, to_exnref, + kGCPrefix, kExprRefCastNull, kExnRefCode, + kExprThrowRef]) .exportFunc(); builder.addFunction('castNullToNullExnRef', - makeSig([kWasmExnRef], [kWasmExnRef])) - .addBody([kExprLocalGet, 0, kGCPrefix, kExprRefCastNull, kNullExnRefCode]) + makeSig([kWasmExternRef], [])) + .addBody([ + kExprLocalGet, 0, + kExprCallFunction, to_exnref, + kGCPrefix, kExprRefCastNull, kNullExnRefCode, + kGCPrefix, kExprRefCastNull, kExnRefCode, + kExprThrowRef]) .exportFunc(); - let instance = builder.instantiate(); + let instance = builder.instantiate({m: {to_exnref: helper.exports.to_exnref}}); let wasm = instance.exports; let exnRef = getExnRef(); assertTraps(kTrapIllegalCast, () => wasm.castToExnRef(null)); - assertEquals(exnRef, wasm.castToExnRef(exnRef)); + assertThrowsEquals(() => wasm.castToExnRef(exnRef), exnRef); assertTraps(kTrapIllegalCast, () => wasm.castToNullExnRef(null)); assertTraps(kTrapIllegalCast, () => wasm.castToNullExnRef(exnRef)); - assertSame(null, wasm.castNullToExnRef(null)); - assertEquals(exnRef, wasm.castNullToExnRef(exnRef)); - assertSame(null, wasm.castNullToNullExnRef(null)); + assertThrows(() => wasm.castNullToExnRef(null), Error, /rethrowing null value/); + assertThrowsEquals(() => wasm.castNullToExnRef(exnRef), exnRef); + assertThrows(() => wasm.castNullToNullExnRef(null), Error, /rethrowing null value/); assertTraps(kTrapIllegalCast, () => wasm.castNullToNullExnRef(exnRef)); })(); (function BrOnCastExnRef() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); + let to_exnref = builder.addImport('m', 'to_exnref', makeSig([kWasmExternRef], [kWasmExnRef])); builder.addFunction('castToExnRef', - makeSig([kWasmExnRef], [kWasmI32])) + makeSig([kWasmExternRef], [kWasmI32])) .addBody([ kExprBlock, kWasmRef, kExnRefCode, kExprLocalGet, 0, + kExprCallFunction, to_exnref, ...wasmBrOnCast( 0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmExnRef)), kExprI32Const, 0, @@ -94,10 +154,11 @@ let getExnRef = function() { ]) .exportFunc(); builder.addFunction('castToNullExnRef', - makeSig([kWasmExnRef], [kWasmI32])) + makeSig([kWasmExternRef], [kWasmI32])) .addBody([ kExprBlock, kWasmRef, kNullExnRefCode, kExprLocalGet, 0, + kExprCallFunction, to_exnref, ...wasmBrOnCast( 0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmNullExnRef)), kExprI32Const, 0, @@ -110,10 +171,11 @@ let getExnRef = function() { .exportFunc(); builder.addFunction('castNullToExnRef', - makeSig([kWasmExnRef], [kWasmI32])) + makeSig([kWasmExternRef], [kWasmI32])) .addBody([ kExprBlock, kWasmRefNull, kExnRefCode, kExprLocalGet, 0, + kExprCallFunction, to_exnref, ...wasmBrOnCast(0, wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmExnRef)), kExprI32Const, 0, @@ -125,10 +187,11 @@ let getExnRef = function() { ]) .exportFunc(); builder.addFunction('castNullToNullExnRef', - makeSig([kWasmExnRef], [kWasmI32])) + makeSig([kWasmExternRef], [kWasmI32])) .addBody([ kExprBlock, kWasmRefNull, kNullExnRefCode, kExprLocalGet, 0, + kExprCallFunction, to_exnref, ...wasmBrOnCast(0, wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmNullExnRef)), kExprI32Const, 0, @@ -141,10 +204,11 @@ let getExnRef = function() { .exportFunc(); builder.addFunction('castFailToExnRef', - makeSig([kWasmExnRef], [kWasmI32])) + makeSig([kWasmExternRef], [kWasmI32])) .addBody([ kExprBlock, kWasmRefNull, kExnRefCode, kExprLocalGet, 0, + kExprCallFunction, to_exnref, ...wasmBrOnCastFail(0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmExnRef)), kExprI32Const, 0, @@ -156,10 +220,11 @@ let getExnRef = function() { ]) .exportFunc(); builder.addFunction('castFailToNullExnRef', - makeSig([kWasmExnRef], [kWasmI32])) + makeSig([kWasmExternRef], [kWasmI32])) .addBody([ kExprBlock, kWasmRefNull, kExnRefCode, kExprLocalGet, 0, + kExprCallFunction, to_exnref, ...wasmBrOnCastFail(0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmNullExnRef)), kExprI32Const, 0, @@ -172,10 +237,11 @@ let getExnRef = function() { .exportFunc(); builder.addFunction('castFailNullToExnRef', - makeSig([kWasmExnRef], [kWasmI32])) + makeSig([kWasmExternRef], [kWasmI32])) .addBody([ kExprBlock, kWasmRef, kExnRefCode, kExprLocalGet, 0, + kExprCallFunction, to_exnref, ...wasmBrOnCastFail(0, wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmExnRef)), kExprI32Const, 0, @@ -187,10 +253,11 @@ let getExnRef = function() { ]) .exportFunc(); builder.addFunction('castFailNullToNullExnRef', - makeSig([kWasmExnRef], [kWasmI32])) + makeSig([kWasmExternRef], [kWasmI32])) .addBody([ kExprBlock, kWasmRef, kExnRefCode, kExprLocalGet, 0, + kExprCallFunction, to_exnref, ...wasmBrOnCastFail(0, wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmNullExnRef)), kExprI32Const, 0, @@ -202,7 +269,7 @@ let getExnRef = function() { ]) .exportFunc(); - let instance = builder.instantiate(); + let instance = builder.instantiate({m: {to_exnref: helper.exports.to_exnref}}); let wasm = instance.exports; let exnRef = getExnRef(); diff --git a/deps/v8/test/wasm-spec-tests/wasm-spec-tests.status b/deps/v8/test/wasm-spec-tests/wasm-spec-tests.status index 84faab6193c8ac..717ba82a536a8a 100644 --- a/deps/v8/test/wasm-spec-tests/wasm-spec-tests.status +++ b/deps/v8/test/wasm-spec-tests/wasm-spec-tests.status @@ -85,6 +85,10 @@ 'proposals/tail-call/binary': [FAIL], 'proposals/exception-handling/binary': [FAIL], 'proposals/exception-handling/imports': [FAIL], + + # The test is incorrect as it exports a function with an exnref in the + # signature, which is a runtime type error. + 'proposals/exception-handling/ref_null': [FAIL] }], # ALWAYS ['arch == arm and not simulator_run', { From 82e371c591773aefe3f26f8b689034a4d186259e Mon Sep 17 00:00:00 2001 From: Manos Koukoutos Date: Mon, 1 Apr 2024 09:23:04 +0200 Subject: [PATCH 03/17] deps: V8: cherry-pick c734674e03f9 Original commit message: [wasm][exnref] Fix null value for constant expressions Bug: v8:14398 Change-Id: Ia00d2de97a897d608d6c043b6e267c7d6313a18b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5402583 Auto-Submit: Manos Koukoutos Commit-Queue: Thibaud Michaud Reviewed-by: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#93107} Refs: https://github.com/v8/v8/commit/c734674e03f9d065312c77016dc61bf046692429 --- common.gypi | 2 +- deps/v8/src/wasm/constant-expression-interface.cc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common.gypi b/common.gypi index 9ab011f5cddd08..8a74ba163b8a34 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.41', + 'v8_embedder_string': '-node.42', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/constant-expression-interface.cc b/deps/v8/src/wasm/constant-expression-interface.cc index c09bd2c1b2fe82..75e6d198df6236 100644 --- a/deps/v8/src/wasm/constant-expression-interface.cc +++ b/deps/v8/src/wasm/constant-expression-interface.cc @@ -105,7 +105,8 @@ void ConstantExpressionInterface::RefNull(FullDecoder* decoder, ValueType type, Value* result) { if (!generate_value()) return; result->runtime_value = - WasmValue(type == kWasmExternRef || type == kWasmNullExternRef + WasmValue((IsSubtypeOf(type, kWasmExternRef, decoder->module_) || + IsSubtypeOf(type, kWasmExnRef, decoder->module_)) ? Handle::cast(isolate_->factory()->null_value()) : Handle::cast(isolate_->factory()->wasm_null()), type); From 6ed9e61b5f381ceda720fc88c5922f99a9d34dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Doeraene?= Date: Wed, 10 Apr 2024 19:27:23 +0200 Subject: [PATCH 04/17] deps: V8: cherry-pick 692f3d526a38 Original commit message: [wasm][exnref] Implement special behavior of WA.JSTag in try_table. This commit ports the changes from 4e79015dc28659a8a031f06580e902720b35674c to `CatchCase`, i.e., the `try_table` instruction. In addition, it implements the same changes in Turboshaft, for which the implementation of exceptions initially came from 2c1c14d30c61fa4fa19184369e587cb663bd8580 and already contained the `JSTag` handling for `CatchException`. This commit addresses part of https://issues.chromium.org/issues/333067164 but not all. Only catching with `try_table` is fixed. `throw` remains unchanged. Change-Id: I7bad031e28eaf609fb12e7706d0b6a7cc63fa09d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5435077 Commit-Queue: Thibaud Michaud Reviewed-by: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#93303} Refs: https://github.com/v8/v8/commit/692f3d526a382b3c2f1d979105e777df16855e84 --- common.gypi | 2 +- deps/v8/AUTHORS | 1 + deps/v8/src/wasm/baseline/liftoff-compiler.cc | 109 ++++++++-- deps/v8/src/wasm/graph-builder-interface.cc | 55 ++++- .../v8/src/wasm/turboshaft-graph-interface.cc | 72 ++++++- deps/v8/test/mjsunit/wasm/exnref-api.js | 203 ++++++++++++++++++ deps/v8/test/mjsunit/wasm/exnref.js | 2 +- 7 files changed, 416 insertions(+), 28 deletions(-) create mode 100644 deps/v8/test/mjsunit/wasm/exnref-api.js diff --git a/common.gypi b/common.gypi index 8a74ba163b8a34..b34cb104b34786 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.42', + 'v8_embedder_string': '-node.43', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index 93b3d9d5b2320c..394c7deedb0717 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -258,6 +258,7 @@ Sander Mathijs van Veen Sandro Santilli Sanjoy Das Sam James +Sébastien Doeraene Seo Sanghyeon Shawn Anastasio Shawn Presser diff --git a/deps/v8/src/wasm/baseline/liftoff-compiler.cc b/deps/v8/src/wasm/baseline/liftoff-compiler.cc index 78e7247456754d..d14057b88a8748 100644 --- a/deps/v8/src/wasm/baseline/liftoff-compiler.cc +++ b/deps/v8/src/wasm/baseline/liftoff-compiler.cc @@ -1548,23 +1548,104 @@ class LiftoffCompiler { wasm::ObjectAccess::ElementOffsetInTaggedFixedArray( catch_case.maybe_tag.tag_imm.index)); + VarState exn = __ cache_state() -> stack_state.back(); + CODE_COMMENT("compare tags"); - { - FREEZE_STATE(frozen); - Label caught; - __ emit_cond_jump(kEqual, &caught, kRefNull, imm_tag, caught_tag.gp(), - frozen); - // The tags don't match, merge the current state into the catch state - // and jump to the next handler. - __ MergeFullStackWith(block->try_info->catch_state); - __ emit_jump(&block->try_info->catch_label); - __ bind(&caught); + if (catch_case.maybe_tag.tag_imm.tag->sig->parameter_count() == 1 && + catch_case.maybe_tag.tag_imm.tag->sig->GetParam(0) == kWasmExternRef) { + // Check for the special case where the tag is WebAssembly.JSTag and the + // exception is not a WebAssembly.Exception. In this case the exception is + // caught and pushed on the operand stack. + // Only perform this check if the tag signature is the same as + // the JSTag signature, i.e. a single externref, otherwise we know + // statically that it cannot be the JSTag. + LiftoffRegister undefined = + pinned.set(__ GetUnusedRegister(kGpReg, pinned)); + __ LoadFullPointer( + undefined.gp(), kRootRegister, + IsolateData::root_slot_offset(RootIndex::kUndefinedValue)); + LiftoffRegister js_tag = pinned.set(__ GetUnusedRegister(kGpReg, pinned)); + LOAD_TAGGED_PTR_INSTANCE_FIELD(js_tag.gp(), NativeContext, pinned); + __ LoadTaggedPointer( + js_tag.gp(), js_tag.gp(), no_reg, + NativeContext::SlotOffset(Context::WASM_JS_TAG_INDEX)); + __ LoadTaggedPointer( + js_tag.gp(), js_tag.gp(), no_reg, + wasm::ObjectAccess::ToTagged(WasmTagObject::kTagOffset)); + { + LiftoffAssembler::CacheState initial_state(zone_); + LiftoffAssembler::CacheState end_state(zone_); + Label js_exception; + Label done; + Label uncaught; + initial_state.Split(*__ cache_state()); + { + FREEZE_STATE(state_merged_explicitly); + // If the tag is undefined, this is not a wasm exception. Go to a + // different block to process the JS exception. Otherwise compare it + // with the expected tag. + __ emit_cond_jump(kEqual, &js_exception, kRefNull, caught_tag.gp(), + undefined.gp(), state_merged_explicitly); + __ emit_cond_jump(kNotEqual, &uncaught, kRefNull, imm_tag, + caught_tag.gp(), state_merged_explicitly); + } + // Case 1: A wasm exception with a matching tag. + CODE_COMMENT("unpack exception"); + GetExceptionValues(decoder, __ cache_state()->stack_state.back(), + catch_case.maybe_tag.tag_imm.tag); + // GetExceptionValues modified the cache state. Remember the new state + // to merge the end state of case 2 into it. + end_state.Steal(*__ cache_state()); + __ emit_jump(&done); + + __ bind(&js_exception); + __ cache_state() -> Split(initial_state); + { + FREEZE_STATE(state_merged_explicitly); + __ emit_cond_jump(kNotEqual, &uncaught, kRefNull, imm_tag, + js_tag.gp(), state_merged_explicitly); + } + // Case 2: A JS exception, and the expected tag is JSTag. + // TODO(thibaudm): Can we avoid some state splitting/stealing by + // reserving this register earlier and not modifying the state in this + // block? + CODE_COMMENT("JS exception caught by JSTag"); + LiftoffRegister exception = __ PeekToRegister(0, pinned); + __ PushRegister(kRefNull, exception); + // The exception is now on the stack twice: once as an implicit operand + // for rethrow, and once as the "unpacked" value. + __ MergeFullStackWith(end_state); + __ emit_jump(&done); + + // Case 3: Either a wasm exception with a mismatching tag, or a JS + // exception but the expected tag is not JSTag. + __ bind(&uncaught); + __ cache_state() -> Steal(initial_state); + __ MergeFullStackWith(block->try_info->catch_state); + __ emit_jump(&block->try_info->catch_label); + + __ bind(&done); + __ cache_state() -> Steal(end_state); + } + } else { + { + FREEZE_STATE(frozen); + Label caught; + __ emit_cond_jump(kEqual, &caught, kRefNull, imm_tag, caught_tag.gp(), + frozen); + // The tags don't match, merge the current state into the catch state + // and jump to the next handler. + __ MergeFullStackWith(block->try_info->catch_state); + __ emit_jump(&block->try_info->catch_label); + __ bind(&caught); + } + + CODE_COMMENT("unpack exception"); + pinned = {}; + GetExceptionValues(decoder, __ cache_state()->stack_state.back(), + catch_case.maybe_tag.tag_imm.tag); } - CODE_COMMENT("unpack exception"); - pinned = {}; - VarState exn = __ cache_state()->stack_state.back(); - GetExceptionValues(decoder, exn, catch_case.maybe_tag.tag_imm.tag); if (catch_case.kind == kCatchRef) { // Append the exception on the operand stack. DCHECK(exn.is_stack()); diff --git a/deps/v8/src/wasm/graph-builder-interface.cc b/deps/v8/src/wasm/graph-builder-interface.cc index 0ee5c9ceb71909..458d8d859c2ac8 100644 --- a/deps/v8/src/wasm/graph-builder-interface.cc +++ b/deps/v8/src/wasm/graph-builder-interface.cc @@ -1420,9 +1420,58 @@ class WasmGraphBuildingInterface { base::Vector values_without_exnref = catch_case.kind == kCatch ? values : values.SubVector(0, values.size() - 1); - CatchAndUnpackWasmException(decoder, block, exception, - catch_case.maybe_tag.tag_imm.tag, caught_tag, - expected_tag, values_without_exnref); + + if (catch_case.maybe_tag.tag_imm.tag->sig->parameter_count() == 1 && + catch_case.maybe_tag.tag_imm.tag->sig->GetParam(0) == kWasmExternRef) { + // Check for the special case where the tag is WebAssembly.JSTag and the + // exception is not a WebAssembly.Exception. In this case the exception is + // caught and pushed on the operand stack. + // Only perform this check if the tag signature is the same as + // the JSTag signature, i.e. a single externref, otherwise + // we know statically that it cannot be the JSTag. + + TFNode* is_js_exn = builder_->IsExceptionTagUndefined(caught_tag); + auto [exn_is_js, exn_is_wasm] = builder_->BranchExpectFalse(is_js_exn); + SsaEnv* exn_is_js_env = Split(decoder->zone(), ssa_env_); + exn_is_js_env->control = exn_is_js; + SsaEnv* exn_is_wasm_env = Steal(decoder->zone(), ssa_env_); + exn_is_wasm_env->control = exn_is_wasm; + + // Case 1: A wasm exception. + SetEnv(exn_is_wasm_env); + CatchAndUnpackWasmException(decoder, block, exception, + catch_case.maybe_tag.tag_imm.tag, caught_tag, + expected_tag, values_without_exnref); + + // Case 2: A JS exception. + SetEnv(exn_is_js_env); + TFNode* js_tag = builder_->LoadJSTag(); + TFNode* compare = builder_->ExceptionTagEqual(expected_tag, js_tag); + auto [if_catch, if_no_catch] = builder_->BranchNoHint(compare); + // Merge the wasm no-catch and JS no-catch paths. + SsaEnv* if_no_catch_env = Split(decoder->zone(), ssa_env_); + if_no_catch_env->control = if_no_catch; + SetEnv(if_no_catch_env); + Goto(decoder, block->try_info->catch_env); + // Merge the wasm catch and JS catch paths. + SsaEnv* if_catch_env = Steal(decoder->zone(), ssa_env_); + if_catch_env->control = if_catch; + SetEnv(if_catch_env); + Goto(decoder, block->block_env); + + // The final env is a merge of case 1 and 2. The unpacked value is a Phi + // of the unpacked value (case 1) and the exception itself (case 2). + SetEnv(block->block_env); + TFNode* phi_inputs[] = {values[0].node, exception, + block->block_env->control}; + TFNode* ref = builder_->Phi(wasm::kWasmExternRef, 2, phi_inputs); + SetAndTypeNode(&values[0], ref); + } else { + CatchAndUnpackWasmException(decoder, block, exception, + catch_case.maybe_tag.tag_imm.tag, caught_tag, + expected_tag, values_without_exnref); + } + if (catch_case.kind == kCatchRef) { DCHECK_EQ(values.last().type, kWasmExnRef); values.last().node = block->try_info->exception; diff --git a/deps/v8/src/wasm/turboshaft-graph-interface.cc b/deps/v8/src/wasm/turboshaft-graph-interface.cc index d63d5e36e81409..f431b0fdb94a7e 100644 --- a/deps/v8/src/wasm/turboshaft-graph-interface.cc +++ b/deps/v8/src/wasm/turboshaft-graph-interface.cc @@ -3010,9 +3010,10 @@ class TurboshaftGraphBuildingInterface : public WasmGraphBuilderBase { BrOrRet(decoder, catch_case.br_imm.depth); return; } + V native_context = instance_cache_.native_context(); V caught_tag = V::Cast( CallBuiltinThroughJumptable( - decoder, instance_cache_.native_context(), + decoder, native_context, {block->exception, LOAD_ROOT(wasm_exception_tag_symbol)})); V instance_tags = LOAD_IMMUTABLE_INSTANCE_FIELD(trusted_instance_data(), TagsTable, @@ -3022,17 +3023,70 @@ class TurboshaftGraphBuildingInterface : public WasmGraphBuilderBase { TSBlock* if_catch = __ NewBlock(); TSBlock* if_no_catch = NewBlockWithPhis(decoder, nullptr); SetupControlFlowEdge(decoder, if_no_catch); + + // If the tags don't match we continue with the next tag by setting the + // no-catch environment as the new {block->false_or_loop_or_catch_block} + // here. block->false_or_loop_or_catch_block = if_no_catch; - __ Branch(ConditionWithHint(__ TaggedEqual(caught_tag, expected_tag)), - if_catch, block->false_or_loop_or_catch_block); - __ Bind(if_catch); - if (catch_case.kind == kCatchRef) { - UnpackWasmException(decoder, block->exception, - values.SubVector(0, values.size() - 1)); - values.last().op = block->exception; + + if (catch_case.maybe_tag.tag_imm.tag->sig->parameter_count() == 1 && + catch_case.maybe_tag.tag_imm.tag->sig->GetParam(0) == kWasmExternRef) { + // Check for the special case where the tag is WebAssembly.JSTag and the + // exception is not a WebAssembly.Exception. In this case the exception is + // caught and pushed on the operand stack. + // Only perform this check if the tag signature is the same as + // the JSTag signature, i.e. a single externref, otherwise + // we know statically that it cannot be the JSTag. + V caught_tag_undefined = + __ TaggedEqual(caught_tag, LOAD_ROOT(UndefinedValue)); + Label if_catch(&asm_); + Label<> no_catch_merge(&asm_); + + IF (UNLIKELY(caught_tag_undefined)) { + V tag_object = __ Load( + native_context, LoadOp::Kind::TaggedBase(), + MemoryRepresentation::TaggedPointer(), + NativeContext::OffsetOfElementAt(Context::WASM_JS_TAG_INDEX)); + V js_tag = __ Load(tag_object, LoadOp::Kind::TaggedBase(), + MemoryRepresentation::TaggedPointer(), + WasmTagObject::kTagOffset); + GOTO_IF(__ TaggedEqual(expected_tag, js_tag), if_catch, + block->exception); + GOTO(no_catch_merge); + } ELSE { + IF (__ TaggedEqual(caught_tag, expected_tag)) { + if (catch_case.kind == kCatchRef) { + UnpackWasmException(decoder, block->exception, + values.SubVector(0, values.size() - 1)); + values.last().op = block->exception; + } else { + UnpackWasmException(decoder, block->exception, values); + } + GOTO(if_catch, values[0].op); + } + GOTO(no_catch_merge); + } + + BIND(no_catch_merge); + __ Goto(if_no_catch); + + BIND(if_catch, caught_exception); + // The first unpacked value is the exception itself in the case of a JS + // exception. + values[0].op = caught_exception; } else { - UnpackWasmException(decoder, block->exception, values); + __ Branch(ConditionWithHint(__ TaggedEqual(caught_tag, expected_tag)), + if_catch, if_no_catch); + __ Bind(if_catch); + if (catch_case.kind == kCatchRef) { + UnpackWasmException(decoder, block->exception, + values.SubVector(0, values.size() - 1)); + values.last().op = block->exception; + } else { + UnpackWasmException(decoder, block->exception, values); + } } + BrOrRet(decoder, catch_case.br_imm.depth); bool is_last = &catch_case == &block->catch_cases.last(); diff --git a/deps/v8/test/mjsunit/wasm/exnref-api.js b/deps/v8/test/mjsunit/wasm/exnref-api.js new file mode 100644 index 00000000000000..cf73379ba7b034 --- /dev/null +++ b/deps/v8/test/mjsunit/wasm/exnref-api.js @@ -0,0 +1,203 @@ +// Copyright 2023 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --allow-natives-syntax --experimental-wasm-exnref --turboshaft-wasm + +// This file is for the most parts a direct port of +// test/mjsunit/wasm/exceptions-api.js using the new exception handling +// proposal. + +d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); +d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); + +(function TestCatchJSTag() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let js_tag = builder.addImportedTag("", "tag", kSig_v_r); + + // Throw a JS object and check that we can catch it and unpack it using + // WebAssembly.JSTag in try_table. + function throw_ref(x) { + throw x; + } + let kJSThrowRef = builder.addImport("", "throw_ref", kSig_r_r); + let try_sig_index = builder.addType(kSig_r_v); + builder.addFunction("test", kSig_r_r) + .addBody([ + kExprBlock, try_sig_index, + kExprTryTable, try_sig_index, 1, + kCatchNoRef, js_tag, 0, + kExprLocalGet, 0, + kExprCallFunction, kJSThrowRef, + kExprEnd, + kExprEnd, + ]) + .exportFunc(); + + let instance = builder.instantiate({"": { + throw_ref: throw_ref, + tag: WebAssembly.JSTag, + }}); + + let obj = {}; + + // Catch with implicit wrapping. + assertSame(obj, instance.exports.test(obj)); + // Catch with explicit wrapping. + assertSame(obj, instance.exports.test(new WebAssembly.Exception(WebAssembly.JSTag, [obj]))); + // Don't catch with explicit wrapping. + let not_js_tag = new WebAssembly.Tag({parameters:['externref']}); + let exn = new WebAssembly.Exception(not_js_tag, [obj]); + assertThrowsEquals(() => instance.exports.test(exn), exn); + + + // There is a separate code path for tags with externref type, so also check + // that everything still works when the tag is *not* the JSTag. + + instance = builder.instantiate({"": { + throw_ref: throw_ref, + tag: not_js_tag + }}); + + // Catch with explicit wrapping. + assertSame(obj, instance.exports.test(new WebAssembly.Exception(not_js_tag, [obj]))); + // Don't catch with explicit wrapping. + exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); + // TODO(thibaudm): Should the exception get implicitly unwrapped when it + // bubbles up from wasm to JS, even though it was wrapped explicitly? + assertThrowsEquals(() => instance.exports.test(exn), exn); + // Don't catch with implicit wrapping. + assertThrowsEquals(() => instance.exports.test(obj), obj); +})(); + +(function TestCatchRefJSTag() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let js_tag = builder.addImportedTag("", "tag", kSig_v_r); + + // Throw a JS object and check that we can catch it and unpack it using + // WebAssembly.JSTag in try_table. + function throw_ref(x) { + throw x; + } + let kJSThrowRef = builder.addImport("", "throw_ref", kSig_r_r); + let try_sig_index = builder.addType(kSig_r_v); + let catch_sig_index = builder.addType(makeSig([], [kWasmExternRef, kWasmExnRef])); + builder.addFunction("test", kSig_r_r) + .addBody([ + kExprBlock, catch_sig_index, + kExprTryTable, try_sig_index, 1, + kCatchRef, js_tag, 0, + kExprLocalGet, 0, + kExprCallFunction, kJSThrowRef, + kExprEnd, + kExprReturn, + kExprEnd, + kExprDrop, + ]) + .exportFunc(); + + let instance = builder.instantiate({"": { + throw_ref: throw_ref, + tag: WebAssembly.JSTag, + }}); + + let obj = {}; + + // Catch with implicit wrapping. + assertSame(obj, instance.exports.test(obj)); + // Catch with explicit wrapping. + assertSame(obj, instance.exports.test(new WebAssembly.Exception(WebAssembly.JSTag, [obj]))); + // Don't catch with explicit wrapping. + let not_js_tag = new WebAssembly.Tag({parameters:['externref']}); + let exn = new WebAssembly.Exception(not_js_tag, [obj]); + assertThrowsEquals(() => instance.exports.test(exn), exn); + + + // There is a separate code path for tags with externref type, so also check + // that everything still works when the tag is *not* the JSTag. + + instance = builder.instantiate({"": { + throw_ref: throw_ref, + tag: not_js_tag + }}); + + // Catch with explicit wrapping. + assertSame(obj, instance.exports.test(new WebAssembly.Exception(not_js_tag, [obj]))); + // Don't catch with explicit wrapping. + exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); + // TODO(thibaudm): Should the exception get implicitly unwrapped when it + // bubbles up from wasm to JS, even though it was wrapped explicitly? + assertThrowsEquals(() => instance.exports.test(exn), exn); + // Don't catch with implicit wrapping. + assertThrowsEquals(() => instance.exports.test(obj), obj); +})(); + +(function TestCatchRefThrowRefJSTag() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let js_tag = builder.addImportedTag("", "tag", kSig_v_r); + + // Throw a JS object and check that we can catch it and unpack it using + // WebAssembly.JSTag in try_table, then rethrow it as a JS object with + // throw_ref. + function throw_ref(x) { + throw x; + } + let kJSThrowRef = builder.addImport("", "throw_ref", kSig_r_r); + let try_sig_index = builder.addType(kSig_r_v); + let catch_sig_index = builder.addType(makeSig([], [kWasmExternRef, kWasmExnRef])); + builder.addFunction("test", kSig_r_r) + .addBody([ + kExprBlock, catch_sig_index, + kExprTryTable, try_sig_index, 1, + kCatchRef, js_tag, 0, + kExprLocalGet, 0, + kExprCallFunction, kJSThrowRef, + kExprEnd, + kExprReturn, + kExprEnd, + kExprThrowRef, + ]) + .exportFunc(); + + let instance = builder.instantiate({"": { + throw_ref: throw_ref, + tag: WebAssembly.JSTag, + }}); + + let obj = {}; + + // Catch and rethrown with implicit wrapping. + assertThrowsEquals(() => instance.exports.test(obj), obj); + // Catch and rethrown with explicit wrapping. + // TODO: Should the exception get implicitly unwrapped when it + // is rethrown from wasm to JS, even though it was wrapped explicitly? + let exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); + assertThrowsEquals(() => instance.exports.test(exn), exn); + // Don't catch with explicit wrapping. + let not_js_tag = new WebAssembly.Tag({parameters:['externref']}); + exn = new WebAssembly.Exception(not_js_tag, [obj]); + assertThrowsEquals(() => instance.exports.test(exn), exn); + + + // There is a separate code path for tags with externref type, so also check + // that everything still works when the tag is *not* the JSTag. + + instance = builder.instantiate({"": { + throw_ref: throw_ref, + tag: not_js_tag + }}); + + // Catch and rethrow with explicit wrapping -> not unwrapped in this case. + exn = new WebAssembly.Exception(not_js_tag, [obj]); + assertThrowsEquals(() => instance.exports.test(exn), exn); + // Don't catch with explicit wrapping. + exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); + // TODO(thibaudm): Should the exception get implicitly unwrapped when it + // bubbles up from wasm to JS, even though it was wrapped explicitly? + assertThrowsEquals(() => instance.exports.test(exn), exn); + // Don't catch with implicit wrapping. + assertThrowsEquals(() => instance.exports.test(obj), obj); +})(); diff --git a/deps/v8/test/mjsunit/wasm/exnref.js b/deps/v8/test/mjsunit/wasm/exnref.js index 36dfe701f6d243..401b426d381a62 100644 --- a/deps/v8/test/mjsunit/wasm/exnref.js +++ b/deps/v8/test/mjsunit/wasm/exnref.js @@ -9,7 +9,7 @@ // Tests that are independent of the version of the proposal are not included // (e.g. tests that only use the `throw` instruction), and some exnref-specific // tests are added. -// See also exnref-rethrow.js and exnref-global.js. +// See also exnref-rethrow.js, exnref-global.js and exnref-api.js. d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); From 652fc6e59e0605554960900158a5b053b63e5a82 Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Wed, 10 Apr 2024 19:36:55 +0200 Subject: [PATCH 05/17] deps: V8: cherry-pick cf03d55db2a0 Original commit message: [wasm][exnref] Fix default value for null exnref R=manoskouk@chromium.org Bug: 332081797 Change-Id: Ied777935946c880a78e2011040a4d9ab19a4ddd2 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5444544 Reviewed-by: Manos Koukoutos Commit-Queue: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#93310} Refs: https://github.com/v8/v8/commit/cf03d55db2a0b7c5ff62e08ff5ad52312f6da0b4 --- common.gypi | 2 +- deps/v8/src/wasm/constant-expression-interface.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common.gypi b/common.gypi index b34cb104b34786..a4e92a58ce7536 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.43', + 'v8_embedder_string': '-node.44', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/constant-expression-interface.cc b/deps/v8/src/wasm/constant-expression-interface.cc index 75e6d198df6236..c07070d0fba042 100644 --- a/deps/v8/src/wasm/constant-expression-interface.cc +++ b/deps/v8/src/wasm/constant-expression-interface.cc @@ -202,7 +202,7 @@ WasmValue DefaultValueForType(ValueType type, Isolate* isolate) { case kRefNull: return WasmValue( type == kWasmExternRef || type == kWasmNullExternRef || - type == kWasmExnRef + type == kWasmExnRef || type == kWasmNullExnRef ? Handle::cast(isolate->factory()->null_value()) : Handle::cast(isolate->factory()->wasm_null()), type); From f49efcf58b0e48917f562eebb513f2fb014da770 Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Tue, 16 Apr 2024 17:38:21 +0200 Subject: [PATCH 06/17] deps: V8: cherry-pick b8f91e510e0f Original commit message: [wasm][exnref] Update WA.JSTag semantics According to the last spec updates: - Passing WebAssembly.JSTag to the WebAssembly.Exception constructor is not allowed in JS, - Throwing an exception with the JSTag in wasm is allowed, but the exception should conceptually be "unwrapped" when it exits wasm, and JS should observe the raw externref. Instead, we simply throw the externref in this case, which has the same observable behavior and is consistent with how JSTag has been implemented so far. R=ahaas@chromium.org Bug: 333067164 Change-Id: I6f43df8d254dd7450137d99ff7cc9cbffb697663 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5454404 Reviewed-by: Andreas Haas Commit-Queue: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#93398} Refs: https://github.com/v8/v8/commit/b8f91e510e0f46985b72c7f9afcb0e7fc0659112 --- common.gypi | 2 +- deps/v8/src/runtime/runtime-wasm.cc | 14 ++++-- deps/v8/src/wasm/wasm-js.cc | 5 +++ deps/v8/test/mjsunit/wasm/exceptions-api.js | 9 +--- deps/v8/test/mjsunit/wasm/exnref-api.js | 48 +++++++++++---------- 5 files changed, 43 insertions(+), 35 deletions(-) diff --git a/common.gypi b/common.gypi index a4e92a58ce7536..57ff53d6671879 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.44', + 'v8_embedder_string': '-node.45', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/runtime/runtime-wasm.cc b/deps/v8/src/runtime/runtime-wasm.cc index d13eb0a5ba4b03..f822fec8fb4dba 100644 --- a/deps/v8/src/runtime/runtime-wasm.cc +++ b/deps/v8/src/runtime/runtime-wasm.cc @@ -354,12 +354,18 @@ RUNTIME_FUNCTION(Runtime_WasmThrow) { ClearThreadInWasmScope clear_wasm_flag(isolate); HandleScope scope(isolate); DCHECK_EQ(2, args.length()); - isolate->set_context(GetNativeContextFromWasmInstanceOnStackTop(isolate)); + Tagged context = GetNativeContextFromWasmInstanceOnStackTop(isolate); + isolate->set_context(context); Handle tag(WasmExceptionTag::cast(args[0]), isolate); Handle values(FixedArray::cast(args[1]), isolate); - Handle exception = - WasmExceptionPackage::New(isolate, tag, values); - return isolate->Throw(*exception); + auto js_tag = WasmTagObject::cast(context->wasm_js_tag()); + if (*tag == js_tag->tag()) { + return isolate->Throw(values->get(0)); + } else { + Handle exception = + WasmExceptionPackage::New(isolate, tag, values); + return isolate->Throw(*exception); + } } RUNTIME_FUNCTION(Runtime_WasmReThrow) { diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index 127dbc091cb84a..ababafb42bf8c7 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -2001,6 +2001,11 @@ void WebAssemblyExceptionImpl(const v8::FunctionCallbackInfo& info) { i::Handle::cast(arg0); i::Handle tag( i::WasmExceptionTag::cast(tag_object->tag()), i_isolate); + auto js_tag = i::WasmTagObject::cast(i_isolate->context()->wasm_js_tag()); + if (*tag == js_tag->tag()) { + thrower.TypeError("Argument 0 cannot be WebAssembly.JSTag"); + return; + } uint32_t size = GetEncodedSize(tag_object); i::Handle runtime_exception = i::WasmExceptionPackage::New(i_isolate, tag, size); diff --git a/deps/v8/test/mjsunit/wasm/exceptions-api.js b/deps/v8/test/mjsunit/wasm/exceptions-api.js index 14a0b78a288051..36f48c374c1cdc 100644 --- a/deps/v8/test/mjsunit/wasm/exceptions-api.js +++ b/deps/v8/test/mjsunit/wasm/exceptions-api.js @@ -295,11 +295,11 @@ function TestGetArgHelper(types_str, types, values) { }}); let obj = {}; + // Creating a WA.Exception with the JSTag explicitly is not allowed. + assertThrows(() => new WebAssembly.Exception(WebAssembly.JSTag, [obj]), TypeError); // Catch with implicit wrapping. assertSame(obj, instance.exports.test(obj)); - // Catch with explicit wrapping. - assertSame(obj, instance.exports.test(new WebAssembly.Exception(WebAssembly.JSTag, [obj]))); // Don't catch with explicit wrapping. let not_js_tag = new WebAssembly.Tag({parameters:['externref']}); let exn = new WebAssembly.Exception(not_js_tag, [obj]); @@ -316,11 +316,6 @@ function TestGetArgHelper(types_str, types, values) { // Catch with explicit wrapping. assertSame(obj, instance.exports.test(new WebAssembly.Exception(not_js_tag, [obj]))); - // Don't catch with explicit wrapping. - exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); - // TODO(thibaudm): Should the exception get implicitly unwrapped when it - // bubbles up from wasm to JS, even though it was wrapped explicitly? - assertThrowsEquals(() => instance.exports.test(exn), exn); // Don't catch with implicit wrapping. assertThrowsEquals(() => instance.exports.test(obj), obj); })(); diff --git a/deps/v8/test/mjsunit/wasm/exnref-api.js b/deps/v8/test/mjsunit/wasm/exnref-api.js index cf73379ba7b034..8774ebfaeec4db 100644 --- a/deps/v8/test/mjsunit/wasm/exnref-api.js +++ b/deps/v8/test/mjsunit/wasm/exnref-api.js @@ -41,11 +41,11 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); }}); let obj = {}; + // Creating a WA.Exception with the JSTag explicitly is not allowed. + assertThrows(() => new WebAssembly.Exception(WebAssembly.JSTag, [obj]), TypeError); // Catch with implicit wrapping. assertSame(obj, instance.exports.test(obj)); - // Catch with explicit wrapping. - assertSame(obj, instance.exports.test(new WebAssembly.Exception(WebAssembly.JSTag, [obj]))); // Don't catch with explicit wrapping. let not_js_tag = new WebAssembly.Tag({parameters:['externref']}); let exn = new WebAssembly.Exception(not_js_tag, [obj]); @@ -63,10 +63,6 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); // Catch with explicit wrapping. assertSame(obj, instance.exports.test(new WebAssembly.Exception(not_js_tag, [obj]))); // Don't catch with explicit wrapping. - exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); - // TODO(thibaudm): Should the exception get implicitly unwrapped when it - // bubbles up from wasm to JS, even though it was wrapped explicitly? - assertThrowsEquals(() => instance.exports.test(exn), exn); // Don't catch with implicit wrapping. assertThrowsEquals(() => instance.exports.test(obj), obj); })(); @@ -107,8 +103,6 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); // Catch with implicit wrapping. assertSame(obj, instance.exports.test(obj)); - // Catch with explicit wrapping. - assertSame(obj, instance.exports.test(new WebAssembly.Exception(WebAssembly.JSTag, [obj]))); // Don't catch with explicit wrapping. let not_js_tag = new WebAssembly.Tag({parameters:['externref']}); let exn = new WebAssembly.Exception(not_js_tag, [obj]); @@ -125,11 +119,6 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); // Catch with explicit wrapping. assertSame(obj, instance.exports.test(new WebAssembly.Exception(not_js_tag, [obj]))); - // Don't catch with explicit wrapping. - exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); - // TODO(thibaudm): Should the exception get implicitly unwrapped when it - // bubbles up from wasm to JS, even though it was wrapped explicitly? - assertThrowsEquals(() => instance.exports.test(exn), exn); // Don't catch with implicit wrapping. assertThrowsEquals(() => instance.exports.test(obj), obj); })(); @@ -171,11 +160,6 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); // Catch and rethrown with implicit wrapping. assertThrowsEquals(() => instance.exports.test(obj), obj); - // Catch and rethrown with explicit wrapping. - // TODO: Should the exception get implicitly unwrapped when it - // is rethrown from wasm to JS, even though it was wrapped explicitly? - let exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); - assertThrowsEquals(() => instance.exports.test(exn), exn); // Don't catch with explicit wrapping. let not_js_tag = new WebAssembly.Tag({parameters:['externref']}); exn = new WebAssembly.Exception(not_js_tag, [obj]); @@ -193,11 +177,29 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); // Catch and rethrow with explicit wrapping -> not unwrapped in this case. exn = new WebAssembly.Exception(not_js_tag, [obj]); assertThrowsEquals(() => instance.exports.test(exn), exn); - // Don't catch with explicit wrapping. - exn = new WebAssembly.Exception(WebAssembly.JSTag, [obj]); - // TODO(thibaudm): Should the exception get implicitly unwrapped when it - // bubbles up from wasm to JS, even though it was wrapped explicitly? - assertThrowsEquals(() => instance.exports.test(exn), exn); // Don't catch with implicit wrapping. assertThrowsEquals(() => instance.exports.test(obj), obj); })(); + +(function TestThrowJSTag() { + print(arguments.callee.name); + let builder = new WasmModuleBuilder(); + let js_tag = builder.addImportedTag("", "tag", kSig_v_r); + + // Throw a JS object with WebAssembly.JSTag and check that we can catch + // it as-is from JavaScript. + builder.addFunction("test", kSig_v_r) + .addBody([ + kExprLocalGet, 0, + kExprThrow, js_tag, + ]) + .exportFunc(); + + let instance = builder.instantiate({"": { + tag: WebAssembly.JSTag, + }}); + + let obj = {}; + assertThrowsEquals(() => instance.exports.test(obj), obj); + assertThrowsEquals(() => instance.exports.test(5), 5); +})(); From 696df7edd7bf4ff2e07933ac0b22737e096d9985 Mon Sep 17 00:00:00 2001 From: Jakob Kummerow Date: Tue, 4 Jun 2024 17:04:29 +0200 Subject: [PATCH 07/17] deps: V8: backport 910cb91733dc Original commit message: [wasm][liftoff][arm64] Fix DropExceptionValueAtOffset We cannot exit the iteration early, we must update all entries in the cache state. Fixed: 343748812 Change-Id: I8353acb7bd0edc4b979db92e44d24cb9028fd92b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5596273 Reviewed-by: Clemens Backes Commit-Queue: Clemens Backes Auto-Submit: Jakob Kummerow Commit-Queue: Jakob Kummerow Cr-Commit-Position: refs/heads/main@{#94244} Refs: https://github.com/v8/v8/commit/910cb91733dc --- common.gypi | 2 +- deps/v8/src/wasm/baseline/liftoff-assembler.cc | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/common.gypi b/common.gypi index 57ff53d6671879..72da0b464234fa 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.45', + 'v8_embedder_string': '-node.46', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/baseline/liftoff-assembler.cc b/deps/v8/src/wasm/baseline/liftoff-assembler.cc index 821b6b80495849..e1ca7bebdc8408 100644 --- a/deps/v8/src/wasm/baseline/liftoff-assembler.cc +++ b/deps/v8/src/wasm/baseline/liftoff-assembler.cc @@ -430,12 +430,13 @@ void LiftoffAssembler::DropExceptionValueAtOffset(int offset) { slot != end; ++slot) { *slot = *(slot + 1); stack_offset = NextSpillOffset(slot->kind(), stack_offset); - // Padding could allow us to exit early. - if (slot->offset() == stack_offset) break; - if (slot->is_stack()) { - MoveStackValue(stack_offset, slot->offset(), slot->kind()); + // Padding could cause some spill offsets to remain the same. + if (slot->offset() != stack_offset) { + if (slot->is_stack()) { + MoveStackValue(stack_offset, slot->offset(), slot->kind()); + } + slot->set_offset(stack_offset); } - slot->set_offset(stack_offset); } cache_state_.stack_state.pop_back(); } From 521d704dd2a49873b5a11a7db2a05370c24e9a34 Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Mon, 10 Jun 2024 13:42:09 +0200 Subject: [PATCH 08/17] deps: V8: backport 89dc6eab605c Original commit message: [wasm] Add missing type canonicalization for exceptions JS API When we encode a JS value in a wasm exception, canonicalize the type stored in the tag's signature first. Canonicalize it using the tag's original module by storing the instance on the tag object. R=jkummerow@chromium.org Bug: 346197738 Change-Id: I7575fd79c792d98e4a11c00b466700f0ab82d164 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5613375 Commit-Queue: Thibaud Michaud Reviewed-by: Jakob Kummerow Cr-Commit-Position: refs/heads/main@{#94335} Refs: https://github.com/v8/v8/commit/89dc6eab605c --- common.gypi | 2 +- deps/v8/src/wasm/module-instantiate.cc | 4 +++- deps/v8/src/wasm/wasm-js.cc | 26 +++++++++++++++++++++----- deps/v8/src/wasm/wasm-objects.cc | 4 +++- deps/v8/src/wasm/wasm-objects.h | 3 ++- deps/v8/src/wasm/wasm-objects.tq | 1 + 6 files changed, 31 insertions(+), 9 deletions(-) diff --git a/common.gypi b/common.gypi index 72da0b464234fa..8a1857612e7e86 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.46', + 'v8_embedder_string': '-node.47', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/module-instantiate.cc b/deps/v8/src/wasm/module-instantiate.cc index c74dc117ee21b9..51b9d1e7492444 100644 --- a/deps/v8/src/wasm/module-instantiate.cc +++ b/deps/v8/src/wasm/module-instantiate.cc @@ -2655,8 +2655,10 @@ void InstanceBuilder::ProcessExports( isolate_); uint32_t canonical_sig_index = module_->isorecursive_canonical_type_ids[tag.sig_index]; + Handle instance = + handle(trusted_instance_data->instance_object(), isolate_); wrapper = WasmTagObject::New(isolate_, tag.sig, canonical_sig_index, - tag_object); + tag_object, instance); tags_wrappers_[exp.index] = wrapper; } value = wrapper; diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index ababafb42bf8c7..4e051942c68914 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -1852,7 +1852,8 @@ void WebAssemblyTagImpl(const v8::FunctionCallbackInfo& info) { i::wasm::GetWasmEngine()->type_canonicalizer()->AddRecursiveGroup(&sig); i::Handle tag_object = - i::WasmTagObject::New(i_isolate, &sig, canonical_type_index, tag); + i::WasmTagObject::New(i_isolate, &sig, canonical_type_index, tag, + i_isolate->factory()->undefined_value()); info.GetReturnValue().Set(Utils::ToLocal(tag_object)); } @@ -1898,6 +1899,7 @@ uint32_t GetEncodedSize(i::Handle tag_object) { void EncodeExceptionValues(v8::Isolate* isolate, i::Handle> signature, + i::Handle tag_object, const Local& arg, ErrorThrower* thrower, i::Handle values_out) { Local context = isolate->GetCurrentContext(); @@ -1955,6 +1957,19 @@ void EncodeExceptionValues(v8::Isolate* isolate, case i::wasm::kRefNull: { const char* error_message; i::Handle value_handle = Utils::OpenHandle(*value); + + if (type.has_index()) { + // Canonicalize the type using the tag's original module. + i::Tagged maybe_instance = tag_object->instance(); + CHECK(!i::IsUndefined(maybe_instance)); + auto instance = i::WasmInstanceObject::cast(maybe_instance); + const i::wasm::WasmModule* module = instance->module(); + uint32_t canonical_index = + module->isorecursive_canonical_type_ids[type.ref_index()]; + type = i::wasm::ValueType::RefMaybeNull(canonical_index, + type.nullability()); + } + if (!internal::wasm::JSToWasmObject(i_isolate, value_handle, type, &error_message) .ToHandle(&value_handle)) { @@ -2015,7 +2030,8 @@ void WebAssemblyExceptionImpl(const v8::FunctionCallbackInfo& info) { runtime_exception)); i::Handle> signature( tag_object->serialized_signature(), i_isolate); - EncodeExceptionValues(isolate, signature, info[1], &thrower, values); + EncodeExceptionValues(isolate, signature, tag_object, info[1], &thrower, + values); if (thrower.error()) return; // Third argument: optional ExceptionOption ({traceStack: }). @@ -3231,9 +3247,9 @@ void WasmJs::PrepareForSnapshot(Isolate* isolate) { // Note the canonical_type_index is reset in WasmJs::Install s.t. // type_canonicalizer bookkeeping remains valid. static constexpr uint32_t kInitialCanonicalTypeIndex = 0; - Handle js_tag_object = - WasmTagObject::New(isolate, &kWasmExceptionTagSignature, - kInitialCanonicalTypeIndex, js_tag); + Handle js_tag_object = WasmTagObject::New( + isolate, &kWasmExceptionTagSignature, kInitialCanonicalTypeIndex, + js_tag, isolate->factory()->undefined_value()); native_context->set_wasm_js_tag(*js_tag_object); JSObject::AddProperty(isolate, webassembly, "JSTag", js_tag_object, ro_attributes); diff --git a/deps/v8/src/wasm/wasm-objects.cc b/deps/v8/src/wasm/wasm-objects.cc index 889de39fa5b16f..771fd4dfcfa354 100644 --- a/deps/v8/src/wasm/wasm-objects.cc +++ b/deps/v8/src/wasm/wasm-objects.cc @@ -1785,7 +1785,8 @@ void WasmArray::SetTaggedElement(uint32_t index, Handle value, Handle WasmTagObject::New(Isolate* isolate, const wasm::FunctionSig* sig, uint32_t canonical_type_index, - Handle tag) { + Handle tag, + Handle instance) { Handle tag_cons(isolate->native_context()->wasm_tag_constructor(), isolate); @@ -1806,6 +1807,7 @@ Handle WasmTagObject::New(Isolate* isolate, tag_wrapper->set_serialized_signature(*serialized_sig); tag_wrapper->set_canonical_type_index(canonical_type_index); tag_wrapper->set_tag(*tag); + tag_wrapper->set_instance(*instance); return tag_wrapper; } diff --git a/deps/v8/src/wasm/wasm-objects.h b/deps/v8/src/wasm/wasm-objects.h index 341e97040b69f9..a7495d3cbb394e 100644 --- a/deps/v8/src/wasm/wasm-objects.h +++ b/deps/v8/src/wasm/wasm-objects.h @@ -605,7 +605,8 @@ class WasmTagObject static Handle New(Isolate* isolate, const wasm::FunctionSig* sig, uint32_t canonical_type_index, - Handle tag); + Handle tag, + Handle instance); TQ_OBJECT_CONSTRUCTORS(WasmTagObject) }; diff --git a/deps/v8/src/wasm/wasm-objects.tq b/deps/v8/src/wasm/wasm-objects.tq index dadb0342d08a94..7d937ec308f734 100644 --- a/deps/v8/src/wasm/wasm-objects.tq +++ b/deps/v8/src/wasm/wasm-objects.tq @@ -211,6 +211,7 @@ extern class WasmGlobalObject extends JSObject { extern class WasmTagObject extends JSObject { serialized_signature: PodArrayOfWasmValueType; tag: HeapObject; + instance: WasmInstanceObject|Undefined; canonical_type_index: Smi; } From b8c656002debc4b9d8f13ef1d9639e94bdd2213e Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Wed, 2 Oct 2024 13:02:42 +0200 Subject: [PATCH 09/17] deps: V8: backport 323942700cfe Original commit message: [wasm][exnref] Accept exnref subtypes for throw_ref Only accepting a strict exnref type was incorrect in two cases: - the stack-polymorphic case, with the bottom type - a noexn param R=jkummerow@chromium.org Fixed: 332931390 Change-Id: I80c96a7026f2469e6a3ce54344c2d5e617b78be7 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5904414 Reviewed-by: Jakob Kummerow Commit-Queue: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#96387} Refs: https://github.com/v8/v8/commit/323942700cfe --- common.gypi | 2 +- deps/v8/src/wasm/function-body-decoder-impl.h | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/common.gypi b/common.gypi index 8a1857612e7e86..3aa02c58d72c68 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.47', + 'v8_embedder_string': '-node.48', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/function-body-decoder-impl.h b/deps/v8/src/wasm/function-body-decoder-impl.h index b0aa65983ee6cb..8b49075955a03b 100644 --- a/deps/v8/src/wasm/function-body-decoder-impl.h +++ b/deps/v8/src/wasm/function-body-decoder-impl.h @@ -3306,14 +3306,7 @@ class WasmFullDecoder : public WasmDecoder { DECODE(ThrowRef) { this->detected_->Add(kFeature_exnref); - Value value = Pop(); - if (!VALIDATE( - (value.type.kind() == kRef || value.type.kind() == kRefNull) && - value.type.heap_type() == HeapType::kExn)) { - this->DecodeError("invalid type for throw_ref: expected exnref, found %s", - value.type.name().c_str()); - return 0; - } + Value value = Pop(kWasmExnRef); CALL_INTERFACE_IF_OK_AND_REACHABLE(ThrowRef, &value); MarkMightThrow(); EndControl(); From ef09254d75625345bd0ab9debe4b78a159f5191d Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Wed, 9 Oct 2024 16:02:47 +0200 Subject: [PATCH 10/17] deps: V8: backport 63b8849d73ae Original commit message: [wasm][exnref] Reject non-nullable exnref in JS import/export R=jkummerow@chromium.org Change-Id: I0ba2deb1a9671d87e76fea7bfe76df9eee56442a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5920338 Commit-Queue: Thibaud Michaud Reviewed-by: Jakob Kummerow Cr-Commit-Position: refs/heads/main@{#96489} Refs: https://github.com/v8/v8/commit/63b8849d73ae --- common.gypi | 2 +- deps/v8/src/wasm/wasm-opcodes.cc | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common.gypi b/common.gypi index 3aa02c58d72c68..3cda2a7e61dc26 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.48', + 'v8_embedder_string': '-node.49', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/wasm-opcodes.cc b/deps/v8/src/wasm/wasm-opcodes.cc index b383e0f1ec919f..a4d09e35264376 100644 --- a/deps/v8/src/wasm/wasm-opcodes.cc +++ b/deps/v8/src/wasm/wasm-opcodes.cc @@ -33,12 +33,13 @@ bool IsJSCompatibleSignature(const FunctionSig* sig) { // Rtts are internal-only. They should never be part of a signature. DCHECK(!type.is_rtt()); if (type == kWasmS128) return false; - if (type == kWasmExnRef) return false; if (type.is_object_reference()) { switch (type.heap_representation_non_shared()) { case HeapType::kStringViewWtf8: case HeapType::kStringViewWtf16: case HeapType::kStringViewIter: + case HeapType::kExn: + case HeapType::kNoExn: return false; default: break; From a3e2702058f394f3714031adb91f72a051715f63 Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Wed, 9 Oct 2024 13:19:52 +0200 Subject: [PATCH 11/17] deps: V8: cherry-pick 8e214ec3ec8c Original commit message: [wasm][exnref] Fix catchless try_table If the try_table does not have a catch handler, we don't update the {current_catch_} index or set the {previous_catch} field of the block when we enter it. Therefore also skip the reverse operation when the block ends. R=clemensb@chromium.org Fixed: 372261626 Change-Id: Ib3a23e32f9d0ec153d6a00733d96b52cf040e8bd Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5920086 Commit-Queue: Thibaud Michaud Reviewed-by: Clemens Backes Cr-Commit-Position: refs/heads/main@{#96481} Refs: https://github.com/v8/v8/commit/8e214ec3ec8cdbdb7f34433a48a52420dee19ba6 --- common.gypi | 2 +- deps/v8/src/wasm/function-body-decoder-impl.h | 6 +++++- .../mjsunit/regress/wasm/regress-372261626.js | 21 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-372261626.js diff --git a/common.gypi b/common.gypi index 3cda2a7e61dc26..e9e552df7252a8 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.49', + 'v8_embedder_string': '-node.50', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/function-body-decoder-impl.h b/deps/v8/src/wasm/function-body-decoder-impl.h index 8b49075955a03b..5df75d84d13a1a 100644 --- a/deps/v8/src/wasm/function-body-decoder-impl.h +++ b/deps/v8/src/wasm/function-body-decoder-impl.h @@ -3483,7 +3483,11 @@ class WasmFullDecoder : public WasmDecoder { if (!VALIDATE(TypeCheckOneArmedIf(c))) return 0; } if (c->is_try_table()) { - current_catch_ = c->previous_catch; + // "Pop" the {current_catch_} index. We did not push it if the block has + // no handler, so also skip it here in this case. + if (c->catch_cases.size() > 0) { + current_catch_ = c->previous_catch; + } FallThrough(); // Temporarily set the reachability for the catch handlers, and restore // it before we actually exit the try block. diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-372261626.js b/deps/v8/test/mjsunit/regress/wasm/regress-372261626.js new file mode 100644 index 00000000000000..23f49a64102dff --- /dev/null +++ b/deps/v8/test/mjsunit/regress/wasm/regress-372261626.js @@ -0,0 +1,21 @@ +// Copyright 2024 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --experimental-wasm-exnref + +d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); + +let builder = new WasmModuleBuilder(); +let tag = builder.addTag(kSig_v_v); +builder.addFunction("main", kSig_v_v) + .addBody([ + kExprTry, kWasmVoid, + kExprTryTable, kWasmVoid, 0, + kExprEnd, + kExprThrow, tag, + kExprCatchAll, + kExprEnd + ]).exportFunc(); +let instance = builder.instantiate(); +assertDoesNotThrow(instance.exports.main); From 0374a22d878d61610c5d689b6da5fba0fd1b1bd5 Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Thu, 10 Oct 2024 18:54:04 +0200 Subject: [PATCH 12/17] deps: V8: cherry-pick e7ccf0af1bdd Original commit message: [wasm] Fix default externref/exnref reference - The default nullexternref should be null instead of undefined - The default exnref/nullexnref should be null instead of wasm_null R=mliedtke@chromium.org Fixed: 372285204,372269618 Change-Id: Id5addce2b196f7ba81aac3c2dd9447a91ed2ce2b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5922878 Commit-Queue: Thibaud Michaud Reviewed-by: Matthias Liedtke Cr-Commit-Position: refs/heads/main@{#96531} Refs: https://github.com/v8/v8/commit/e7ccf0af1bdddd20dc58e1790a94739dba0209a3 --- common.gypi | 2 +- deps/v8/src/wasm/wasm-js.cc | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common.gypi b/common.gypi index e9e552df7252a8..19e3cb8b101e61 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.50', + 'v8_embedder_string': '-node.51', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index 4e051942c68914..3b5f71be69ad03 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -1281,9 +1281,12 @@ i::Handle DefaultReferenceValue(i::Isolate* isolate, DCHECK(type.is_object_reference()); // Use undefined for JS type (externref) but null for wasm types as wasm does // not know undefined. - if (type.heap_representation() == i::wasm::HeapType::kExtern || - type.heap_representation() == i::wasm::HeapType::kNoExtern) { + if (type.heap_representation() == i::wasm::HeapType::kExtern) { return isolate->factory()->undefined_value(); + } else if (type.heap_representation() == i::wasm::HeapType::kNoExtern || + type.heap_representation() == i::wasm::HeapType::kExn || + type.heap_representation() == i::wasm::HeapType::kNoExn) { + return isolate->factory()->null_value(); } return isolate->factory()->wasm_null(); } From 6e965c75cfb551ccecf1cadd370d5d4419688c15 Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Wed, 16 Oct 2024 18:28:30 +0200 Subject: [PATCH 13/17] deps: V8: cherry-pick 7cb6188cf913 Original commit message: [wasm][exnref] Accept non-nullable exn catch type R=jkummerow@chromium.org Fixed: 373681572 Change-Id: Iecfc86d2ce6592a6f442bc3504ddde58ff236f64 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5938956 Commit-Queue: Thibaud Michaud Reviewed-by: Jakob Kummerow Cr-Commit-Position: refs/heads/main@{#96637} Refs: https://github.com/v8/v8/commit/7cb6188cf9132d43e6c631befb0584a47a0e7d69 --- common.gypi | 2 +- deps/v8/src/wasm/function-body-decoder-impl.h | 4 ++-- deps/v8/src/wasm/graph-builder-interface.cc | 4 ++-- .../wasm/function-body-decoder-unittest.cc | 13 +++++++++++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/common.gypi b/common.gypi index 19e3cb8b101e61..7bf76ad7048f88 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.51', + 'v8_embedder_string': '-node.52', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/function-body-decoder-impl.h b/deps/v8/src/wasm/function-body-decoder-impl.h index 5df75d84d13a1a..290660104a5936 100644 --- a/deps/v8/src/wasm/function-body-decoder-impl.h +++ b/deps/v8/src/wasm/function-body-decoder-impl.h @@ -3280,7 +3280,7 @@ class WasmFullDecoder : public WasmDecoder { } if (catch_case.kind == kCatchRef || catch_case.kind == kCatchAllRef) { stack_.EnsureMoreCapacity(1, this->zone_); - Push(kWasmExnRef); + Push(ValueType::Ref(HeapType::kExn)); push_count += 1; } Control* target = control_at(catch_case.br_imm.depth); @@ -3506,7 +3506,7 @@ class WasmFullDecoder : public WasmDecoder { } if (catch_case.kind == kCatchRef || catch_case.kind == kCatchAllRef) { stack_.EnsureMoreCapacity(1, this->zone_); - Push(kWasmExnRef); + Push(ValueType::Ref(HeapType::kExn)); push_count += 1; } base::Vector values( diff --git a/deps/v8/src/wasm/graph-builder-interface.cc b/deps/v8/src/wasm/graph-builder-interface.cc index 458d8d859c2ac8..96a9acb34194fc 100644 --- a/deps/v8/src/wasm/graph-builder-interface.cc +++ b/deps/v8/src/wasm/graph-builder-interface.cc @@ -1406,7 +1406,7 @@ class WasmGraphBuildingInterface { if (catch_case.kind == kCatchAll || catch_case.kind == kCatchAllRef) { if (catch_case.kind == kCatchAllRef) { - DCHECK_EQ(values[0].type, kWasmExnRef); + DCHECK_EQ(values[0].type, ValueType::Ref(HeapType::kExn)); values[0].node = block->try_info->exception; } BrOrRet(decoder, catch_case.br_imm.depth); @@ -1473,7 +1473,7 @@ class WasmGraphBuildingInterface { } if (catch_case.kind == kCatchRef) { - DCHECK_EQ(values.last().type, kWasmExnRef); + DCHECK_EQ(values.last().type, ValueType::Ref(HeapType::kExn)); values.last().node = block->try_info->exception; } BrOrRet(decoder, catch_case.br_imm.depth); diff --git a/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc b/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc index 873b855bb4d0bc..2e7979a4e9f662 100644 --- a/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc +++ b/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc @@ -2994,7 +2994,7 @@ TEST_F(FunctionBodyDecoderTest, TryTable) { U32V_1(1), CatchKind::kCatchAllRef, U32V_1(0), kExprEnd, kExprUnreachable, kExprEnd, kExprDrop}, kAppendEnd); - // // Duplicate catch-all. + // Duplicate catch-all. ExpectValidates( sigs.v_v(), {kExprBlock, kExnRefCode, WASM_TRY_TABLE_OP, U32V_1(4), @@ -3002,12 +3002,21 @@ TEST_F(FunctionBodyDecoderTest, TryTable) { CatchKind::kCatchAllRef, U32V_1(0), CatchKind::kCatchAllRef, U32V_1(0), kExprEnd, kExprUnreachable, kExprEnd, kExprDrop}, kAppendEnd); - // // Catch-all before catch. + // Catch-all before catch. ExpectValidates( sigs.v_v(), {WASM_TRY_TABLE_OP, U32V_1(2), CatchKind::kCatchAll, U32V_1(0), CatchKind::kCatch, ex, U32V_1(0), kExprEnd, kExprUnreachable}, kAppendEnd); + // Non-nullable exnref. + ValueType kNonNullableExnRef = ValueType::Ref(HeapType::kExn); + auto sig = FixedSizeSignature::Returns(kNonNullableExnRef); + uint8_t sig_id = builder.AddSignature(&sig); + ExpectValidates( + sigs.v_v(), + {kExprBlock, sig_id, WASM_TRY_TABLE_OP, U32V_1(1), CatchKind::kCatchRef, + ex, U32V_1(0), kExprEnd, kExprUnreachable, kExprEnd, kExprDrop}, + kAppendEnd); constexpr uint8_t kInvalidCatchKind = kLastCatchKind + 1; ExpectFailure(sigs.v_v(), From ffa9627d50e2698862eb88ac88033f0030d179b5 Mon Sep 17 00:00:00 2001 From: Clemens Backes Date: Wed, 16 Oct 2024 13:16:03 +0200 Subject: [PATCH 14/17] deps: V8: cherry-pick b96e40d5ac85 Original commit message: [wasm][js-api] Fix exception handling in Exception Calling `Get` on the third argument can throw. If so, return immediately. R=thibaudm@chromium.org Fixed: 372993873 Change-Id: I70ec0d0421833a60151f6bcdc9c386f6ad864256 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5937803 Reviewed-by: Thibaud Michaud Commit-Queue: Clemens Backes Cr-Commit-Position: refs/heads/main@{#96627} Refs: https://github.com/v8/v8/commit/b96e40d5ac85272cd08d3adc0dc98b9ddbe1249a --- common.gypi | 2 +- deps/v8/src/wasm/wasm-js.cc | 9 +++++---- .../test/mjsunit/regress/wasm/regress-372993873.js | 12 ++++++++++++ 3 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-372993873.js diff --git a/common.gypi b/common.gypi index 7bf76ad7048f88..4d8ca7cca7fe45 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.52', + 'v8_embedder_string': '-node.53', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index 3b5f71be69ad03..261ec7da170c53 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -2046,11 +2046,12 @@ void WebAssemblyExceptionImpl(const v8::FunctionCallbackInfo& info) { Local context = isolate->GetCurrentContext(); Local trace_stack_obj = Local::Cast(info[2]); Local trace_stack_key = v8_str(isolate, "traceStack"); - v8::MaybeLocal maybe_trace_stack = - trace_stack_obj->Get(context, trace_stack_key); v8::Local trace_stack_value; - if (maybe_trace_stack.ToLocal(&trace_stack_value) && - trace_stack_value->BooleanValue(isolate)) { + if (!trace_stack_obj->Get(context, trace_stack_key) + .ToLocal(&trace_stack_value)) { + return; + } + if (trace_stack_value->BooleanValue(isolate)) { auto caller = Utils::OpenHandle(*info.NewTarget()); i::Handle capture_result; diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-372993873.js b/deps/v8/test/mjsunit/regress/wasm/regress-372993873.js new file mode 100644 index 00000000000000..b216191872f784 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/wasm/regress-372993873.js @@ -0,0 +1,12 @@ +// Copyright 2024 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +let tag = new WebAssembly.Tag({'parameters': []}); +let proxy = new Proxy({}, { + 'get': () => { + throw new Error('boom') + } +}); + +assertThrows(() => new WebAssembly.Exception(tag, [], proxy), Error, 'boom'); From 746b4c97b492c01fc70f1cf74eac7774a2069364 Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Wed, 23 Oct 2024 15:27:44 +0200 Subject: [PATCH 15/17] deps: V8: backport 9997fc013952 Original commit message: [wasm][exnref] Use wasm_null for exnref A JS null caught in wasm as an exnref with catch_(all_)ref should be observably different from a null exnref: a JS null should behave like a regular JS exception with null as the externref package, while a null exnref is the actual null value for this type. In particular, a JS null exception can be rethrown while a null exnref cannot. Represent null exnrefs with wasm_null instead of JS null to avoid the confusion. R=jkummerow@chromium.org Fixed: 374790906 Change-Id: If9f16a24407ee7d1399613255c3f14e0a6ebef9e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/5953226 Reviewed-by: Jakob Kummerow Commit-Queue: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#96782} Refs: https://github.com/v8/v8/commit/9997fc013952 --- common.gypi | 2 +- deps/v8/src/builtins/wasm.tq | 7 +- .../turboshaft/wasm-lowering-reducer.h | 14 +- deps/v8/src/compiler/wasm-compiler.cc | 12 +- deps/v8/src/compiler/wasm-compiler.h | 1 + deps/v8/src/compiler/wasm-gc-lowering.cc | 10 +- deps/v8/src/wasm/baseline/liftoff-compiler.cc | 15 +-- .../src/wasm/constant-expression-interface.cc | 6 +- deps/v8/src/wasm/constant-expression.cc | 3 +- deps/v8/src/wasm/graph-builder-interface.cc | 2 +- deps/v8/src/wasm/wasm-builtin-list.h | 1 + deps/v8/test/mjsunit/wasm/gc-casts-exnref.js | 126 ++++++++++++------ 12 files changed, 118 insertions(+), 81 deletions(-) diff --git a/common.gypi b/common.gypi index 4d8ca7cca7fe45..3ce183146a0b28 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.53', + 'v8_embedder_string': '-node.54', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/builtins/wasm.tq b/deps/v8/src/builtins/wasm.tq index 2317066b742547..ae034ce9622035 100644 --- a/deps/v8/src/builtins/wasm.tq +++ b/deps/v8/src/builtins/wasm.tq @@ -373,7 +373,12 @@ builtin WasmThrow(tag: Object, values: FixedArray): JSAny { } builtin WasmRethrow(exception: Object): JSAny { - if (exception == Null) tail ThrowWasmTrapRethrowNull(); + dcheck(exception != kWasmNull); + tail runtime::WasmReThrow(LoadContextFromFrame(), exception); +} + +builtin WasmThrowRef(exception: Object): JSAny { + if (exception == kWasmNull) tail ThrowWasmTrapRethrowNull(); tail runtime::WasmReThrow(LoadContextFromFrame(), exception); } diff --git a/deps/v8/src/compiler/turboshaft/wasm-lowering-reducer.h b/deps/v8/src/compiler/turboshaft/wasm-lowering-reducer.h index dc255c01fc6160..4c38825c507b13 100644 --- a/deps/v8/src/compiler/turboshaft/wasm-lowering-reducer.h +++ b/deps/v8/src/compiler/turboshaft/wasm-lowering-reducer.h @@ -46,8 +46,7 @@ class WasmLoweringReducer : public Next { #if V8_STATIC_ROOTS_BOOL // TODO(14616): Extend this for shared types. const bool is_wasm_null = - !wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_) && - !wasm::IsSubtypeOf(type, wasm::kWasmExnRef, module_); + !wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_); OpIndex null_value = __ UintPtrConstant(is_wasm_null ? StaticReadOnlyRoot::kWasmNull : StaticReadOnlyRoot::kNullValue); @@ -68,8 +67,7 @@ class WasmLoweringReducer : public Next { // (3) the object might be a JS object. if (null_check_strategy_ == NullCheckStrategy::kExplicit || wasm::IsSubtypeOf(wasm::kWasmI31Ref.AsNonNull(), type, module_) || - wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_) || - wasm::IsSubtypeOf(type, wasm::kWasmExnRef, module_)) { + wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_)) { __ TrapIf(__ IsNull(object, type), OpIndex::Invalid(), trap_id); } else { // Otherwise, load the word after the map word. @@ -919,11 +917,9 @@ class WasmLoweringReducer : public Next { OpIndex Null(wasm::ValueType type) { OpIndex roots = __ LoadRootRegister(); - RootIndex index = - wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_) || - wasm::IsSubtypeOf(type, wasm::kWasmExnRef, module_) - ? RootIndex::kNullValue - : RootIndex::kWasmNull; + RootIndex index = wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_) + ? RootIndex::kNullValue + : RootIndex::kWasmNull; // We load WasmNull as a pointer here and not as a TaggedPointer because // WasmNull is stored uncompressed in the IsolateData, and a load of a // TaggedPointer loads compressed pointers. We do not bitcast the WasmNull diff --git a/deps/v8/src/compiler/wasm-compiler.cc b/deps/v8/src/compiler/wasm-compiler.cc index 14bc728ba5a7e8..bd3dd3b27bb9ee 100644 --- a/deps/v8/src/compiler/wasm-compiler.cc +++ b/deps/v8/src/compiler/wasm-compiler.cc @@ -391,10 +391,8 @@ Node* WasmGraphBuilder::EffectPhi(unsigned count, Node** effects_and_control) { Node* WasmGraphBuilder::RefNull(wasm::ValueType type) { // We immediately lower null in wrappers, as they do not go through a lowering // phase. - // TODO(thibaudm): Can we use wasm null for exnref? return parameter_mode_ == kInstanceParameterMode ? gasm_->Null(type) - : (type == wasm::kWasmExternRef || type == wasm::kWasmNullExternRef || - type == wasm::kWasmExnRef || type == wasm::kWasmNullExnRef) + : (type == wasm::kWasmExternRef || type == wasm::kWasmNullExternRef) ? LOAD_ROOT(NullValue, null_value) : LOAD_ROOT(WasmNull, wasm_null); } @@ -2372,6 +2370,14 @@ Node* WasmGraphBuilder::Rethrow(Node* except_obj) { Builtin::kWasmRethrow, Operator::kNoProperties, except_obj); } +Node* WasmGraphBuilder::ThrowRef(Node* except_obj) { + // TODO(v8:8091): Currently the message of the original exception is not being + // preserved when rethrown to the console. The pending message will need to be + // saved when caught and restored here while being rethrown. + return gasm_->CallBuiltinThroughJumptable( + Builtin::kWasmThrowRef, Operator::kNoProperties, except_obj); +} + Node* WasmGraphBuilder::IsExceptionTagUndefined(Node* tag) { return gasm_->TaggedEqual(tag, UndefinedValue()); } diff --git a/deps/v8/src/compiler/wasm-compiler.h b/deps/v8/src/compiler/wasm-compiler.h index fcff46c449768a..352051898264c2 100644 --- a/deps/v8/src/compiler/wasm-compiler.h +++ b/deps/v8/src/compiler/wasm-compiler.h @@ -233,6 +233,7 @@ class WasmGraphBuilder { const base::Vector values, wasm::WasmCodePosition position); Node* Rethrow(Node* except_obj); + Node* ThrowRef(Node* except_obj); Node* IsExceptionTagUndefined(Node* tag); Node* LoadJSTag(); Node* ExceptionTagEqual(Node* caught_tag, Node* expected_tag); diff --git a/deps/v8/src/compiler/wasm-gc-lowering.cc b/deps/v8/src/compiler/wasm-gc-lowering.cc index 647059daf21e78..b99e4b1d4617f1 100644 --- a/deps/v8/src/compiler/wasm-gc-lowering.cc +++ b/deps/v8/src/compiler/wasm-gc-lowering.cc @@ -95,9 +95,7 @@ Reduction WasmGCLowering::Reduce(Node* node) { } Node* WasmGCLowering::Null(wasm::ValueType type) { - // TODO(thibaudm): Can we use wasm null for exnref? - RootIndex index = wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_) || - wasm::IsSubtypeOf(type, wasm::kWasmExnRef, module_) + RootIndex index = wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_) ? RootIndex::kNullValue : RootIndex::kWasmNull; return gasm_.LoadImmutable(MachineType::Pointer(), gasm_.LoadRootRegister(), @@ -108,8 +106,7 @@ Node* WasmGCLowering::IsNull(Node* object, wasm::ValueType type) { #if V8_STATIC_ROOTS_BOOL // TODO(14616): Extend this for shared types. const bool is_wasm_null = - !wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_) && - !wasm::IsSubtypeOf(type, wasm::kWasmExnRef, module_); + !wasm::IsSubtypeOf(type, wasm::kWasmExternRef, module_); Node* null_value = gasm_.UintPtrConstant(is_wasm_null ? StaticReadOnlyRoot::kWasmNull : StaticReadOnlyRoot::kNullValue); @@ -488,8 +485,7 @@ Reduction WasmGCLowering::ReduceAssertNotNull(Node* node) { if (null_check_strategy_ == NullCheckStrategy::kExplicit || wasm::IsSubtypeOf(wasm::kWasmI31Ref.AsNonNull(), op_parameter.type, module_) || - wasm::IsSubtypeOf(op_parameter.type, wasm::kWasmExternRef, module_) || - wasm::IsSubtypeOf(op_parameter.type, wasm::kWasmExnRef, module_)) { + wasm::IsSubtypeOf(op_parameter.type, wasm::kWasmExternRef, module_)) { gasm_.TrapIf(IsNull(object, op_parameter.type), op_parameter.trap_id); UpdateSourcePosition(gasm_.effect(), node); } else { diff --git a/deps/v8/src/wasm/baseline/liftoff-compiler.cc b/deps/v8/src/wasm/baseline/liftoff-compiler.cc index d14057b88a8748..f0238c2c5fec81 100644 --- a/deps/v8/src/wasm/baseline/liftoff-compiler.cc +++ b/deps/v8/src/wasm/baseline/liftoff-compiler.cc @@ -931,8 +931,7 @@ class LiftoffCompiler { ValueType type = decoder->local_types_[local_index]; if (type.is_reference()) { __ Spill(__ cache_state()->stack_state[local_index].offset(), - IsSubtypeOf(type, kWasmExternRef, decoder->module_) || - IsSubtypeOf(type, kWasmExnRef, decoder->module_) + IsSubtypeOf(type, kWasmExternRef, decoder->module_) ? LiftoffRegister(null_ref_reg) : LiftoffRegister(wasm_null_ref_reg), type.kind()); @@ -1668,7 +1667,7 @@ class LiftoffCompiler { void ThrowRef(FullDecoder* decoder, Value*) { // Like Rethrow, but pops the exception from the stack. VarState exn = __ PopVarState(); - CallBuiltin(Builtin::kWasmRethrow, MakeSig::Params(kRef), {exn}, + CallBuiltin(Builtin::kWasmThrowRef, MakeSig::Params(kRef), {exn}, decoder->position()); int pc_offset = __ pc_offset(); MaybeOSR(); @@ -2622,8 +2621,7 @@ class LiftoffCompiler { LiftoffRegister obj = pinned.set(__ PopToRegister(pinned)); if (null_check_strategy_ == compiler::NullCheckStrategy::kExplicit || IsSubtypeOf(kWasmI31Ref.AsNonNull(), arg.type, decoder->module_) || - IsSubtypeOf(arg.type, kWasmExternRef, decoder->module_) || - IsSubtypeOf(arg.type, kWasmExnRef, decoder->module_)) { + IsSubtypeOf(arg.type, kWasmExternRef, decoder->module_)) { // Use an explicit null check if // (1) we cannot use trap handler or // (2) the object might be a Smi or @@ -8253,11 +8251,9 @@ class LiftoffCompiler { } void LoadNullValue(Register null, ValueType type) { - // TODO(thibaudm): Can we use wasm null for exnref? __ LoadFullPointer( null, kRootRegister, - type == kWasmExternRef || type == kWasmNullExternRef || - type == kWasmExnRef || type == kWasmNullExnRef + type == kWasmExternRef || type == kWasmNullExternRef ? IsolateData::root_slot_offset(RootIndex::kNullValue) : IsolateData::root_slot_offset(RootIndex::kWasmNull)); } @@ -8270,8 +8266,7 @@ class LiftoffCompiler { ValueType type) { #if V8_STATIC_ROOTS_BOOL // TODO(14616): Extend this for shared types. - bool is_wasm_null = type != kWasmExternRef && type != kWasmNullExternRef && - type != kWasmExnRef && type != kWasmNullExnRef; + bool is_wasm_null = type != kWasmExternRef && type != kWasmNullExternRef; uint32_t value = is_wasm_null ? StaticReadOnlyRoot::kWasmNull : StaticReadOnlyRoot::kNullValue; __ LoadConstant(LiftoffRegister(null), diff --git a/deps/v8/src/wasm/constant-expression-interface.cc b/deps/v8/src/wasm/constant-expression-interface.cc index c07070d0fba042..da2db6744a6348 100644 --- a/deps/v8/src/wasm/constant-expression-interface.cc +++ b/deps/v8/src/wasm/constant-expression-interface.cc @@ -105,8 +105,7 @@ void ConstantExpressionInterface::RefNull(FullDecoder* decoder, ValueType type, Value* result) { if (!generate_value()) return; result->runtime_value = - WasmValue((IsSubtypeOf(type, kWasmExternRef, decoder->module_) || - IsSubtypeOf(type, kWasmExnRef, decoder->module_)) + WasmValue(IsSubtypeOf(type, kWasmExternRef, decoder->module_) ? Handle::cast(isolate_->factory()->null_value()) : Handle::cast(isolate_->factory()->wasm_null()), type); @@ -201,8 +200,7 @@ WasmValue DefaultValueForType(ValueType type, Isolate* isolate) { return WasmValue(Simd128()); case kRefNull: return WasmValue( - type == kWasmExternRef || type == kWasmNullExternRef || - type == kWasmExnRef || type == kWasmNullExnRef + type == kWasmExternRef || type == kWasmNullExternRef ? Handle::cast(isolate->factory()->null_value()) : Handle::cast(isolate->factory()->wasm_null()), type); diff --git a/deps/v8/src/wasm/constant-expression.cc b/deps/v8/src/wasm/constant-expression.cc index f78517ffeb4615..046ceedaa07c57 100644 --- a/deps/v8/src/wasm/constant-expression.cc +++ b/deps/v8/src/wasm/constant-expression.cc @@ -36,8 +36,7 @@ ValueOrError EvaluateConstantExpression( return WasmValue(expr.i32_value()); case ConstantExpression::kRefNull: return WasmValue( - expected == kWasmExternRef || expected == kWasmNullExternRef || - expected == kWasmNullExnRef || expected == kWasmExnRef + expected == kWasmExternRef || expected == kWasmNullExternRef ? Handle::cast(isolate->factory()->null_value()) : Handle::cast(isolate->factory()->wasm_null()), ValueType::RefNull(expr.repr())); diff --git a/deps/v8/src/wasm/graph-builder-interface.cc b/deps/v8/src/wasm/graph-builder-interface.cc index 96a9acb34194fc..0e98427f07a144 100644 --- a/deps/v8/src/wasm/graph-builder-interface.cc +++ b/deps/v8/src/wasm/graph-builder-interface.cc @@ -2799,7 +2799,7 @@ class WasmGraphBuildingInterface { void ThrowRef(FullDecoder* decoder, TFNode* exception) { DCHECK_NOT_NULL(exception); - CheckForException(decoder, builder_->Rethrow(exception), false); + CheckForException(decoder, builder_->ThrowRef(exception), false); builder_->TerminateThrow(effect(), control()); } }; diff --git a/deps/v8/src/wasm/wasm-builtin-list.h b/deps/v8/src/wasm/wasm-builtin-list.h index 15b8754bb4ace3..1d976b5b012dff 100644 --- a/deps/v8/src/wasm/wasm-builtin-list.h +++ b/deps/v8/src/wasm/wasm-builtin-list.h @@ -51,6 +51,7 @@ namespace v8::internal::wasm { V(WasmAllocateFixedArray) \ V(WasmThrow) \ V(WasmRethrow) \ + V(WasmThrowRef) \ V(WasmRethrowExplicitContext) \ V(WasmTraceEnter) \ V(WasmTraceExit) \ diff --git a/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js b/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js index ba1f30a4dee26c..632d3a6e0aa7ae 100644 --- a/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js +++ b/deps/v8/test/mjsunit/wasm/gc-casts-exnref.js @@ -117,32 +117,72 @@ let helper = (function () { kExprThrowRef]) .exportFunc(); + builder.addFunction('nullCastToExnRef', kSig_v_v) + .addLocals(kWasmExnRef, 1) + .addBody([ + kExprLocalGet, 0, + kGCPrefix, kExprRefCast, kExnRefCode, + kExprThrowRef]) + .exportFunc(); + builder.addFunction('nullCastToNullExnRef', kSig_v_v) + .addLocals(kWasmExnRef, 1) + .addBody([ + kExprLocalGet, 0, + kGCPrefix, kExprRefCast, kNullExnRefCode, + kExprDrop]) + .exportFunc(); + builder.addFunction('nullCastNullToExnRef', kSig_v_v) + .addLocals(kWasmExnRef, 1) + .addBody([ + kExprLocalGet, 0, + kGCPrefix, kExprRefCastNull, kExnRefCode, + kExprThrowRef]) + .exportFunc(); + builder.addFunction('nullCastNullToNullExnRef', kSig_v_v) + .addLocals(kWasmExnRef, 1) + .addBody([ + kExprLocalGet, 0, + kGCPrefix, kExprRefCastNull, kNullExnRefCode, + kGCPrefix, kExprRefCastNull, kExnRefCode, + kExprThrowRef]) + .exportFunc(); + let instance = builder.instantiate({m: {to_exnref: helper.exports.to_exnref}}); let wasm = instance.exports; - let exnRef = getExnRef(); - assertTraps(kTrapIllegalCast, () => wasm.castToExnRef(null)); - assertThrowsEquals(() => wasm.castToExnRef(exnRef), exnRef); - assertTraps(kTrapIllegalCast, () => wasm.castToNullExnRef(null)); - assertTraps(kTrapIllegalCast, () => wasm.castToNullExnRef(exnRef)); + let obj = {}; + assertTraps(kTrapIllegalCast, wasm.nullCastToExnRef); + assertThrowsEquals(() => wasm.castToExnRef(obj), obj); + assertTraps(kTrapIllegalCast, wasm.nullCastToNullExnRef); + assertTraps(kTrapIllegalCast, () => wasm.castToNullExnRef(obj)); - assertThrows(() => wasm.castNullToExnRef(null), Error, /rethrowing null value/); - assertThrowsEquals(() => wasm.castNullToExnRef(exnRef), exnRef); - assertThrows(() => wasm.castNullToNullExnRef(null), Error, /rethrowing null value/); - assertTraps(kTrapIllegalCast, () => wasm.castNullToNullExnRef(exnRef)); + assertThrows(wasm.nullCastNullToExnRef, Error, /rethrowing null value/); + assertThrowsEquals(() => wasm.castNullToExnRef(obj), obj); + assertThrows(wasm.nullCastNullToNullExnRef, Error, /rethrowing null value/); + assertTraps(kTrapIllegalCast, () => wasm.castNullToNullExnRef(obj)); })(); (function BrOnCastExnRef() { print(arguments.callee.name); let builder = new WasmModuleBuilder(); - let to_exnref = builder.addImport('m', 'to_exnref', makeSig([kWasmExternRef], [kWasmExnRef])); + let get_exnref = builder.addImport('m', 'get_exnref', makeSig([], [kWasmExnRef])); + let get_exnref_if = builder.addFunction('getExnRefOrNull', + makeSig([kWasmI32], [kWasmExnRef])) + .addBody([ + kExprLocalGet, 0, + kExprIf, kExnRefCode, + kExprCallFunction, get_exnref, + kExprElse, + kExprRefNull, kExnRefCode, + kExprEnd, + ]).index; builder.addFunction('castToExnRef', - makeSig([kWasmExternRef], [kWasmI32])) + makeSig([kWasmI32], [kWasmI32])) .addBody([ kExprBlock, kWasmRef, kExnRefCode, kExprLocalGet, 0, - kExprCallFunction, to_exnref, + kExprCallFunction, get_exnref_if, ...wasmBrOnCast( 0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmExnRef)), kExprI32Const, 0, @@ -154,11 +194,11 @@ let helper = (function () { ]) .exportFunc(); builder.addFunction('castToNullExnRef', - makeSig([kWasmExternRef], [kWasmI32])) + makeSig([kWasmI32], [kWasmI32])) .addBody([ kExprBlock, kWasmRef, kNullExnRefCode, kExprLocalGet, 0, - kExprCallFunction, to_exnref, + kExprCallFunction, get_exnref_if, ...wasmBrOnCast( 0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmNullExnRef)), kExprI32Const, 0, @@ -171,11 +211,11 @@ let helper = (function () { .exportFunc(); builder.addFunction('castNullToExnRef', - makeSig([kWasmExternRef], [kWasmI32])) + makeSig([kWasmI32], [kWasmI32])) .addBody([ kExprBlock, kWasmRefNull, kExnRefCode, kExprLocalGet, 0, - kExprCallFunction, to_exnref, + kExprCallFunction, get_exnref_if, ...wasmBrOnCast(0, wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmExnRef)), kExprI32Const, 0, @@ -187,11 +227,11 @@ let helper = (function () { ]) .exportFunc(); builder.addFunction('castNullToNullExnRef', - makeSig([kWasmExternRef], [kWasmI32])) + makeSig([kWasmI32], [kWasmI32])) .addBody([ kExprBlock, kWasmRefNull, kNullExnRefCode, kExprLocalGet, 0, - kExprCallFunction, to_exnref, + kExprCallFunction, get_exnref_if, ...wasmBrOnCast(0, wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmNullExnRef)), kExprI32Const, 0, @@ -204,11 +244,11 @@ let helper = (function () { .exportFunc(); builder.addFunction('castFailToExnRef', - makeSig([kWasmExternRef], [kWasmI32])) + makeSig([kWasmI32], [kWasmI32])) .addBody([ kExprBlock, kWasmRefNull, kExnRefCode, kExprLocalGet, 0, - kExprCallFunction, to_exnref, + kExprCallFunction, get_exnref_if, ...wasmBrOnCastFail(0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmExnRef)), kExprI32Const, 0, @@ -220,11 +260,11 @@ let helper = (function () { ]) .exportFunc(); builder.addFunction('castFailToNullExnRef', - makeSig([kWasmExternRef], [kWasmI32])) + makeSig([kWasmI32], [kWasmI32])) .addBody([ kExprBlock, kWasmRefNull, kExnRefCode, kExprLocalGet, 0, - kExprCallFunction, to_exnref, + kExprCallFunction, get_exnref_if, ...wasmBrOnCastFail(0, wasmRefNullType(kWasmExnRef), wasmRefType(kWasmNullExnRef)), kExprI32Const, 0, @@ -237,11 +277,11 @@ let helper = (function () { .exportFunc(); builder.addFunction('castFailNullToExnRef', - makeSig([kWasmExternRef], [kWasmI32])) + makeSig([kWasmI32], [kWasmI32])) .addBody([ kExprBlock, kWasmRef, kExnRefCode, kExprLocalGet, 0, - kExprCallFunction, to_exnref, + kExprCallFunction, get_exnref_if, ...wasmBrOnCastFail(0, wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmExnRef)), kExprI32Const, 0, @@ -253,11 +293,11 @@ let helper = (function () { ]) .exportFunc(); builder.addFunction('castFailNullToNullExnRef', - makeSig([kWasmExternRef], [kWasmI32])) + makeSig([kWasmI32], [kWasmI32])) .addBody([ kExprBlock, kWasmRef, kExnRefCode, kExprLocalGet, 0, - kExprCallFunction, to_exnref, + kExprCallFunction, get_exnref_if, ...wasmBrOnCastFail(0, wasmRefNullType(kWasmExnRef), wasmRefNullType(kWasmNullExnRef)), kExprI32Const, 0, @@ -269,31 +309,31 @@ let helper = (function () { ]) .exportFunc(); - let instance = builder.instantiate({m: {to_exnref: helper.exports.to_exnref}}); + let instance = builder.instantiate({m: {get_exnref: helper.exports.get_exnref}}); let wasm = instance.exports; let exnRef = getExnRef(); - assertEquals(0, wasm.castToExnRef(null)); - assertEquals(1, wasm.castToExnRef(exnRef)); + assertEquals(0, wasm.castToExnRef(0)); + assertEquals(1, wasm.castToExnRef(1)); - assertEquals(0, wasm.castToNullExnRef(null)); - assertEquals(0, wasm.castToNullExnRef(exnRef)); + assertEquals(0, wasm.castToNullExnRef(0)); + assertEquals(0, wasm.castToNullExnRef(1)); - assertEquals(1, wasm.castNullToExnRef(null)); - assertEquals(1, wasm.castNullToExnRef(exnRef)); + assertEquals(1, wasm.castNullToExnRef(0)); + assertEquals(1, wasm.castNullToExnRef(1)); - assertEquals(1, wasm.castNullToNullExnRef(null)); - assertEquals(0, wasm.castNullToNullExnRef(exnRef)); + assertEquals(1, wasm.castNullToNullExnRef(0)); + assertEquals(0, wasm.castNullToNullExnRef(1)); - assertEquals(1, wasm.castFailToExnRef(null)); - assertEquals(0, wasm.castFailToExnRef(exnRef)); + assertEquals(1, wasm.castFailToExnRef(0)); + assertEquals(0, wasm.castFailToExnRef(1)); - assertEquals(1, wasm.castFailToNullExnRef(null)); - assertEquals(1, wasm.castFailToNullExnRef(exnRef)); + assertEquals(1, wasm.castFailToNullExnRef(0)); + assertEquals(1, wasm.castFailToNullExnRef(1)); - assertEquals(0, wasm.castFailNullToExnRef(null)); - assertEquals(0, wasm.castFailNullToExnRef(exnRef)); + assertEquals(0, wasm.castFailNullToExnRef(0)); + assertEquals(0, wasm.castFailNullToExnRef(1)); - assertEquals(0, wasm.castFailNullToNullExnRef(null)); - assertEquals(1, wasm.castFailNullToNullExnRef(exnRef)); + assertEquals(0, wasm.castFailNullToNullExnRef(0)); + assertEquals(1, wasm.castFailNullToNullExnRef(1)); })(); From ff4b2c73425d14f6773f72a7e4c78eb913c82e5f Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Mon, 10 Feb 2025 14:52:15 +0100 Subject: [PATCH 16/17] deps: V8: backport 1b27e4674f11 Original commit message: [wasm] Disallow v128 in exception handling JS API R=jkummerow@chromium.org Fixed: 395214627 Change-Id: Ief84b0fd79a87e539dfbfed31d475926f0f0a288 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6249317 Reviewed-by: Jakob Kummerow Commit-Queue: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#98608} Refs: https://github.com/v8/v8/commit/1b27e4674f11 --- common.gypi | 2 +- deps/v8/src/wasm/wasm-js.cc | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/common.gypi b/common.gypi index 3ce183146a0b28..6f5312afc0a850 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.54', + 'v8_embedder_string': '-node.55', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index 261ec7da170c53..3330aae4888ad6 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -1982,12 +1982,14 @@ void EncodeExceptionValues(v8::Isolate* isolate, values_out->set(index++, *value_handle); break; } + case i::wasm::kS128: + thrower->TypeError("Invalid type v128"); + return; case i::wasm::kRtt: case i::wasm::kI8: case i::wasm::kI16: case i::wasm::kVoid: case i::wasm::kBottom: - case i::wasm::kS128: UNREACHABLE(); } } @@ -2799,12 +2801,14 @@ void WebAssemblyExceptionGetArgImpl( return WasmObjectToJSReturnValue(return_value, obj, signature->get(index), i_isolate, &thrower); } + case i::wasm::kS128: + thrower.TypeError("Invalid type v128"); + return; case i::wasm::kRtt: case i::wasm::kI8: case i::wasm::kI16: case i::wasm::kVoid: case i::wasm::kBottom: - case i::wasm::kS128: UNREACHABLE(); } info.GetReturnValue().Set(result); From 37e2c4c0e85d64c8945fb7b57f2cdf0427a9d6ed Mon Sep 17 00:00:00 2001 From: Thibaud Michaud Date: Tue, 18 Mar 2025 11:00:32 +0100 Subject: [PATCH 17/17] deps: V8: backport 85b390089e51 Original commit message: [wasm][eh] Fix getArg() when exception has an S128 We cannot read an S128 exception value from JS, but we can read a value at a higher index in the exception. So accept S128 values when we compute the encoded index. R=mliedtke@chromium.org Fixed: 403675482 Change-Id: I7cc0238310863b6d579fcbe0a216ddce6f760c8b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6367014 Reviewed-by: Matthias Liedtke Commit-Queue: Thibaud Michaud Cr-Commit-Position: refs/heads/main@{#99305} Refs: https://github.com/v8/v8/commit/85b390089e51 --- common.gypi | 2 +- deps/v8/src/wasm/wasm-js.cc | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common.gypi b/common.gypi index 6f5312afc0a850..0ffa5b13719515 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.55', + 'v8_embedder_string': '-node.56', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/wasm/wasm-js.cc b/deps/v8/src/wasm/wasm-js.cc index 3330aae4888ad6..35f34db216a5b1 100644 --- a/deps/v8/src/wasm/wasm-js.cc +++ b/deps/v8/src/wasm/wasm-js.cc @@ -2754,12 +2754,14 @@ void WebAssemblyExceptionGetArgImpl( case i::wasm::kRefNull: decode_index++; break; + case i::wasm::kS128: + decode_index += 8; + break; case i::wasm::kRtt: case i::wasm::kI8: case i::wasm::kI16: case i::wasm::kVoid: case i::wasm::kBottom: - case i::wasm::kS128: UNREACHABLE(); } }