[compiler] Don't iterate past end of StateValuesAccess iterator

StateValuesAccess iterates over actual (non-adapted) arguments, thus
we must be careful not to iterate past their end when handling rest
args and advancing through the initial non-rest-args.

Tbr: neis@chromium.org
Bug: chromium:1167709,chromium:1166136
Change-Id: If506050a5518f394e0dcdbf39840b99923d4cbae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2637213
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72145}
This commit is contained in:
Jakob Gruber 2021-01-19 09:48:49 +01:00 committed by Commit Bot
parent 722050d8cd
commit 47135e0368
3 changed files with 61 additions and 21 deletions

View File

@ -3876,28 +3876,32 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
frame_state = outer_state;
}
// Add the actual parameters to the {node}, skipping the receiver.
Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
StateValuesAccess parameters_access(parameters);
auto parameters_it = ++parameters_access.begin(); // Skip the receiver.
for (int i = 0; i < start_index; i++) {
// A non-zero start_index implies that there are rest arguments. Skip them.
++parameters_it;
const int argument_count =
FrameStateInfoOf(frame_state->op()).parameter_count() -
1; // Minus receiver.
if (start_index < argument_count) {
Node* const parameters = frame_state->InputAt(kFrameStateParametersInput);
StateValuesAccess parameters_access(parameters);
auto parameters_it = ++parameters_access.begin(); // Skip the receiver.
for (int i = 0; i < start_index; i++) {
// A non-zero start_index implies that there are rest arguments. Skip
// them.
++parameters_it;
}
for (int i = start_index; i < argument_count; ++i, ++parameters_it) {
Node* parameter_node = parameters_it.node();
DCHECK_NOT_NULL(parameter_node);
node->InsertInput(graph()->zone(),
JSCallOrConstructNode::ArgumentIndex(argc++),
parameter_node);
}
// TODO(jgruber): Currently, each use-site does the awkward dance above,
// iterating based on the FrameStateInfo's parameter count minus one, and
// manually advancing the iterator past the receiver. Consider wrapping all
// this in an understandable iterator s.t. one only needs to iterate from
// the beginning until done().
DCHECK(parameters_it.done());
}
int argument_count = FrameStateInfoOf(frame_state->op()).parameter_count() -
1; // Minus receiver.
for (int i = start_index; i < argument_count; ++i, ++parameters_it) {
Node* parameter_node = parameters_it.node();
DCHECK_NOT_NULL(parameter_node);
node->InsertInput(graph()->zone(),
JSCallOrConstructNode::ArgumentIndex(argc++),
parameter_node);
}
// TODO(jgruber): Currently, each use-site does the awkward dance above,
// iterating based on the FrameStateInfo's parameter count minus one, and
// manually advancing the iterator past the receiver. Consider wrapping all
// this in an understandable iterator s.t. one only needs to iterate from the
// beginning until done().
DCHECK(parameters_it.done());
if (IsCallWithArrayLikeOrSpread(node)) {
NodeProperties::ChangeOp(

View File

@ -0,0 +1,18 @@
// 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: --allow-natives-syntax --no-lazy-feedback-allocation
function __f_0() {
}
function __f_3( __v_7, ...__v_8) {
return __f_0( ...__v_8);
}
function __f_5() {
__f_3();
}
%PrepareFunctionForOptimization(__f_5);
__f_5();
%OptimizeFunctionOnNextCall(__f_5);
__f_5();

View File

@ -0,0 +1,18 @@
// 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: --allow-natives-syntax --no-lazy-feedback-allocation
function __f_0() {
}
function __f_3( __v_7, ...__v_8) {
return new __f_0( ...__v_8);
}
function __f_5() {
__f_3();
}
%PrepareFunctionForOptimization(__f_5);
__f_5();
%OptimizeFunctionOnNextCall(__f_5);
__f_5();