diff --git a/src/wasm/baseline/arm/liftoff-assembler-arm.h b/src/wasm/baseline/arm/liftoff-assembler-arm.h index d05779cdca..31afd35f76 100644 --- a/src/wasm/baseline/arm/liftoff-assembler-arm.h +++ b/src/wasm/baseline/arm/liftoff-assembler-arm.h @@ -1906,6 +1906,16 @@ bool LiftoffAssembler::emit_i64_popcnt(LiftoffRegister dst, } void LiftoffAssembler::IncrementSmi(LiftoffRegister dst, int offset) { + if (!is_int12(offset)) { + // For large offsets, ldr/str will need a scratch register, but we need + // the single available scratch register here. So fold the offset into the + // base address. + // Note: if we ever want to use this function for callers that don't want + // {dst} to get clobbered, we could spill it to the stack and restore it + // later. + add(dst.gp(), dst.gp(), Operand(offset)); + offset = 0; + } UseScratchRegisterScope temps(this); Register scratch = temps.Acquire(); ldr(scratch, MemOperand(dst.gp(), offset)); diff --git a/src/wasm/baseline/liftoff-assembler.h b/src/wasm/baseline/liftoff-assembler.h index 6a4a92d8e1..32e8a3098b 100644 --- a/src/wasm/baseline/liftoff-assembler.h +++ b/src/wasm/baseline/liftoff-assembler.h @@ -803,6 +803,7 @@ class LiftoffAssembler : public TurboAssembler { emit_i32_sari(dst.gp(), dst.gp(), kSmiTagSize); } } + // Warning: may clobber {dst} on some architectures! inline void IncrementSmi(LiftoffRegister dst, int offset); inline void Load(LiftoffRegister dst, Register src_addr, Register offset_reg, uintptr_t offset_imm, LoadType type, diff --git a/src/wasm/baseline/liftoff-compiler.cc b/src/wasm/baseline/liftoff-compiler.cc index 7e72cd83f0..5f3ac28cc5 100644 --- a/src/wasm/baseline/liftoff-compiler.cc +++ b/src/wasm/baseline/liftoff-compiler.cc @@ -7023,6 +7023,7 @@ class LiftoffCompiler { __ IncrementSmi(vector, wasm::ObjectAccess::ElementOffsetInTaggedFixedArray( static_cast(vector_slot))); + // Warning: {vector} may be clobbered by {IncrementSmi}! } // A direct call within this module just gets the current instance. __ PrepareCall(&sig, call_descriptor); diff --git a/test/mjsunit/regress/wasm/regress-13118.js b/test/mjsunit/regress/wasm/regress-13118.js new file mode 100644 index 0000000000..6ff050cc57 --- /dev/null +++ b/test/mjsunit/regress/wasm/regress-13118.js @@ -0,0 +1,19 @@ +// Copyright 2022 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. + +d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); + +let builder = new WasmModuleBuilder(); + +let callee = builder.addFunction('callee', kSig_v_v).addBody([kExprNop]); + +let body = []; +for (let i = 0; i < 600; i++) { + body.push(kExprCallFunction, callee.index); +} + +builder.addFunction('main', kSig_v_v).exportFunc().addBody(body); + +let instance = builder.instantiate(); +instance.exports.main();