Commit 9fe6b543 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[deoptimizer] More consistent semantics of height for all frame types

Information required for deoptimization is passed from codegen to the
deoptimizer through so-called translations. Translations contain,
among many other things, a 'height' field. It is used during deopts to
calculate the unoptimized frame height (but note that it does not
correspond exactly to the frame height itself - further calculations
on the deopt side are needed to get to the real frame height).

The height field has roughly the following data flow:

1. During codegen, we serialize whatever
FrameStateDescriptor::GetHeight() returns.
2. During deopts, serialized translations are converted into
TranslatedFrame objects in TranslatedState::CreateNextTranslatedFrame.
3. These are later used to arrive at the real frame height in multiple
spots, e.g. in DoComputeInterpretedFrame and friends.

Prior to this CL, we were adding and subtracting 1 in basically random
spots. For example, for interpreted and construct stub frames we added
1 in step 1 and subtracted 1 in step 3. For continuation frames, we
added 1 in step 2 and subtracted it in step 3. Argument adaptor frames
were left untouched.

This CL removes all these +-1's. The height field now contains
locals_count() for interpreted frames, and parameters_count() for
everything else. I also tried to make the meaning of adds/subs clearer
through use of named constants like kTheReceiver.

Bug: v8:9534
Change-Id: I6fd26886ff5aa63930f413d879d5480578d9dc7e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1751724Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarMichael Stanton <mvstanton@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63238}
parent 0645b26a
......@@ -1019,23 +1019,22 @@ FrameStateDescriptor::FrameStateDescriptor(
outer_state_(outer_state) {}
size_t FrameStateDescriptor::GetHeight() const {
// TODO(jgruber): Unify how the height is handled. Currently, we seem to add
// and subtract 1 at random spots. For example, for interpreted functions we
// add 1 here, and subtract it in DoComputeInterpretedFrame. For builtin
// continuation frames, we add 1 in CreateNextTranslatedFrame, and subtract
// it in DoComputeBuiltinContinuation. Arguments adaptor frames thread through
// the height unmodified.
// Handling in all these cases should ideally be consistent and use named
// constants.
switch (type()) {
case FrameStateType::kInterpretedFunction:
return locals_count() + 1; // +1 for the accumulator.
case FrameStateType::kConstructStub:
return parameters_count() + 1; // +1 for the context.
case FrameStateType::kArgumentsAdaptor:
return locals_count(); // The accumulator is *not* included.
case FrameStateType::kBuiltinContinuation:
// Custom, non-JS calling convention (that does not have a notion of
// a receiver or context).
return parameters_count();
case FrameStateType::kArgumentsAdaptor:
case FrameStateType::kConstructStub:
case FrameStateType::kJavaScriptBuiltinContinuation:
case FrameStateType::kJavaScriptBuiltinContinuationWithCatch:
// JS linkage. The parameters count
// - includes the receiver (input 1 in CreateArtificialFrameState, and
// passed as part of stack parameters to
// CreateJavaScriptBuiltinContinuationFrameState), and
// - does *not* include the context.
return parameters_count();
}
UNREACHABLE();
......
......@@ -190,11 +190,13 @@ Node* CreateJavaScriptBuiltinContinuationFrameState(
actual_parameters.push_back(stack_parameters[i]);
}
// Register parameters follow stack paraemters. The context will be added by
Node* new_target = jsgraph->UndefinedConstant();
// Register parameters follow stack parameters. The context will be added by
// instruction selector during FrameState translation.
actual_parameters.push_back(target);
actual_parameters.push_back(jsgraph->UndefinedConstant());
actual_parameters.push_back(argc);
actual_parameters.push_back(target); // kJavaScriptCallTargetRegister
actual_parameters.push_back(new_target); // kJavaScriptCallNewTargetRegister
actual_parameters.push_back(argc); // kJavaScriptCallArgCountRegister
return CreateBuiltinContinuationFrameStateCommon(
jsgraph,
......
......@@ -5655,10 +5655,14 @@ Node* JSCallReducer::CreateArtificialFrameState(
bailout_id, OutputFrameStateCombine::Ignore(), state_info);
const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
Node* node0 = graph()->NewNode(op0);
static constexpr int kTargetInputIndex = 0;
static constexpr int kReceiverInputIndex = 1;
const int parameter_count_with_receiver = parameter_count + 1;
std::vector<Node*> params;
params.reserve(parameter_count + 1);
for (int parameter = 0; parameter < parameter_count + 1; ++parameter) {
params.push_back(node->InputAt(1 + parameter));
params.reserve(parameter_count_with_receiver);
for (int i = 0; i < parameter_count_with_receiver; i++) {
params.push_back(node->InputAt(kReceiverInputIndex + i));
}
const Operator* op_param = common()->StateValues(
static_cast<int>(params.size()), SparseInputMask::Dense());
......@@ -5668,7 +5672,7 @@ Node* JSCallReducer::CreateArtificialFrameState(
context = jsgraph()->UndefinedConstant();
}
return graph()->NewNode(op, params_node, node0, node0, context,
node->InputAt(0), outer_frame_state);
node->InputAt(kTargetInputIndex), outer_frame_state);
}
Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
......
......@@ -247,9 +247,13 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
bailout_id, OutputFrameStateCombine::Ignore(), state_info);
const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
Node* node0 = graph()->NewNode(op0);
static constexpr int kTargetInputIndex = 0;
static constexpr int kReceiverInputIndex = 1;
const int parameter_count_with_receiver = parameter_count + 1;
NodeVector params(local_zone_);
for (int parameter = 0; parameter < parameter_count + 1; ++parameter) {
params.push_back(node->InputAt(1 + parameter));
for (int i = 0; i < parameter_count_with_receiver; i++) {
params.push_back(node->InputAt(kReceiverInputIndex + i));
}
const Operator* op_param = common()->StateValues(
static_cast<int>(params.size()), SparseInputMask::Dense());
......@@ -259,7 +263,7 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
context = jsgraph()->UndefinedConstant();
}
return graph()->NewNode(op, params_node, node0, node0, context,
node->InputAt(0), outer_frame_state);
node->InputAt(kTargetInputIndex), outer_frame_state);
}
namespace {
......
This diff is collapsed.
......@@ -172,7 +172,14 @@ class TranslatedFrame {
Kind kind() const { return kind_; }
BailoutId node_id() const { return node_id_; }
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
// TODO(jgruber): Simplify/clarify the semantics of this field. The name
// `height` is slightly misleading. Yes, this value is related to stack frame
// height, but must undergo additional mutations to arrive at the real stack
// frame height (e.g.: addition/subtraction of context, accumulator, fixed
// frame sizes, padding).
int height() const { return height_; }
int return_value_offset() const { return return_value_offset_; }
int return_value_count() const { return return_value_count_; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment