Skip to content

Commit 7506e06

Browse files
thibaudmichaudCommit Bot
authored andcommitted
[codegen] Skip invalid optimization in tail calls
Preparing for tail call is usually done by emitting the gap moves and then moving the stack pointer to its new position. An optimization consists in moving the stack pointer first and transforming some of the moves into pushes. In the attached case it looks like this (arm): 138 add sp, sp, #40 13c str r6, [sp, #-4]! 140 str r6, [sp, #-4]! 144 str r6, [sp, #-4]! 148 str r6, [sp, #-4]! 14c str r6, [sp, #-4]! ... 160 vldr d1, [sp - 4*3] The last line is a gap reload, but because the stack pointer was already moved, the slot is now below the stack pointer. This is invalid and triggers this DCHECK: Fatal error in ../../v8/src/codegen/arm/assembler-arm.cc, line 402 Debug check failed: 0 <= offset (0 vs. -12). A comment already explains that we skip the optimization if the gap contains stack moves to prevent this, but the code only checks for non-FP slots. This is fixed by replacing "source.IsStackSlot()" with "source.IsAnyStackSlot()": 108 vldr d1, [sp + 4*2] ... 118 str r0, [sp, #+36] 11c str r0, [sp, #+32] 120 str r0, [sp, #+28] 124 str r0, [sp, #+24] 128 str r0, [sp, #+20] ... 134 add sp, sp, #20 [email protected] Bug: chromium:1137608 Change-Id: If2b85dde49bf31a6bd3f5e0255407f9390727f9d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2474784 Reviewed-by: Jakob Gruber <[email protected]> Commit-Queue: Thibaud Michaud <[email protected]> Cr-Commit-Position: refs/heads/master@{#70603}
1 parent 853c17a commit 7506e06

2 files changed

Lines changed: 48 additions & 2 deletions

File tree

src/compiler/backend/code-generator.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,8 +615,8 @@ void CodeGenerator::GetPushCompatibleMoves(Instruction* instr,
615615
// then the full gap resolver must be used since optimization with
616616
// pushes don't participate in the parallel move and might clobber
617617
// values needed for the gap resolve.
618-
if (source.IsStackSlot() && LocationOperand::cast(source).index() >=
619-
first_push_compatible_index) {
618+
if (source.IsAnyStackSlot() && LocationOperand::cast(source).index() >=
619+
first_push_compatible_index) {
620620
pushes->clear();
621621
return;
622622
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2020 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
//
5+
// Flags: --no-liftoff --experimental-wasm-return-call --experimental-wasm-threads
6+
7+
load("test/mjsunit/wasm/wasm-module-builder.js");
8+
9+
(function Regress1137608() {
10+
print(arguments.callee.name);
11+
let builder = new WasmModuleBuilder();
12+
let sig0 = builder.addType(kSig_i_iii);
13+
let sig1 = builder.addType(makeSig([kWasmF64, kWasmF64, kWasmI32,
14+
kWasmI32, kWasmI32, kWasmF32, kWasmI32, kWasmF64, kWasmI32, kWasmF32,
15+
kWasmI32, kWasmF32, kWasmI32, kWasmF64, kWasmI32], [kWasmI32]));
16+
let main = builder.addFunction("main", sig0)
17+
.addBody([
18+
kExprI64Const, 0,
19+
kExprF64UConvertI64,
20+
kExprF64Const, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00,
21+
kExprF64Const, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
22+
kExprF64Mul,
23+
kExprI32Const, 0,
24+
kExprF64Const, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25+
kExprF64StoreMem, 0x00, 0xb0, 0xe0, 0xc0, 0x81, 0x03,
26+
kExprI32Const, 0,
27+
kExprI32Const, 0,
28+
kExprI32Const, 0,
29+
kExprF32Const, 0x00, 0x00, 0x00, 0x00,
30+
kExprI32Const, 0,
31+
kExprF64Const, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32+
kExprI32Const, 0,
33+
kExprF32Const, 0x00, 0x00, 0x00, 0x00,
34+
kExprI32Const, 0,
35+
kExprF32Const, 0x00, 0x00, 0x00, 0x00,
36+
kExprI32Const, 0,
37+
kExprF64Const, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38+
kExprI32Const, 0,
39+
kExprI32Const, 2,
40+
kExprReturnCallIndirect, sig1, kTableZero]).exportFunc();
41+
builder.addFunction("f", sig1).addBody([kExprI32Const, 0]);
42+
builder.addTable(kWasmAnyFunc, 4, 4);
43+
builder.addMemory(16, 32, false, true);
44+
let module = new WebAssembly.Module(builder.toBuffer());
45+
let instance = new WebAssembly.Instance(module);
46+
})();

0 commit comments

Comments
 (0)