diff --git a/common.gypi b/common.gypi index 45850e0f8de97e..6d49200da370e3 100644 --- a/common.gypi +++ b/common.gypi @@ -36,7 +36,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/baseline/liftoff-assembler.cc b/deps/v8/src/wasm/baseline/liftoff-assembler.cc index 923d375064c924..c505cf7e6d17ef 100644 --- a/deps/v8/src/wasm/baseline/liftoff-assembler.cc +++ b/deps/v8/src/wasm/baseline/liftoff-assembler.cc @@ -37,6 +37,7 @@ class StackTransferRecipe { struct RegisterLoad { enum LoadKind : uint8_t { + kNop, // no-op, used for high fp of a fp pair. kConstant, // load a constant value into a register. kStack, // fill a register from a stack slot. kLowHalfStack, // fill a register from the low half of a stack slot. @@ -63,6 +64,10 @@ class StackTransferRecipe { return {half == kLowWord ? kLowHalfStack : kHighHalfStack, kWasmI32, offset}; } + static RegisterLoad Nop() { + // ValueType does not matter. + return {kNop, kWasmI32, 0}; + } private: RegisterLoad(LoadKind kind, ValueType type, int32_t value) @@ -217,11 +222,11 @@ class StackTransferRecipe { RegisterLoad::HalfStack(stack_offset, kHighWord); } else if (dst.is_fp_pair()) { DCHECK_EQ(kWasmS128, type); - // load_dst_regs_.set above will set both low and high fp regs. - // But unlike gp_pair, we load a kWasm128 in one go in ExecuteLoads. - // So unset the top fp register to skip loading it. - load_dst_regs_.clear(dst.high()); + // Only need register_load for low_gp since we load 128 bits at one go. + // Both low and high need to be set in load_dst_regs_ but when iterating + // over it, both low and high will be cleared, so we won't load twice. *register_load(dst.low()) = RegisterLoad::Stack(stack_offset, type); + *register_load(dst.high()) = RegisterLoad::Nop(); } else { *register_load(dst) = RegisterLoad::Stack(stack_offset, type); } @@ -318,6 +323,8 @@ class StackTransferRecipe { for (LiftoffRegister dst : load_dst_regs_) { RegisterLoad* load = register_load(dst); switch (load->kind) { + case RegisterLoad::kNop: + break; case RegisterLoad::kConstant: asm_->LoadConstant(dst, load->type == kWasmI64 ? WasmValue(int64_t{load->value}) diff --git a/deps/v8/test/mjsunit/regress/wasm/regress-1161654.js b/deps/v8/test/mjsunit/regress/wasm/regress-1161654.js new file mode 100644 index 00000000000000..93f2c3b556fc55 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/wasm/regress-1161654.js @@ -0,0 +1,56 @@ +// Copyright 2021 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: --wasm-staging + +// This is a fuzzer-generated test case that exposed a bug in Liftoff that only +// affects ARM, where the fp register aliasing is different from other archs. +// We were inncorrectly clearing the the high fp register in a LiftoffRegList +// indicating registers to load, hitting a DCHECK. +load('test/mjsunit/wasm/wasm-module-builder.js'); + +const builder = new WasmModuleBuilder(); +builder.addMemory(19, 32, false); +builder.addGlobal(kWasmI32, 0); +builder.addType(makeSig([], [])); +builder.addType(makeSig([kWasmI64, kWasmS128, kWasmF32], [kWasmI32])); +// Generate function 1 (out of 5). +builder.addFunction(undefined, 0 /* sig */) + .addBodyWithEnd([ +// signature: v_v +// body: +kExprI32Const, 0x05, // i32.const +kExprReturn, // return +kExprUnreachable, // unreachable +kExprEnd, // end @5 +]); +// Generate function 4 (out of 5). +builder.addFunction(undefined, 1 /* sig */) + .addBodyWithEnd([ +// signature: i_lsf +// body: +kExprLocalGet, 0x01, // local.get +kExprLocalGet, 0x01, // local.get +kExprGlobalGet, 0x00, // global.get +kExprDrop, // drop +kExprLoop, kWasmStmt, // loop @8 + kExprLoop, 0x00, // loop @10 + kExprI32Const, 0x01, // i32.const + kExprMemoryGrow, 0x00, // memory.grow + kExprI64LoadMem8U, 0x00, 0x70, // i64.load8_u + kExprLoop, 0x00, // loop @19 + kExprCallFunction, 0x00, // call function #0: v_v + kExprEnd, // end @23 + kExprI64Const, 0xf1, 0x24, // i64.const + kExprGlobalGet, 0x00, // global.get + kExprDrop, // drop + kExprBr, 0x00, // br depth=0 + kExprEnd, // end @32 + kExprEnd, // end @33 +kExprI32Const, 0x5b, // i32.const +kExprReturn, // return +kExprEnd, // end @37 +]); +// Instantiation is enough to cause a crash. +const instance = builder.instantiate();