[wasm][generic-wrapper] Fix number of parameters popped off the stack
In the generic wrapper we popped the wrong number of parameters off the stack. We always popped the number of parameters needed by the generic wrapper, according to the signature. The correct number though is max(parameters provide, parameters needed). R=victorgomes@chromium.org, thibaudm@chromium.org CC=vkont@google.com Bug: v8:10982 Change-Id: If9b8d4dbe093eb6df08ddf9f3594d5c60b9be33f Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2558317 Commit-Queue: Andreas Haas <ahaas@chromium.org> Reviewed-by: Thibaud Michaud <thibaudm@chromium.org> Reviewed-by: Victor Gomes <victorgomes@chromium.org> Cr-Commit-Position: refs/heads/master@{#71406}
This commit is contained in:
parent
7f15f3e7ad
commit
73a35c3555
@ -2995,7 +2995,11 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
|
||||
constexpr int kFrameMarkerOffset = -kSystemPointerSize;
|
||||
constexpr int kGCScanSlotCountOffset =
|
||||
kFrameMarkerOffset - kSystemPointerSize;
|
||||
constexpr int kParamCountOffset = kGCScanSlotCountOffset - kSystemPointerSize;
|
||||
// The number of parameters passed to this function.
|
||||
constexpr int kInParamCountOffset =
|
||||
kGCScanSlotCountOffset - kSystemPointerSize;
|
||||
// The number of parameters according to the signature.
|
||||
constexpr int kParamCountOffset = kInParamCountOffset - kSystemPointerSize;
|
||||
constexpr int kReturnCountOffset = kParamCountOffset - kSystemPointerSize;
|
||||
constexpr int kValueTypesArrayStartOffset =
|
||||
kReturnCountOffset - kSystemPointerSize;
|
||||
@ -3004,8 +3008,13 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
|
||||
constexpr int kFunctionDataOffset =
|
||||
kValueTypesArrayStartOffset - kSystemPointerSize;
|
||||
constexpr int kLastSpillOffset = kFunctionDataOffset;
|
||||
constexpr int kNumSpillSlots = 5;
|
||||
constexpr int kNumSpillSlots = 6;
|
||||
__ subq(rsp, Immediate(kNumSpillSlots * kSystemPointerSize));
|
||||
// Put the in_parameter count on the stack, we only need it at the very end
|
||||
// when we pop the parameters off the stack.
|
||||
Register in_param_count = rax;
|
||||
__ movq(MemOperand(rbp, kInParamCountOffset), in_param_count);
|
||||
in_param_count = no_reg;
|
||||
|
||||
// -------------------------------------------
|
||||
// Load the Wasm exported function data and the Wasm instance.
|
||||
@ -3158,20 +3167,19 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
|
||||
// We will loop through the params starting with the 1st param.
|
||||
// The order of processing the params is important. We have to evaluate them
|
||||
// in an increasing order.
|
||||
// Not reversed Reversed
|
||||
// +-----------------+------+-----------------+---------------
|
||||
// | receiver | | param n |
|
||||
// |- - - - - - - - -| |- - - - - - - - -|
|
||||
// | param 1 | | param n-1 | Caller
|
||||
// | ... | | ... | frame slots
|
||||
// | param n-1 | | param 1 |
|
||||
// |- - - - - - - - -| |- - - - - - - - -|
|
||||
// | param n | | receiver |
|
||||
// -+-----------------+------+-----------------+---------------
|
||||
// | return addr | | return addr |
|
||||
// |- - - - - - - - -|<-FP->|- - - - - - - - -|
|
||||
// | rbp | | rbp | Spill slots
|
||||
// |- - - - - - - - -| |- - - - - - - - -|
|
||||
// +-----------------+---------------
|
||||
// | param n |
|
||||
// |- - - - - - - - -|
|
||||
// | param n-1 | Caller
|
||||
// | ... | frame slots
|
||||
// | param 1 |
|
||||
// |- - - - - - - - -|
|
||||
// | receiver |
|
||||
// +-----------------+---------------
|
||||
// | return addr |
|
||||
// FP->|- - - - - - - - -|
|
||||
// | rbp | Spill slots
|
||||
// |- - - - - - - - -|
|
||||
//
|
||||
// [rbp + current_param] gives us the parameter we are processing.
|
||||
// We iterate through half-open interval <1st param, [rbp + param_limit]).
|
||||
@ -3456,6 +3464,13 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
|
||||
__ bind(&return_done);
|
||||
__ movq(param_count, MemOperand(rbp, kParamCountOffset));
|
||||
|
||||
// Calculate the number of parameters we have to pop off the stack. This
|
||||
// number is max(in_param_count, param_count).
|
||||
in_param_count = rdx;
|
||||
__ movq(in_param_count, MemOperand(rbp, kInParamCountOffset));
|
||||
__ cmpq(param_count, in_param_count);
|
||||
__ cmovq(less, param_count, in_param_count);
|
||||
|
||||
// -------------------------------------------
|
||||
// Deconstrunct the stack frame.
|
||||
// -------------------------------------------
|
||||
@ -3471,6 +3486,9 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) {
|
||||
Register return_addr = rbx;
|
||||
__ popq(return_addr);
|
||||
Register caller_frame_slots_count = param_count;
|
||||
// Add one to also pop the receiver. The receiver is passed to a JSFunction
|
||||
// over the stack but is neither included in the number of parameters passed
|
||||
// to this function nor in the number of parameters expected in this function.
|
||||
__ addq(caller_frame_slots_count, Immediate(1));
|
||||
__ shlq(caller_frame_slots_count, Immediate(kSystemPointerSizeLog2));
|
||||
__ addq(rsp, caller_frame_slots_count);
|
||||
|
@ -762,3 +762,28 @@ let kSig_f_iiliiiffddlifffdi = makeSig([kWasmI32, kWasmI32, kWasmI64, kWasmI32,
|
||||
let instance = builder.instantiate();
|
||||
assertEquals(15, instance.exports.f1());
|
||||
})();
|
||||
|
||||
(function testDeoptWithIncorrectNumberOfParams() {
|
||||
print(arguments.callee.name);
|
||||
const builder = new WasmModuleBuilder();
|
||||
let sig_index = builder.addType(kSig_v_ii);
|
||||
let imp = builder.addImport('q', 'func', sig_index);
|
||||
builder.addFunction('main', sig_index)
|
||||
.addBody([kExprLocalGet, 0, kExprLocalGet, 1, kExprCallFunction, imp])
|
||||
.exportAs('main');
|
||||
|
||||
function deopt() {
|
||||
%DeoptimizeFunction(caller);
|
||||
}
|
||||
|
||||
let main = builder.instantiate({q: {func: deopt}}).exports.main;
|
||||
function caller() {
|
||||
main(1, 2, 3, 4, 5);
|
||||
main(1, 2, 3, 4);
|
||||
main(1, 2, 3);
|
||||
main(1, 2);
|
||||
main(1);
|
||||
main();
|
||||
}
|
||||
caller();
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user