Commit 3c869fde authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[compiler] Extend impl and uses of the FrameState node wrapper

Move index constants into the wrapper, add getters, and use the
wrapper in more spots.

Bug: v8:1166136
Change-Id: I3f37a541482fd6b7c604719c759952a72d58bad2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2637218
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72198}
parent f1730ded
...@@ -671,7 +671,7 @@ size_t InstructionSelector::AddInputsToFrameStateDescriptor( ...@@ -671,7 +671,7 @@ size_t InstructionSelector::AddInputsToFrameStateDescriptor(
// Returns the number of instruction operands added to inputs. // Returns the number of instruction operands added to inputs.
size_t InstructionSelector::AddInputsToFrameStateDescriptor( size_t InstructionSelector::AddInputsToFrameStateDescriptor(
FrameStateDescriptor* descriptor, Node* state, OperandGenerator* g, FrameStateDescriptor* descriptor, FrameState state, OperandGenerator* g,
StateObjectDeduplicator* deduplicator, InstructionOperandVector* inputs, StateObjectDeduplicator* deduplicator, InstructionOperandVector* inputs,
FrameStateInputKind kind, Zone* zone) { FrameStateInputKind kind, Zone* zone) {
DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode()); DCHECK_EQ(IrOpcode::kFrameState, state->op()->opcode());
...@@ -682,15 +682,15 @@ size_t InstructionSelector::AddInputsToFrameStateDescriptor( ...@@ -682,15 +682,15 @@ size_t InstructionSelector::AddInputsToFrameStateDescriptor(
if (descriptor->outer_state()) { if (descriptor->outer_state()) {
entries += AddInputsToFrameStateDescriptor( entries += AddInputsToFrameStateDescriptor(
descriptor->outer_state(), state->InputAt(kFrameStateOuterStateInput), descriptor->outer_state(), state.outer_frame_state(), g, deduplicator,
g, deduplicator, inputs, kind, zone); inputs, kind, zone);
} }
Node* parameters = state->InputAt(kFrameStateParametersInput); Node* parameters = state.parameters();
Node* locals = state->InputAt(kFrameStateLocalsInput); Node* locals = state.locals();
Node* stack = state->InputAt(kFrameStateStackInput); Node* stack = state.stack();
Node* context = state->InputAt(kFrameStateContextInput); Node* context = state.context();
Node* function = state->InputAt(kFrameStateFunctionInput); Node* function = state.function();
DCHECK_EQ(descriptor->parameters_count(), DCHECK_EQ(descriptor->parameters_count(),
StateValuesAccess(parameters).size()); StateValuesAccess(parameters).size());
...@@ -803,7 +803,7 @@ Instruction* InstructionSelector::EmitWithContinuation( ...@@ -803,7 +803,7 @@ Instruction* InstructionSelector::EmitWithContinuation(
DeoptFrameStateOffsetField::encode(static_cast<int>(input_count)); DeoptFrameStateOffsetField::encode(static_cast<int>(input_count));
AppendDeoptimizeArguments(&continuation_inputs_, cont->kind(), AppendDeoptimizeArguments(&continuation_inputs_, cont->kind(),
cont->reason(), cont->feedback(), cont->reason(), cont->feedback(),
cont->frame_state()); FrameState{cont->frame_state()});
} else if (cont->IsSet()) { } else if (cont->IsSet()) {
continuation_outputs_.push_back(g.DefineAsRegister(cont->result())); continuation_outputs_.push_back(g.DefineAsRegister(cont->result()));
} else if (cont->IsTrap()) { } else if (cont->IsTrap()) {
...@@ -828,7 +828,7 @@ Instruction* InstructionSelector::EmitWithContinuation( ...@@ -828,7 +828,7 @@ Instruction* InstructionSelector::EmitWithContinuation(
void InstructionSelector::AppendDeoptimizeArguments( void InstructionSelector::AppendDeoptimizeArguments(
InstructionOperandVector* args, DeoptimizeKind kind, InstructionOperandVector* args, DeoptimizeKind kind,
DeoptimizeReason reason, FeedbackSource const& feedback, DeoptimizeReason reason, FeedbackSource const& feedback,
Node* frame_state) { FrameState frame_state) {
OperandGenerator g(this); OperandGenerator g(this);
FrameStateDescriptor* const descriptor = GetFrameStateDescriptor(frame_state); FrameStateDescriptor* const descriptor = GetFrameStateDescriptor(frame_state);
DCHECK_NE(DeoptimizeKind::kLazy, kind); DCHECK_NE(DeoptimizeKind::kLazy, kind);
...@@ -1015,20 +1015,21 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, ...@@ -1015,20 +1015,21 @@ void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer,
size_t frame_state_entries = 0; size_t frame_state_entries = 0;
USE(frame_state_entries); // frame_state_entries is only used for debug. USE(frame_state_entries); // frame_state_entries is only used for debug.
if (buffer->frame_state_descriptor != nullptr) { if (buffer->frame_state_descriptor != nullptr) {
Node* frame_state = FrameState frame_state{
call->InputAt(static_cast<int>(buffer->descriptor->InputCount())); call->InputAt(static_cast<int>(buffer->descriptor->InputCount()))};
// If it was a syntactic tail call we need to drop the current frame and // If it was a syntactic tail call we need to drop the current frame and
// all the frames on top of it that are either an arguments adaptor frame // all the frames on top of it that are either an arguments adaptor frame
// or a tail caller frame. // or a tail caller frame.
if (is_tail_call) { if (is_tail_call) {
frame_state = NodeProperties::GetFrameStateInput(frame_state); frame_state = FrameState{NodeProperties::GetFrameStateInput(frame_state)};
buffer->frame_state_descriptor = buffer->frame_state_descriptor =
buffer->frame_state_descriptor->outer_state(); buffer->frame_state_descriptor->outer_state();
while (buffer->frame_state_descriptor != nullptr && while (buffer->frame_state_descriptor != nullptr &&
buffer->frame_state_descriptor->type() == buffer->frame_state_descriptor->type() ==
FrameStateType::kArgumentsAdaptor) { FrameStateType::kArgumentsAdaptor) {
frame_state = NodeProperties::GetFrameStateInput(frame_state); frame_state =
FrameState{NodeProperties::GetFrameStateInput(frame_state)};
buffer->frame_state_descriptor = buffer->frame_state_descriptor =
buffer->frame_state_descriptor->outer_state(); buffer->frame_state_descriptor->outer_state();
} }
...@@ -1288,7 +1289,7 @@ void InstructionSelector::VisitControl(BasicBlock* block) { ...@@ -1288,7 +1289,7 @@ void InstructionSelector::VisitControl(BasicBlock* block) {
} }
case BasicBlock::kDeoptimize: { case BasicBlock::kDeoptimize: {
DeoptimizeParameters p = DeoptimizeParametersOf(input->op()); DeoptimizeParameters p = DeoptimizeParametersOf(input->op());
Node* value = input->InputAt(0); FrameState value{input->InputAt(0)};
VisitDeoptimize(p.kind(), p.reason(), p.feedback(), value); VisitDeoptimize(p.kind(), p.reason(), p.feedback(), value);
break; break;
} }
...@@ -2939,8 +2940,8 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ...@@ -2939,8 +2940,8 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
FrameStateDescriptor* frame_state_descriptor = nullptr; FrameStateDescriptor* frame_state_descriptor = nullptr;
if (call_descriptor->NeedsFrameState()) { if (call_descriptor->NeedsFrameState()) {
frame_state_descriptor = GetFrameStateDescriptor( frame_state_descriptor = GetFrameStateDescriptor(FrameState{
node->InputAt(static_cast<int>(call_descriptor->InputCount()))); node->InputAt(static_cast<int>(call_descriptor->InputCount()))});
} }
CallBuffer buffer(zone(), call_descriptor, frame_state_descriptor); CallBuffer buffer(zone(), call_descriptor, frame_state_descriptor);
...@@ -3199,7 +3200,7 @@ void InstructionSelector::EmitIdentity(Node* node) { ...@@ -3199,7 +3200,7 @@ void InstructionSelector::EmitIdentity(Node* node) {
void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind, void InstructionSelector::VisitDeoptimize(DeoptimizeKind kind,
DeoptimizeReason reason, DeoptimizeReason reason,
FeedbackSource const& feedback, FeedbackSource const& feedback,
Node* frame_state) { FrameState frame_state) {
InstructionOperandVector args(instruction_zone()); InstructionOperandVector args(instruction_zone());
AppendDeoptimizeArguments(&args, kind, reason, feedback, frame_state); AppendDeoptimizeArguments(&args, kind, reason, feedback, frame_state);
Emit(kArchDeoptimize, 0, nullptr, args.size(), &args.front(), 0, nullptr); Emit(kArchDeoptimize, 0, nullptr, args.size(), &args.front(), 0, nullptr);
...@@ -3315,18 +3316,19 @@ bool InstructionSelector::ZeroExtendsWord32ToWord64(Node* node, ...@@ -3315,18 +3316,19 @@ bool InstructionSelector::ZeroExtendsWord32ToWord64(Node* node,
namespace { namespace {
FrameStateDescriptor* GetFrameStateDescriptorInternal(Zone* zone, Node* state) { FrameStateDescriptor* GetFrameStateDescriptorInternal(Zone* zone,
FrameState state) {
DCHECK_EQ(IrOpcode::kFrameState, state->opcode()); DCHECK_EQ(IrOpcode::kFrameState, state->opcode());
DCHECK_EQ(kFrameStateInputCount, state->InputCount()); DCHECK_EQ(FrameState::kFrameStateInputCount, state->InputCount());
const FrameStateInfo& state_info = FrameStateInfoOf(state->op()); const FrameStateInfo& state_info = FrameStateInfoOf(state->op());
int parameters = state_info.parameter_count(); int parameters = state_info.parameter_count();
int locals = state_info.local_count(); int locals = state_info.local_count();
int stack = state_info.type() == FrameStateType::kInterpretedFunction ? 1 : 0; int stack = state_info.type() == FrameStateType::kInterpretedFunction ? 1 : 0;
FrameStateDescriptor* outer_state = nullptr; FrameStateDescriptor* outer_state = nullptr;
Node* outer_node = state->InputAt(kFrameStateOuterStateInput); if (state.has_outer_frame_state()) {
if (outer_node->opcode() == IrOpcode::kFrameState) { outer_state =
outer_state = GetFrameStateDescriptorInternal(zone, outer_node); GetFrameStateDescriptorInternal(zone, state.outer_frame_state());
} }
if (state_info.type() == FrameStateType::kJSToWasmBuiltinContinuation) { if (state_info.type() == FrameStateType::kJSToWasmBuiltinContinuation) {
...@@ -3347,7 +3349,7 @@ FrameStateDescriptor* GetFrameStateDescriptorInternal(Zone* zone, Node* state) { ...@@ -3347,7 +3349,7 @@ FrameStateDescriptor* GetFrameStateDescriptorInternal(Zone* zone, Node* state) {
} // namespace } // namespace
FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor( FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
Node* state) { FrameState state) {
auto* desc = GetFrameStateDescriptorInternal(instruction_zone(), state); auto* desc = GetFrameStateDescriptorInternal(instruction_zone(), state);
*max_unoptimized_frame_height_ = *max_unoptimized_frame_height_ =
std::max(*max_unoptimized_frame_height_, std::max(*max_unoptimized_frame_height_,
......
...@@ -491,7 +491,7 @@ class V8_EXPORT_PRIVATE InstructionSelector final { ...@@ -491,7 +491,7 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
void AppendDeoptimizeArguments(InstructionOperandVector* args, void AppendDeoptimizeArguments(InstructionOperandVector* args,
DeoptimizeKind kind, DeoptimizeReason reason, DeoptimizeKind kind, DeoptimizeReason reason,
FeedbackSource const& feedback, FeedbackSource const& feedback,
Node* frame_state); FrameState frame_state);
void EmitTableSwitch(const SwitchInfo& sw, void EmitTableSwitch(const SwitchInfo& sw,
InstructionOperand const& index_operand); InstructionOperand const& index_operand);
...@@ -564,9 +564,9 @@ class V8_EXPORT_PRIVATE InstructionSelector final { ...@@ -564,9 +564,9 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
void UpdateMaxPushedArgumentCount(size_t count); void UpdateMaxPushedArgumentCount(size_t count);
FrameStateDescriptor* GetFrameStateDescriptor(Node* node); FrameStateDescriptor* GetFrameStateDescriptor(FrameState node);
size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor, size_t AddInputsToFrameStateDescriptor(FrameStateDescriptor* descriptor,
Node* state, OperandGenerator* g, FrameState state, OperandGenerator* g,
StateObjectDeduplicator* deduplicator, StateObjectDeduplicator* deduplicator,
InstructionOperandVector* inputs, InstructionOperandVector* inputs,
FrameStateInputKind kind, Zone* zone); FrameStateInputKind kind, Zone* zone);
...@@ -627,7 +627,7 @@ class V8_EXPORT_PRIVATE InstructionSelector final { ...@@ -627,7 +627,7 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch); void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch);
void VisitSwitch(Node* node, const SwitchInfo& sw); void VisitSwitch(Node* node, const SwitchInfo& sw);
void VisitDeoptimize(DeoptimizeKind kind, DeoptimizeReason reason, void VisitDeoptimize(DeoptimizeKind kind, DeoptimizeReason reason,
FeedbackSource const& feedback, Node* frame_state); FeedbackSource const& feedback, FrameState frame_state);
void VisitReturn(Node* ret); void VisitReturn(Node* ret);
void VisitThrow(Node* node); void VisitThrow(Node* node);
void VisitRetain(Node* node); void VisitRetain(Node* node);
......
...@@ -601,6 +601,65 @@ class CommonNodeWrapperBase : public NodeWrapper { ...@@ -601,6 +601,65 @@ class CommonNodeWrapperBase : public NodeWrapper {
NodeProperties::GetValueInput(node(), TheIndex)); \ NodeProperties::GetValueInput(node(), TheIndex)); \
} }
// TODO(jgruber): This class doesn't match the usual OpcodeNode naming
// convention for historical reasons (it was originally a very basic typed node
// wrapper similar to Effect and Control). Consider updating the name, with low
// priority.
class FrameState : public CommonNodeWrapperBase {
public:
explicit constexpr FrameState(Node* node) : CommonNodeWrapperBase(node) {
// TODO(jgruber): Disallow kStart (needed for PromiseConstructorBasic unit
// test, among others). Also, outer_frame_state points at the start node
// for non-inlined functions. This could be avoided by checking
// has_outer_frame_state() before casting to FrameState.
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kFrameState ||
node->opcode() == IrOpcode::kStart);
}
FrameStateInfo frame_state_info() const {
return FrameStateInfoOf(node()->op());
}
static constexpr int kFrameStateParametersInput = 0;
static constexpr int kFrameStateLocalsInput = 1;
static constexpr int kFrameStateStackInput = 2;
static constexpr int kFrameStateContextInput = 3;
static constexpr int kFrameStateFunctionInput = 4;
static constexpr int kFrameStateOuterStateInput = 5;
static constexpr int kFrameStateInputCount = 6;
// Note: The parameters should be accessed through StateValuesAccess.
Node* parameters() const {
Node* n = node()->InputAt(kFrameStateParametersInput);
DCHECK(n->opcode() == IrOpcode::kStateValues ||
n->opcode() == IrOpcode::kTypedStateValues);
return n;
}
Node* locals() const {
Node* n = node()->InputAt(kFrameStateLocalsInput);
DCHECK(n->opcode() == IrOpcode::kStateValues ||
n->opcode() == IrOpcode::kTypedStateValues);
return n;
}
// TODO(jgruber): Consider renaming this to the more meaningful
// 'accumulator'.
Node* stack() const { return node()->InputAt(kFrameStateStackInput); }
Node* context() const { return node()->InputAt(kFrameStateContextInput); }
Node* function() const { return node()->InputAt(kFrameStateFunctionInput); }
// An outer frame state exists for inlined functions; otherwise it points at
// the start node.
bool has_outer_frame_state() const {
Node* maybe_outer_frame_state = node()->InputAt(kFrameStateOuterStateInput);
DCHECK(maybe_outer_frame_state->opcode() == IrOpcode::kFrameState ||
maybe_outer_frame_state->opcode() == IrOpcode::kStart);
return maybe_outer_frame_state->opcode() == IrOpcode::kFrameState;
}
FrameState outer_frame_state() const {
return FrameState{node()->InputAt(kFrameStateOuterStateInput)};
}
};
class StartNode final : public CommonNodeWrapperBase { class StartNode final : public CommonNodeWrapperBase {
public: public:
explicit constexpr StartNode(Node* node) : CommonNodeWrapperBase(node) { explicit constexpr StartNode(Node* node) : CommonNodeWrapperBase(node) {
......
...@@ -159,9 +159,12 @@ Node* EscapeAnalysisReducer::ReduceDeoptState(Node* node, Node* effect, ...@@ -159,9 +159,12 @@ Node* EscapeAnalysisReducer::ReduceDeoptState(Node* node, Node* effect,
// This input order is important to match the DFS traversal used in the // This input order is important to match the DFS traversal used in the
// instruction selector. Otherwise, the instruction selector might find a // instruction selector. Otherwise, the instruction selector might find a
// duplicate node before the original one. // duplicate node before the original one.
for (int input_id : {kFrameStateOuterStateInput, kFrameStateFunctionInput, for (int input_id : {FrameState::kFrameStateOuterStateInput,
kFrameStateParametersInput, kFrameStateContextInput, FrameState::kFrameStateFunctionInput,
kFrameStateLocalsInput, kFrameStateStackInput}) { FrameState::kFrameStateParametersInput,
FrameState::kFrameStateContextInput,
FrameState::kFrameStateLocalsInput,
FrameState::kFrameStateStackInput}) {
Node* input = node->InputAt(input_id); Node* input = node->InputAt(input_id);
new_node.ReplaceInput(ReduceDeoptState(input, effect, deduplicator), new_node.ReplaceInput(ReduceDeoptState(input, effect, deduplicator),
input_id); input_id);
......
...@@ -17,11 +17,6 @@ namespace v8 { ...@@ -17,11 +17,6 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
// Guard equality of these constants. Ideally they should be merged at
// some point.
STATIC_ASSERT(kFrameStateOuterStateInput ==
FrameState::kFrameStateOuterStateInput);
size_t hash_value(OutputFrameStateCombine const& sc) { size_t hash_value(OutputFrameStateCombine const& sc) {
return base::hash_value(sc.parameter_); return base::hash_value(sc.parameter_);
} }
......
...@@ -160,16 +160,10 @@ size_t hash_value(FrameStateInfo const&); ...@@ -160,16 +160,10 @@ size_t hash_value(FrameStateInfo const&);
std::ostream& operator<<(std::ostream&, FrameStateInfo const&); std::ostream& operator<<(std::ostream&, FrameStateInfo const&);
static constexpr int kFrameStateParametersInput = 0;
static constexpr int kFrameStateLocalsInput = 1;
static constexpr int kFrameStateStackInput = 2;
static constexpr int kFrameStateContextInput = 3;
static constexpr int kFrameStateFunctionInput = 4;
static constexpr int kFrameStateOuterStateInput = 5;
static constexpr int kFrameStateInputCount = kFrameStateOuterStateInput + 1;
enum class ContinuationFrameStateMode { EAGER, LAZY, LAZY_WITH_CATCH }; enum class ContinuationFrameStateMode { EAGER, LAZY, LAZY_WITH_CATCH };
class FrameState;
FrameState CreateStubBuiltinContinuationFrameState( FrameState CreateStubBuiltinContinuationFrameState(
JSGraph* graph, Builtins::Name name, Node* context, Node* const* parameters, JSGraph* graph, Builtins::Name name, Node* context, Node* const* parameters,
int parameter_count, Node* outer_frame_state, int parameter_count, Node* outer_frame_state,
......
...@@ -3879,13 +3879,14 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread( ...@@ -3879,13 +3879,14 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
// we can only optimize this in case the {node} was already inlined into // we can only optimize this in case the {node} was already inlined into
// some other function (and same for the {arguments_list}). // some other function (and same for the {arguments_list}).
CreateArgumentsType const type = CreateArgumentsTypeOf(arguments_list->op()); CreateArgumentsType const type = CreateArgumentsTypeOf(arguments_list->op());
Node* frame_state = NodeProperties::GetFrameStateInput(arguments_list); FrameState frame_state =
FrameState{NodeProperties::GetFrameStateInput(arguments_list)};
int start_index = 0; int start_index = 0;
int formal_parameter_count; int formal_parameter_count;
{ {
Handle<SharedFunctionInfo> shared; Handle<SharedFunctionInfo> shared;
if (!FrameStateInfoOf(frame_state->op()).shared_info().ToHandle(&shared)) { if (!frame_state.frame_state_info().shared_info().ToHandle(&shared)) {
return NoChange(); return NoChange();
} }
formal_parameter_count = SharedFunctionInfoRef(broker(), shared) formal_parameter_count = SharedFunctionInfoRef(broker(), shared)
...@@ -3926,8 +3927,7 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread( ...@@ -3926,8 +3927,7 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
arraylike_or_spread_index - JSCallOrConstructNode::FirstArgumentIndex(); arraylike_or_spread_index - JSCallOrConstructNode::FirstArgumentIndex();
// Check if are spreading to inlined arguments or to the arguments of // Check if are spreading to inlined arguments or to the arguments of
// the outermost function. // the outermost function.
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput); if (!frame_state.has_outer_frame_state()) {
if (outer_state->opcode() != IrOpcode::kFrameState) {
Operator const* op; Operator const* op;
if (IsCallWithArrayLikeOrSpread(node)) { if (IsCallWithArrayLikeOrSpread(node)) {
static constexpr int kTargetAndReceiver = 2; static constexpr int kTargetAndReceiver = 2;
...@@ -3942,21 +3942,20 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread( ...@@ -3942,21 +3942,20 @@ Reduction JSCallReducer::ReduceCallOrConstructWithArrayLikeOrSpread(
NodeProperties::ChangeOp(node, op); NodeProperties::ChangeOp(node, op);
return Changed(node); return Changed(node);
} }
FrameState outer_state = frame_state.outer_frame_state();
// Get to the actual frame state from which to extract the arguments; // Get to the actual frame state from which to extract the arguments;
// we can only optimize this in case the {node} was already inlined into // we can only optimize this in case the {node} was already inlined into
// some other function (and same for the {arg_array}). // some other function (and same for the {arg_array}).
FrameStateInfo outer_info = FrameStateInfoOf(outer_state->op()); FrameStateInfo outer_info = outer_state.frame_state_info();
if (outer_info.type() == FrameStateType::kArgumentsAdaptor) { if (outer_info.type() == FrameStateType::kArgumentsAdaptor) {
// Need to take the parameters from the arguments adaptor. // Need to take the parameters from the arguments adaptor.
frame_state = outer_state; frame_state = outer_state;
} }
// Add the actual parameters to the {node}, skipping the receiver. // Add the actual parameters to the {node}, skipping the receiver.
const int argument_count = const int argument_count =
FrameStateInfoOf(frame_state->op()).parameter_count() - frame_state.frame_state_info().parameter_count() - 1; // Minus receiver.
1; // Minus receiver.
if (start_index < argument_count) { if (start_index < argument_count) {
Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); StateValuesAccess parameters_access(frame_state.parameters());
StateValuesAccess parameters_access(parameters);
auto parameters_it = ++parameters_access.begin(); // Skip the receiver. auto parameters_it = ++parameters_access.begin(); // Skip the receiver.
for (int i = 0; i < start_index; i++) { for (int i = 0; i < start_index; i++) {
// A non-zero start_index implies that there are rest arguments. Skip // A non-zero start_index implies that there are rest arguments. Skip
......
...@@ -36,10 +36,10 @@ namespace compiler { ...@@ -36,10 +36,10 @@ namespace compiler {
namespace { namespace {
// Retrieves the frame state holding actual argument values. // Retrieves the frame state holding actual argument values.
Node* GetArgumentsFrameState(Node* frame_state) { FrameState GetArgumentsFrameState(FrameState frame_state) {
Node* const outer_state = NodeProperties::GetFrameStateInput(frame_state); FrameState outer_state{NodeProperties::GetFrameStateInput(frame_state)};
FrameStateInfo outer_state_info = FrameStateInfoOf(outer_state->op()); return outer_state.frame_state_info().type() ==
return outer_state_info.type() == FrameStateType::kArgumentsAdaptor FrameStateType::kArgumentsAdaptor
? outer_state ? outer_state
: frame_state; : frame_state;
} }
...@@ -148,16 +148,15 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) { ...@@ -148,16 +148,15 @@ Reduction JSCreateLowering::ReduceJSCreate(Node* node) {
Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) { Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode()); DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode());
CreateArgumentsType type = CreateArgumentsTypeOf(node->op()); CreateArgumentsType type = CreateArgumentsTypeOf(node->op());
Node* const frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state{NodeProperties::GetFrameStateInput(node)};
Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
Node* const control = graph()->start(); Node* const control = graph()->start();
FrameStateInfo state_info = FrameStateInfoOf(frame_state->op()); FrameStateInfo state_info = frame_state.frame_state_info();
SharedFunctionInfoRef shared(broker(), SharedFunctionInfoRef shared(broker(),
state_info.shared_info().ToHandleChecked()); state_info.shared_info().ToHandleChecked());
// Use the ArgumentsAccessStub for materializing both mapped and unmapped // Use the ArgumentsAccessStub for materializing both mapped and unmapped
// arguments object, but only for non-inlined (i.e. outermost) frames. // arguments object, but only for non-inlined (i.e. outermost) frames.
if (outer_state->opcode() != IrOpcode::kFrameState) { if (!frame_state.has_outer_frame_state()) {
switch (type) { switch (type) {
case CreateArgumentsType::kMappedArguments: { case CreateArgumentsType::kMappedArguments: {
// TODO(turbofan): Duplicate parameters are not handled yet. // TODO(turbofan): Duplicate parameters are not handled yet.
...@@ -263,7 +262,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) { ...@@ -263,7 +262,7 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
} }
// Use inline allocation for all mapped arguments objects within inlined // Use inline allocation for all mapped arguments objects within inlined
// (i.e. non-outermost) frames, independent of the object size. // (i.e. non-outermost) frames, independent of the object size.
DCHECK_EQ(outer_state->opcode(), IrOpcode::kFrameState); DCHECK_EQ(frame_state.outer_frame_state()->opcode(), IrOpcode::kFrameState);
switch (type) { switch (type) {
case CreateArgumentsType::kMappedArguments: { case CreateArgumentsType::kMappedArguments: {
Node* const callee = NodeProperties::GetValueInput(node, 0); Node* const callee = NodeProperties::GetValueInput(node, 0);
...@@ -274,15 +273,14 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) { ...@@ -274,15 +273,14 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
// Choose the correct frame state and frame state info depending on // Choose the correct frame state and frame state info depending on
// whether there conceptually is an arguments adaptor frame in the call // whether there conceptually is an arguments adaptor frame in the call
// chain. // chain.
Node* const args_state = GetArgumentsFrameState(frame_state); FrameState args_state = GetArgumentsFrameState(frame_state);
if (args_state->InputAt(kFrameStateParametersInput)->opcode() == if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) {
IrOpcode::kDeadValue) {
// This protects against an incompletely propagated DeadValue node. // This protects against an incompletely propagated DeadValue node.
// If the FrameState has a DeadValue input, then this node will be // If the FrameState has a DeadValue input, then this node will be
// pruned anyway. // pruned anyway.
return NoChange(); return NoChange();
} }
FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op()); FrameStateInfo args_state_info = args_state.frame_state_info();
int length = args_state_info.parameter_count() - 1; // Minus receiver. int length = args_state_info.parameter_count() - 1; // Minus receiver.
// Check that the array allocated for arguments is not "large". // Check that the array allocated for arguments is not "large".
{ {
...@@ -319,15 +317,14 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) { ...@@ -319,15 +317,14 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
// Choose the correct frame state and frame state info depending on // Choose the correct frame state and frame state info depending on
// whether there conceptually is an arguments adaptor frame in the call // whether there conceptually is an arguments adaptor frame in the call
// chain. // chain.
Node* const args_state = GetArgumentsFrameState(frame_state); FrameState args_state = GetArgumentsFrameState(frame_state);
if (args_state->InputAt(kFrameStateParametersInput)->opcode() == if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) {
IrOpcode::kDeadValue) {
// This protects against an incompletely propagated DeadValue node. // This protects against an incompletely propagated DeadValue node.
// If the FrameState has a DeadValue input, then this node will be // If the FrameState has a DeadValue input, then this node will be
// pruned anyway. // pruned anyway.
return NoChange(); return NoChange();
} }
FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op()); FrameStateInfo args_state_info = args_state.frame_state_info();
int length = args_state_info.parameter_count() - 1; // Minus receiver. int length = args_state_info.parameter_count() - 1; // Minus receiver.
// Check that the array allocated for arguments is not "large". // Check that the array allocated for arguments is not "large".
{ {
...@@ -361,15 +358,14 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) { ...@@ -361,15 +358,14 @@ Reduction JSCreateLowering::ReduceJSCreateArguments(Node* node) {
// Choose the correct frame state and frame state info depending on // Choose the correct frame state and frame state info depending on
// whether there conceptually is an arguments adaptor frame in the call // whether there conceptually is an arguments adaptor frame in the call
// chain. // chain.
Node* const args_state = GetArgumentsFrameState(frame_state); FrameState args_state = GetArgumentsFrameState(frame_state);
if (args_state->InputAt(kFrameStateParametersInput)->opcode() == if (args_state.parameters()->opcode() == IrOpcode::kDeadValue) {
IrOpcode::kDeadValue) {
// This protects against an incompletely propagated DeadValue node. // This protects against an incompletely propagated DeadValue node.
// If the FrameState has a DeadValue input, then this node will be // If the FrameState has a DeadValue input, then this node will be
// pruned anyway. // pruned anyway.
return NoChange(); return NoChange();
} }
FrameStateInfo args_state_info = FrameStateInfoOf(args_state->op()); FrameStateInfo args_state_info = args_state.frame_state_info();
// Prepare element backing store to be used by the rest array. // Prepare element backing store to be used by the rest array.
Node* const elements = Node* const elements =
AllocateRestArguments(effect, control, args_state, start_index); AllocateRestArguments(effect, control, args_state, start_index);
...@@ -1428,13 +1424,13 @@ Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) { ...@@ -1428,13 +1424,13 @@ Reduction JSCreateLowering::ReduceJSCreateObject(Node* node) {
// Helper that allocates a FixedArray holding argument values recorded in the // Helper that allocates a FixedArray holding argument values recorded in the
// given {frame_state}. Serves as backing store for JSCreateArguments nodes. // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
Node* JSCreateLowering::AllocateArguments(Node* effect, Node* control, Node* JSCreateLowering::AllocateArguments(Node* effect, Node* control,
Node* frame_state) { FrameState frame_state) {
FrameStateInfo state_info = FrameStateInfoOf(frame_state->op()); FrameStateInfo state_info = frame_state.frame_state_info();
int argument_count = state_info.parameter_count() - 1; // Minus receiver. int argument_count = state_info.parameter_count() - 1; // Minus receiver.
if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant(); if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
// Prepare an iterator over argument values recorded in the frame state. // Prepare an iterator over argument values recorded in the frame state.
Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); Node* const parameters = frame_state.parameters();
StateValuesAccess parameters_access(parameters); StateValuesAccess parameters_access(parameters);
auto parameters_it = ++parameters_access.begin(); auto parameters_it = ++parameters_access.begin();
...@@ -1453,15 +1449,15 @@ Node* JSCreateLowering::AllocateArguments(Node* effect, Node* control, ...@@ -1453,15 +1449,15 @@ Node* JSCreateLowering::AllocateArguments(Node* effect, Node* control,
// Helper that allocates a FixedArray holding argument values recorded in the // Helper that allocates a FixedArray holding argument values recorded in the
// given {frame_state}. Serves as backing store for JSCreateArguments nodes. // given {frame_state}. Serves as backing store for JSCreateArguments nodes.
Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control, Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control,
Node* frame_state, FrameState frame_state,
int start_index) { int start_index) {
FrameStateInfo state_info = FrameStateInfoOf(frame_state->op()); FrameStateInfo state_info = frame_state.frame_state_info();
int argument_count = state_info.parameter_count() - 1; // Minus receiver. int argument_count = state_info.parameter_count() - 1; // Minus receiver.
int num_elements = std::max(0, argument_count - start_index); int num_elements = std::max(0, argument_count - start_index);
if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant(); if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant();
// Prepare an iterator over argument values recorded in the frame state. // Prepare an iterator over argument values recorded in the frame state.
Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); Node* const parameters = frame_state.parameters();
StateValuesAccess parameters_access(parameters); StateValuesAccess parameters_access(parameters);
auto parameters_it = ++parameters_access.begin(); auto parameters_it = ++parameters_access.begin();
...@@ -1485,9 +1481,9 @@ Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control, ...@@ -1485,9 +1481,9 @@ Node* JSCreateLowering::AllocateRestArguments(Node* effect, Node* control,
// recorded in the given {frame_state}. Some elements map to slots within the // recorded in the given {frame_state}. Some elements map to slots within the
// given {context}. Serves as backing store for JSCreateArguments nodes. // given {context}. Serves as backing store for JSCreateArguments nodes.
Node* JSCreateLowering::AllocateAliasedArguments( Node* JSCreateLowering::AllocateAliasedArguments(
Node* effect, Node* control, Node* frame_state, Node* context, Node* effect, Node* control, FrameState frame_state, Node* context,
const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) { const SharedFunctionInfoRef& shared, bool* has_aliased_arguments) {
FrameStateInfo state_info = FrameStateInfoOf(frame_state->op()); FrameStateInfo state_info = frame_state.frame_state_info();
int argument_count = state_info.parameter_count() - 1; // Minus receiver. int argument_count = state_info.parameter_count() - 1; // Minus receiver.
if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant(); if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant();
...@@ -1503,7 +1499,7 @@ Node* JSCreateLowering::AllocateAliasedArguments( ...@@ -1503,7 +1499,7 @@ Node* JSCreateLowering::AllocateAliasedArguments(
*has_aliased_arguments = true; *has_aliased_arguments = true;
// Prepare an iterator over argument values recorded in the frame state. // Prepare an iterator over argument values recorded in the frame state.
Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); Node* const parameters = frame_state.parameters();
StateValuesAccess parameters_access(parameters); StateValuesAccess parameters_access(parameters);
auto parameters_it = ++parameters_access.begin(); auto parameters_it = ++parameters_access.begin();
......
...@@ -22,6 +22,7 @@ namespace compiler { ...@@ -22,6 +22,7 @@ namespace compiler {
// Forward declarations. // Forward declarations.
class CommonOperatorBuilder; class CommonOperatorBuilder;
class CompilationDependencies; class CompilationDependencies;
class FrameState;
class JSGraph; class JSGraph;
class JSOperatorBuilder; class JSOperatorBuilder;
class MachineOperatorBuilder; class MachineOperatorBuilder;
...@@ -82,11 +83,11 @@ class V8_EXPORT_PRIVATE JSCreateLowering final ...@@ -82,11 +83,11 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
const SlackTrackingPrediction& slack_tracking_prediction); const SlackTrackingPrediction& slack_tracking_prediction);
Reduction ReduceJSCreateObject(Node* node); Reduction ReduceJSCreateObject(Node* node);
Node* AllocateArguments(Node* effect, Node* control, Node* frame_state); Node* AllocateArguments(Node* effect, Node* control, FrameState frame_state);
Node* AllocateRestArguments(Node* effect, Node* control, Node* frame_state, Node* AllocateRestArguments(Node* effect, Node* control,
int start_index); FrameState frame_state, int start_index);
Node* AllocateAliasedArguments(Node* effect, Node* control, Node* frame_state, Node* AllocateAliasedArguments(Node* effect, Node* control,
Node* context, FrameState frame_state, Node* context,
const SharedFunctionInfoRef& shared, const SharedFunctionInfoRef& shared,
bool* has_aliased_arguments); bool* has_aliased_arguments);
Node* AllocateAliasedArguments(Node* effect, Node* control, Node* context, Node* AllocateAliasedArguments(Node* effect, Node* control, Node* context,
......
...@@ -171,8 +171,8 @@ Reduction JSInliningHeuristic::Reduce(Node* node) { ...@@ -171,8 +171,8 @@ Reduction JSInliningHeuristic::Reduce(Node* node) {
bool can_inline_candidate = false, candidate_is_small = true; bool can_inline_candidate = false, candidate_is_small = true;
candidate.total_size = 0; candidate.total_size = 0;
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state{NodeProperties::GetFrameStateInput(node)};
FrameStateInfo const& frame_info = FrameStateInfoOf(frame_state->op()); FrameStateInfo const& frame_info = frame_state.frame_state_info();
Handle<SharedFunctionInfo> frame_shared_info; Handle<SharedFunctionInfo> frame_shared_info;
for (int i = 0; i < candidate.num_functions; ++i) { for (int i = 0; i < candidate.num_functions; ++i) {
if (!candidate.bytecode[i].has_value()) { if (!candidate.bytecode[i].has_value()) {
...@@ -341,19 +341,18 @@ Node* JSInliningHeuristic::DuplicateStateValuesAndRename(Node* state_values, ...@@ -341,19 +341,18 @@ Node* JSInliningHeuristic::DuplicateStateValuesAndRename(Node* state_values,
namespace { namespace {
bool CollectFrameStateUniqueUses(Node* node, Node* frame_state, bool CollectFrameStateUniqueUses(Node* node, FrameState frame_state,
NodeAndIndex* uses_buffer, size_t* use_count, NodeAndIndex* uses_buffer, size_t* use_count,
size_t max_uses) { size_t max_uses) {
// Only accumulate states that are not shared with other users. // Only accumulate states that are not shared with other users.
if (frame_state->UseCount() > 1) return true; if (frame_state->UseCount() > 1) return true;
if (frame_state->InputAt(kFrameStateStackInput) == node) { if (frame_state.stack() == node) {
if (*use_count >= max_uses) return false; if (*use_count >= max_uses) return false;
uses_buffer[*use_count] = {frame_state, kFrameStateStackInput}; uses_buffer[*use_count] = {frame_state, FrameState::kFrameStateStackInput};
(*use_count)++; (*use_count)++;
} }
if (!CollectStateValuesOwnedUses(node, if (!CollectStateValuesOwnedUses(node, frame_state.locals(), uses_buffer,
frame_state->InputAt(kFrameStateLocalsInput), use_count, max_uses)) {
uses_buffer, use_count, max_uses)) {
return false; return false;
} }
return true; return true;
...@@ -361,28 +360,28 @@ bool CollectFrameStateUniqueUses(Node* node, Node* frame_state, ...@@ -361,28 +360,28 @@ bool CollectFrameStateUniqueUses(Node* node, Node* frame_state,
} // namespace } // namespace
Node* JSInliningHeuristic::DuplicateFrameStateAndRename(Node* frame_state, FrameState JSInliningHeuristic::DuplicateFrameStateAndRename(
Node* from, Node* to, FrameState frame_state, Node* from, Node* to, StateCloneMode mode) {
StateCloneMode mode) {
// Only rename in states that are not shared with other users. This needs to // Only rename in states that are not shared with other users. This needs to
// be in sync with the condition in {DuplicateFrameStateAndRename}. // be in sync with the condition in {DuplicateFrameStateAndRename}.
if (frame_state->UseCount() > 1) return frame_state; if (frame_state->UseCount() > 1) return frame_state;
Node* copy = mode == kChangeInPlace ? frame_state : nullptr; Node* copy =
if (frame_state->InputAt(kFrameStateStackInput) == from) { mode == kChangeInPlace ? static_cast<Node*>(frame_state) : nullptr;
if (frame_state.stack() == from) {
if (!copy) { if (!copy) {
copy = graph()->CloneNode(frame_state); copy = graph()->CloneNode(frame_state);
} }
copy->ReplaceInput(kFrameStateStackInput, to); copy->ReplaceInput(FrameState::kFrameStateStackInput, to);
} }
Node* locals = frame_state->InputAt(kFrameStateLocalsInput); Node* locals = frame_state.locals();
Node* new_locals = DuplicateStateValuesAndRename(locals, from, to, mode); Node* new_locals = DuplicateStateValuesAndRename(locals, from, to, mode);
if (new_locals != locals) { if (new_locals != locals) {
if (!copy) { if (!copy) {
copy = graph()->CloneNode(frame_state); copy = graph()->CloneNode(frame_state);
} }
copy->ReplaceInput(kFrameStateLocalsInput, new_locals); copy->ReplaceInput(FrameState::kFrameStateLocalsInput, new_locals);
} }
return copy ? copy : frame_state; return copy != nullptr ? FrameState{copy} : frame_state;
} }
bool JSInliningHeuristic::TryReuseDispatch(Node* node, Node* callee, bool JSInliningHeuristic::TryReuseDispatch(Node* node, Node* callee,
...@@ -544,14 +543,15 @@ bool JSInliningHeuristic::TryReuseDispatch(Node* node, Node* callee, ...@@ -544,14 +543,15 @@ bool JSInliningHeuristic::TryReuseDispatch(Node* node, Node* callee,
Node* checkpoint_state = nullptr; Node* checkpoint_state = nullptr;
if (checkpoint) { if (checkpoint) {
checkpoint_state = checkpoint->InputAt(0); checkpoint_state = checkpoint->InputAt(0);
if (!CollectFrameStateUniqueUses(callee, checkpoint_state, replaceable_uses, if (!CollectFrameStateUniqueUses(callee, FrameState{checkpoint_state},
&replaceable_uses_count, kMaxUses)) { replaceable_uses, &replaceable_uses_count,
kMaxUses)) {
return false; return false;
} }
} }
// Collect the uses to check case 3. // Collect the uses to check case 3.
Node* frame_state = NodeProperties::GetFrameStateInput(node); FrameState frame_state{NodeProperties::GetFrameStateInput(node)};
if (!CollectFrameStateUniqueUses(callee, frame_state, replaceable_uses, if (!CollectFrameStateUniqueUses(callee, frame_state, replaceable_uses,
&replaceable_uses_count, kMaxUses)) { &replaceable_uses_count, kMaxUses)) {
return false; return false;
...@@ -588,15 +588,15 @@ bool JSInliningHeuristic::TryReuseDispatch(Node* node, Node* callee, ...@@ -588,15 +588,15 @@ bool JSInliningHeuristic::TryReuseDispatch(Node* node, Node* callee,
if (checkpoint) { if (checkpoint) {
// Duplicate the checkpoint. // Duplicate the checkpoint.
Node* new_checkpoint_state = DuplicateFrameStateAndRename( FrameState new_checkpoint_state = DuplicateFrameStateAndRename(
checkpoint_state, callee, target, FrameState{checkpoint_state}, callee, target,
(i == num_calls - 1) ? kChangeInPlace : kCloneState); (i == num_calls - 1) ? kChangeInPlace : kCloneState);
effect = graph()->NewNode(checkpoint->op(), new_checkpoint_state, effect, effect = graph()->NewNode(checkpoint->op(), new_checkpoint_state, effect,
control); control);
} }
// Duplicate the call. // Duplicate the call.
Node* new_lazy_frame_state = DuplicateFrameStateAndRename( FrameState new_lazy_frame_state = DuplicateFrameStateAndRename(
frame_state, callee, target, frame_state, callee, target,
(i == num_calls - 1) ? kChangeInPlace : kCloneState); (i == num_calls - 1) ? kChangeInPlace : kCloneState);
inputs[0] = target; inputs[0] = target;
......
...@@ -81,8 +81,8 @@ class JSInliningHeuristic final : public AdvancedReducer { ...@@ -81,8 +81,8 @@ class JSInliningHeuristic final : public AdvancedReducer {
bool TryReuseDispatch(Node* node, Node* callee, Node** if_successes, bool TryReuseDispatch(Node* node, Node* callee, Node** if_successes,
Node** calls, Node** inputs, int input_count); Node** calls, Node** inputs, int input_count);
enum StateCloneMode { kCloneState, kChangeInPlace }; enum StateCloneMode { kCloneState, kChangeInPlace };
Node* DuplicateFrameStateAndRename(Node* frame_state, Node* from, Node* to, FrameState DuplicateFrameStateAndRename(FrameState frame_state, Node* from,
StateCloneMode mode); Node* to, StateCloneMode mode);
Node* DuplicateStateValuesAndRename(Node* state_values, Node* from, Node* to, Node* DuplicateStateValuesAndRename(Node* state_values, Node* from, Node* to,
StateCloneMode mode); StateCloneMode mode);
Candidate CollectFunctions(Node* node, int functions_size); Candidate CollectFunctions(Node* node, int functions_size);
......
...@@ -61,8 +61,8 @@ class JSCallAccessor { ...@@ -61,8 +61,8 @@ class JSCallAccessor {
Node* new_target() const { return JSConstructNode{call_}.new_target(); } Node* new_target() const { return JSConstructNode{call_}.new_target(); }
Node* frame_state() const { FrameState frame_state() const {
return NodeProperties::GetFrameStateInput(call_); return FrameState{NodeProperties::GetFrameStateInput(call_)};
} }
int argument_count() const { int argument_count() const {
...@@ -245,12 +245,10 @@ Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context, ...@@ -245,12 +245,10 @@ Reduction JSInliner::InlineCall(Node* call, Node* new_target, Node* context,
} }
} }
Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state, FrameState JSInliner::CreateArtificialFrameState(
int parameter_count, Node* node, FrameState outer_frame_state, int parameter_count,
BytecodeOffset bailout_id, BytecodeOffset bailout_id, FrameStateType frame_state_type,
FrameStateType frame_state_type, SharedFunctionInfoRef shared, Node* context) {
SharedFunctionInfoRef shared,
Node* context) {
const int parameter_count_with_receiver = const int parameter_count_with_receiver =
parameter_count + JSCallOrConstructNode::kReceiverOrNewTargetInputCount; parameter_count + JSCallOrConstructNode::kReceiverOrNewTargetInputCount;
const FrameStateFunctionInfo* state_info = const FrameStateFunctionInfo* state_info =
...@@ -273,9 +271,9 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state, ...@@ -273,9 +271,9 @@ Node* JSInliner::CreateArtificialFrameState(Node* node, Node* outer_frame_state,
Node* params_node = graph()->NewNode( Node* params_node = graph()->NewNode(
op_param, static_cast<int>(params.size()), &params.front()); op_param, static_cast<int>(params.size()), &params.front());
if (context == nullptr) context = jsgraph()->UndefinedConstant(); if (context == nullptr) context = jsgraph()->UndefinedConstant();
return graph()->NewNode(op, params_node, node0, node0, context, return FrameState{graph()->NewNode(
node->InputAt(JSCallOrConstructNode::TargetIndex()), op, params_node, node0, node0, context,
outer_frame_state); node->InputAt(JSCallOrConstructNode::TargetIndex()), outer_frame_state)};
} }
namespace { namespace {
...@@ -480,9 +478,9 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -480,9 +478,9 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
// To ensure inlining always terminates, we have an upper limit on inlining // To ensure inlining always terminates, we have an upper limit on inlining
// the nested calls. // the nested calls.
int nesting_level = 0; int nesting_level = 0;
for (Node* frame_state = call.frame_state(); for (FrameState frame_state = FrameState{call.frame_state()};
frame_state->opcode() == IrOpcode::kFrameState; frame_state->opcode() == IrOpcode::kFrameState;
frame_state = frame_state->InputAt(kFrameStateOuterStateInput)) { frame_state = frame_state.outer_frame_state()) {
nesting_level++; nesting_level++;
if (nesting_level > kMaxDepthForInlining) { if (nesting_level > kMaxDepthForInlining) {
TRACE("Not inlining " TRACE("Not inlining "
...@@ -573,7 +571,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) { ...@@ -573,7 +571,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) {
} }
} }
Node* frame_state = call.frame_state(); FrameState frame_state = call.frame_state();
Node* new_target = jsgraph()->UndefinedConstant(); Node* new_target = jsgraph()->UndefinedConstant();
// Inline {JSConstruct} requires some additional magic. // Inline {JSConstruct} requires some additional magic.
......
...@@ -63,12 +63,10 @@ class JSInliner final : public AdvancedReducer { ...@@ -63,12 +63,10 @@ class JSInliner final : public AdvancedReducer {
base::Optional<SharedFunctionInfoRef> DetermineCallTarget(Node* node); base::Optional<SharedFunctionInfoRef> DetermineCallTarget(Node* node);
FeedbackCellRef DetermineCallContext(Node* node, Node** context_out); FeedbackCellRef DetermineCallContext(Node* node, Node** context_out);
Node* CreateArtificialFrameState(Node* node, Node* outer_frame_state, FrameState CreateArtificialFrameState(
int parameter_count, Node* node, FrameState outer_frame_state, int parameter_count,
BytecodeOffset bailout_id, BytecodeOffset bailout_id, FrameStateType frame_state_type,
FrameStateType frame_state_type, SharedFunctionInfoRef shared, Node* context = nullptr);
SharedFunctionInfoRef shared,
Node* context = nullptr);
Reduction InlineCall(Node* call, Node* new_target, Node* context, Reduction InlineCall(Node* call, Node* new_target, Node* context,
Node* frame_state, Node* start, Node* end, Node* frame_state, Node* start, Node* end,
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/base/compiler-specific.h" #include "src/base/compiler-specific.h"
#include "src/codegen/tnode.h" #include "src/codegen/tnode.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/feedback-source.h" #include "src/compiler/feedback-source.h"
#include "src/compiler/globals.h" #include "src/compiler/globals.h"
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
......
...@@ -367,25 +367,6 @@ class Control : public NodeWrapper { ...@@ -367,25 +367,6 @@ class Control : public NodeWrapper {
} }
}; };
class FrameState : public NodeWrapper {
public:
explicit constexpr FrameState(Node* node) : NodeWrapper(node) {
// TODO(jgruber): Disallow kStart (needed for PromiseConstructorBasic unit
// test, among others).
SLOW_DCHECK(node->opcode() == IrOpcode::kFrameState ||
node->opcode() == IrOpcode::kStart);
}
// Duplicating here from frame-states.h for ease of access and to keep
// header include-balls small. Equality of the two constants is
// static-asserted elsewhere.
static constexpr int kFrameStateOuterStateInput = 5;
FrameState outer_frame_state() const {
return FrameState{node()->InputAt(kFrameStateOuterStateInput)};
}
};
// Typedefs to shorten commonly used Node containers. // Typedefs to shorten commonly used Node containers.
using NodeDeque = ZoneDeque<Node*>; using NodeDeque = ZoneDeque<Node*>;
using NodeSet = ZoneSet<Node*>; using NodeSet = ZoneSet<Node*>;
......
...@@ -1224,34 +1224,41 @@ class RepresentationSelector { ...@@ -1224,34 +1224,41 @@ class RepresentationSelector {
} }
template <Phase T> template <Phase T>
void VisitFrameState(Node* node) { void VisitFrameState(FrameState node) {
DCHECK_EQ(5, node->op()->ValueInputCount()); DCHECK_EQ(5, node->op()->ValueInputCount());
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
DCHECK_EQ(FrameState::kFrameStateInputCount, node->InputCount());
ProcessInput<T>(node, 0, UseInfo::AnyTagged()); // Parameters. ProcessInput<T>(node, FrameState::kFrameStateParametersInput,
ProcessInput<T>(node, 1, UseInfo::AnyTagged()); // Registers. UseInfo::AnyTagged());
ProcessInput<T>(node, FrameState::kFrameStateLocalsInput,
UseInfo::AnyTagged());
// Accumulator is a special flower - we need to remember its type in // Accumulator is a special flower - we need to remember its type in
// a singleton typed-state-values node (as if it was a singleton // a singleton typed-state-values node (as if it was a singleton
// state-values node). // state-values node).
Node* accumulator = node->InputAt(2); Node* accumulator = node.stack();
if (propagate<T>()) { if (propagate<T>()) {
// TODO(nicohartmann): Remove, once the deoptimizer can rematerialize // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize
// truncated BigInts. // truncated BigInts.
if (TypeOf(accumulator).Is(Type::BigInt())) { if (TypeOf(accumulator).Is(Type::BigInt())) {
EnqueueInput<T>(node, 2, UseInfo::AnyTagged()); EnqueueInput<T>(node, FrameState::kFrameStateStackInput,
UseInfo::AnyTagged());
} else { } else {
EnqueueInput<T>(node, 2, UseInfo::Any()); EnqueueInput<T>(node, FrameState::kFrameStateStackInput,
UseInfo::Any());
} }
} else if (lower<T>()) { } else if (lower<T>()) {
// TODO(nicohartmann): Remove, once the deoptimizer can rematerialize // TODO(nicohartmann): Remove, once the deoptimizer can rematerialize
// truncated BigInts. // truncated BigInts.
if (TypeOf(accumulator).Is(Type::BigInt())) { if (TypeOf(accumulator).Is(Type::BigInt())) {
ConvertInput(node, 2, UseInfo::AnyTagged()); ConvertInput(node, FrameState::kFrameStateStackInput,
UseInfo::AnyTagged());
} }
Zone* zone = jsgraph_->zone(); Zone* zone = jsgraph_->zone();
if (accumulator == jsgraph_->OptimizedOutConstant()) { if (accumulator == jsgraph_->OptimizedOutConstant()) {
node->ReplaceInput(2, jsgraph_->SingleDeadTypedStateValues()); node->ReplaceInput(FrameState::kFrameStateStackInput,
jsgraph_->SingleDeadTypedStateValues());
} else { } else {
ZoneVector<MachineType>* types = ZoneVector<MachineType>* types =
zone->New<ZoneVector<MachineType>>(1, zone); zone->New<ZoneVector<MachineType>>(1, zone);
...@@ -1259,15 +1266,19 @@ class RepresentationSelector { ...@@ -1259,15 +1266,19 @@ class RepresentationSelector {
TypeOf(accumulator)); TypeOf(accumulator));
node->ReplaceInput( node->ReplaceInput(
2, jsgraph_->graph()->NewNode(jsgraph_->common()->TypedStateValues( FrameState::kFrameStateStackInput,
types, SparseInputMask::Dense()), jsgraph_->graph()->NewNode(jsgraph_->common()->TypedStateValues(
node->InputAt(2))); types, SparseInputMask::Dense()),
node.stack()));
} }
} }
ProcessInput<T>(node, 3, UseInfo::AnyTagged()); // Context. ProcessInput<T>(node, FrameState::kFrameStateContextInput,
ProcessInput<T>(node, 4, UseInfo::AnyTagged()); // Closure. UseInfo::AnyTagged());
ProcessInput<T>(node, 5, UseInfo::AnyTagged()); // Outer frame state. ProcessInput<T>(node, FrameState::kFrameStateFunctionInput,
UseInfo::AnyTagged());
ProcessInput<T>(node, FrameState::kFrameStateOuterStateInput,
UseInfo::AnyTagged());
return SetOutput<T>(node, MachineRepresentation::kTagged); return SetOutput<T>(node, MachineRepresentation::kTagged);
} }
...@@ -3745,7 +3756,7 @@ class RepresentationSelector { ...@@ -3745,7 +3756,7 @@ class RepresentationSelector {
VisitInputs<T>(node); VisitInputs<T>(node);
return SetOutput<T>(node, MachineRepresentation::kTaggedPointer); return SetOutput<T>(node, MachineRepresentation::kTaggedPointer);
case IrOpcode::kFrameState: case IrOpcode::kFrameState:
return VisitFrameState<T>(node); return VisitFrameState<T>(FrameState{node});
case IrOpcode::kStateValues: case IrOpcode::kStateValues:
return VisitStateValues<T>(node); return VisitStateValues<T>(node);
case IrOpcode::kObjectState: case IrOpcode::kObjectState:
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "src/codegen/machine-type.h" #include "src/codegen/machine-type.h"
#include "src/codegen/tnode.h" #include "src/codegen/tnode.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/feedback-source.h" #include "src/compiler/feedback-source.h"
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
#include "src/compiler/operator.h" #include "src/compiler/operator.h"
......
...@@ -536,28 +536,24 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -536,28 +536,24 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
CHECK_EQ(0, control_count); CHECK_EQ(0, control_count);
CHECK_EQ(0, effect_count); CHECK_EQ(0, effect_count);
CHECK_EQ(6, input_count); CHECK_EQ(6, input_count);
// Check that the parameters and registers are kStateValues or
// kTypedStateValues. FrameState state{node};
for (int i = 0; i < 2; ++i) { CHECK(state.parameters()->opcode() == IrOpcode::kStateValues ||
CHECK(NodeProperties::GetValueInput(node, i)->opcode() == state.parameters()->opcode() == IrOpcode::kTypedStateValues);
IrOpcode::kStateValues || CHECK(state.locals()->opcode() == IrOpcode::kStateValues ||
NodeProperties::GetValueInput(node, i)->opcode() == state.locals()->opcode() == IrOpcode::kTypedStateValues);
IrOpcode::kTypedStateValues);
}
// Checks that the state input is empty for all but kInterpretedFunction // Checks that the state input is empty for all but kInterpretedFunction
// frames, where it should have size one. // frames, where it should have size one.
{ {
const FrameStateInfo& state_info = FrameStateInfoOf(node->op()); const FrameStateFunctionInfo* func_info =
const FrameStateFunctionInfo* func_info = state_info.function_info(); state.frame_state_info().function_info();
CHECK_EQ(func_info->parameter_count(), CHECK_EQ(func_info->parameter_count(),
StateValuesAccess(node->InputAt(kFrameStateParametersInput)) StateValuesAccess(state.parameters()).size());
.size()); CHECK_EQ(func_info->local_count(),
CHECK_EQ( StateValuesAccess(state.locals()).size());
func_info->local_count(),
StateValuesAccess(node->InputAt(kFrameStateLocalsInput)).size());
Node* accumulator = node->InputAt(kFrameStateStackInput); Node* accumulator = state.stack();
if (func_info->type() == FrameStateType::kInterpretedFunction) { if (func_info->type() == FrameStateType::kInterpretedFunction) {
// The accumulator (InputAt(2)) cannot be kStateValues. // The accumulator (InputAt(2)) cannot be kStateValues.
// It can be kTypedStateValues (to signal the type) and it can have // It can be kTypedStateValues (to signal the type) and it can have
......
...@@ -361,7 +361,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) { ...@@ -361,7 +361,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
m.common()->FrameState(bailout_id, OutputFrameStateCombine::PokeAt(0), m.common()->FrameState(bailout_id, OutputFrameStateCombine::PokeAt(0),
m.GetFrameStateFunctionInfo(1, 0)), m.GetFrameStateFunctionInfo(1, 0)),
parameters, locals, stack, context_sentinel, function_node, parameters, locals, stack, context_sentinel, function_node,
m.UndefinedConstant()); m.graph()->start());
// Build the call. // Build the call.
Node* nodes[] = {function_node, receiver, m.UndefinedConstant(), Node* nodes[] = {function_node, receiver, m.UndefinedConstant(),
...@@ -421,7 +421,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeopt) { ...@@ -421,7 +421,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeopt) {
OutputFrameStateCombine::PokeAt(0), OutputFrameStateCombine::PokeAt(0),
m.GetFrameStateFunctionInfo(1, 1)), m.GetFrameStateFunctionInfo(1, 1)),
parameters, locals, stack, context_sentinel, function_node, parameters, locals, stack, context_sentinel, function_node,
m.UndefinedConstant()); m.graph()->start());
// Build the call. // Build the call.
Node* stub_code = m.HeapConstant(callable.code()); Node* stub_code = m.HeapConstant(callable.code());
...@@ -512,7 +512,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeoptRecursiveFrameState) { ...@@ -512,7 +512,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeoptRecursiveFrameState) {
m.common()->FrameState(bailout_id_parent, m.common()->FrameState(bailout_id_parent,
OutputFrameStateCombine::Ignore(), OutputFrameStateCombine::Ignore(),
m.GetFrameStateFunctionInfo(1, 1)), m.GetFrameStateFunctionInfo(1, 1)),
parameters, locals, stack, context, function_node, m.UndefinedConstant()); parameters, locals, stack, context, function_node, m.graph()->start());
Node* parameters2 = m.AddNode( Node* parameters2 = m.AddNode(
m.common()->TypedStateValues(&int32_type, SparseInputMask::Dense()), m.common()->TypedStateValues(&int32_type, SparseInputMask::Dense()),
......
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