[wasm][tail-call] Fix CanTailCall check
The CanTailCall check only passes if the return locations are the same in the caller and the callee. However, stack returns are expected to be at a different offset depending on the stack space reserved for parameters. R=clemensb@chromium.org Bug: v8:7431 Change-Id: Iaac15fce889d6cd7d1ac88f320a872202281fb5a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2289789 Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Commit-Queue: Thibaud Michaud <thibaudm@chromium.org> Cr-Commit-Position: refs/heads/master@{#68933}
This commit is contained in:
parent
9df54e0767
commit
69553feaab
@ -125,10 +125,18 @@ int CallDescriptor::GetTaggedParameterSlots() const {
|
||||
|
||||
bool CallDescriptor::CanTailCall(const CallDescriptor* callee) const {
|
||||
if (ReturnCount() != callee->ReturnCount()) return false;
|
||||
const int stack_param_delta = callee->GetStackParameterDelta(this);
|
||||
for (size_t i = 0; i < ReturnCount(); ++i) {
|
||||
if (!LinkageLocation::IsSameLocation(GetReturnLocation(i),
|
||||
callee->GetReturnLocation(i)))
|
||||
if (GetReturnLocation(i).IsCallerFrameSlot() &&
|
||||
callee->GetReturnLocation(i).IsCallerFrameSlot()) {
|
||||
if (GetReturnLocation(i).AsCallerFrameSlot() - stack_param_delta !=
|
||||
callee->GetReturnLocation(i).AsCallerFrameSlot()) {
|
||||
return false;
|
||||
}
|
||||
} else if (!LinkageLocation::IsSameLocation(GetReturnLocation(i),
|
||||
callee->GetReturnLocation(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -159,3 +159,46 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
print(" --right--");
|
||||
assertEquals(3, module.exports.main(0, -2, 3));
|
||||
})();
|
||||
|
||||
(function TestMultiReturnCallWithLongSig() {
|
||||
print(arguments.callee.name);
|
||||
const callee_inputs = 10;
|
||||
// Tail call from a function with less, as many, or more parameters than the
|
||||
// callee.
|
||||
for (caller_inputs = 9; caller_inputs <= 11; ++caller_inputs) {
|
||||
let builder = new WasmModuleBuilder();
|
||||
|
||||
// f just returns its arguments in reverse order.
|
||||
const f_params = new Array(callee_inputs).fill(kWasmI32);
|
||||
const f_returns = f_params;
|
||||
const f_sig = builder.addType(makeSig(f_params, f_returns));
|
||||
let f_body = [];
|
||||
for (i = 0; i < callee_inputs; ++i) {
|
||||
f_body.push(kExprLocalGet, callee_inputs - i - 1);
|
||||
}
|
||||
const f = builder.addFunction("f", f_sig).addBody(f_body);
|
||||
|
||||
// Slice or pad the caller inputs to match the callee.
|
||||
const main_params = new Array(caller_inputs).fill(kWasmI32);
|
||||
const main_sig = builder.addType(makeSig(main_params, f_returns));
|
||||
let main_body = [];
|
||||
for (i = 0; i < callee_inputs; ++i) {
|
||||
main_body.push(kExprLocalGet, Math.min(caller_inputs - 1, i));
|
||||
}
|
||||
main_body.push(kExprReturnCall, f.index);
|
||||
builder.addFunction("main", main_sig).addBody(main_body).exportFunc();
|
||||
|
||||
let module = builder.instantiate();
|
||||
|
||||
inputs = [];
|
||||
for (i = 0; i < caller_inputs; ++i) {
|
||||
inputs.push(i);
|
||||
}
|
||||
let expect = inputs.slice(0, callee_inputs);
|
||||
while (expect.length < callee_inputs) {
|
||||
expect.push(inputs[inputs.length - 1]);
|
||||
}
|
||||
expect.reverse();
|
||||
assertEquals(expect, module.exports.main(...inputs));
|
||||
}
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user