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( ...@@ -1019,23 +1019,22 @@ FrameStateDescriptor::FrameStateDescriptor(
outer_state_(outer_state) {} outer_state_(outer_state) {}
size_t FrameStateDescriptor::GetHeight() const { 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()) { switch (type()) {
case FrameStateType::kInterpretedFunction: case FrameStateType::kInterpretedFunction:
return locals_count() + 1; // +1 for the accumulator. return locals_count(); // The accumulator is *not* included.
case FrameStateType::kConstructStub:
return parameters_count() + 1; // +1 for the context.
case FrameStateType::kArgumentsAdaptor:
case FrameStateType::kBuiltinContinuation: 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::kJavaScriptBuiltinContinuation:
case FrameStateType::kJavaScriptBuiltinContinuationWithCatch: 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(); return parameters_count();
} }
UNREACHABLE(); UNREACHABLE();
......
...@@ -190,11 +190,13 @@ Node* CreateJavaScriptBuiltinContinuationFrameState( ...@@ -190,11 +190,13 @@ Node* CreateJavaScriptBuiltinContinuationFrameState(
actual_parameters.push_back(stack_parameters[i]); 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. // instruction selector during FrameState translation.
actual_parameters.push_back(target); actual_parameters.push_back(target); // kJavaScriptCallTargetRegister
actual_parameters.push_back(jsgraph->UndefinedConstant()); actual_parameters.push_back(new_target); // kJavaScriptCallNewTargetRegister
actual_parameters.push_back(argc); actual_parameters.push_back(argc); // kJavaScriptCallArgCountRegister
return CreateBuiltinContinuationFrameStateCommon( return CreateBuiltinContinuationFrameStateCommon(
jsgraph, jsgraph,
......
...@@ -5655,10 +5655,14 @@ Node* JSCallReducer::CreateArtificialFrameState( ...@@ -5655,10 +5655,14 @@ Node* JSCallReducer::CreateArtificialFrameState(
bailout_id, OutputFrameStateCombine::Ignore(), state_info); bailout_id, OutputFrameStateCombine::Ignore(), state_info);
const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense()); const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
Node* node0 = graph()->NewNode(op0); 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; std::vector<Node*> params;
params.reserve(parameter_count + 1); params.reserve(parameter_count_with_receiver);
for (int parameter = 0; parameter < parameter_count + 1; ++parameter) { for (int i = 0; i < parameter_count_with_receiver; i++) {
params.push_back(node->InputAt(1 + parameter)); params.push_back(node->InputAt(kReceiverInputIndex + i));
} }
const Operator* op_param = common()->StateValues( const Operator* op_param = common()->StateValues(
static_cast<int>(params.size()), SparseInputMask::Dense()); static_cast<int>(params.size()), SparseInputMask::Dense());
...@@ -5668,7 +5672,7 @@ Node* JSCallReducer::CreateArtificialFrameState( ...@@ -5668,7 +5672,7 @@ Node* JSCallReducer::CreateArtificialFrameState(
context = jsgraph()->UndefinedConstant(); context = jsgraph()->UndefinedConstant();
} }
return graph()->NewNode(op, params_node, node0, node0, context, 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) { Reduction JSCallReducer::ReducePromiseConstructor(Node* node) {
......
...@@ -247,9 +247,13 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state, ...@@ -247,9 +247,13 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
bailout_id, OutputFrameStateCombine::Ignore(), state_info); bailout_id, OutputFrameStateCombine::Ignore(), state_info);
const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense()); const Operator* op0 = common()->StateValues(0, SparseInputMask::Dense());
Node* node0 = graph()->NewNode(op0); 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_); NodeVector params(local_zone_);
for (int parameter = 0; parameter < parameter_count + 1; ++parameter) { for (int i = 0; i < parameter_count_with_receiver; i++) {
params.push_back(node->InputAt(1 + parameter)); params.push_back(node->InputAt(kReceiverInputIndex + i));
} }
const Operator* op_param = common()->StateValues( const Operator* op_param = common()->StateValues(
static_cast<int>(params.size()), SparseInputMask::Dense()); static_cast<int>(params.size()), SparseInputMask::Dense());
...@@ -259,7 +263,7 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state, ...@@ -259,7 +263,7 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
context = jsgraph()->UndefinedConstant(); context = jsgraph()->UndefinedConstant();
} }
return graph()->NewNode(op, params_node, node0, node0, context, return graph()->NewNode(op, params_node, node0, node0, context,
node->InputAt(0), outer_frame_state); node->InputAt(kTargetInputIndex), outer_frame_state);
} }
namespace { namespace {
......
This diff is collapsed.
...@@ -172,7 +172,14 @@ class TranslatedFrame { ...@@ -172,7 +172,14 @@ class TranslatedFrame {
Kind kind() const { return kind_; } Kind kind() const { return kind_; }
BailoutId node_id() const { return node_id_; } BailoutId node_id() const { return node_id_; }
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } 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 height() const { return height_; }
int return_value_offset() const { return return_value_offset_; } int return_value_offset() const { return return_value_offset_; }
int return_value_count() const { return return_value_count_; } 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