[nci] Add feedback input to more nodes kinds
... and extend JS node wrapper functionality. Node wrappers now have accessors for value inputs and context/control/effect/frame-state inputs. Accessors are typed, although types aren't very meaningful so far (in current examples we only distinguish between Object/HeapObject). The following node kinds now take an additional feedback vector input, and use the new node wrapper functionality above: - CloneObject - CreateLiteralArray - CreateLiteralObject - CreateLiteralRegExp - GetIterator - GetTemplateObject - HasProperty - LoadProperty - StoreProperty Bug: v8:8888 Change-Id: I1eb33c078b11725a72ec983bbaa848b9a3c7b0d9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2259936 Commit-Queue: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#68538}
This commit is contained in:
parent
bc8efc9a2c
commit
5d417c0d49
@ -1954,7 +1954,10 @@ void BytecodeGraphBuilder::VisitLdaKeyedProperty() {
|
||||
node = lowering.value();
|
||||
} else {
|
||||
DCHECK(!lowering.Changed());
|
||||
node = NewNode(op, object, key);
|
||||
STATIC_ASSERT(JSLoadPropertyNode::ObjectIndex() == 0);
|
||||
STATIC_ASSERT(JSLoadPropertyNode::KeyIndex() == 1);
|
||||
STATIC_ASSERT(JSLoadPropertyNode::FeedbackVectorIndex() == 2);
|
||||
node = NewNode(op, object, key, feedback_vector_node());
|
||||
}
|
||||
environment()->BindAccumulator(node, Environment::kAttachFrameState);
|
||||
}
|
||||
@ -2041,7 +2044,11 @@ void BytecodeGraphBuilder::VisitStaKeyedProperty() {
|
||||
node = lowering.value();
|
||||
} else {
|
||||
DCHECK(!lowering.Changed());
|
||||
node = NewNode(op, object, key, value);
|
||||
STATIC_ASSERT(JSStorePropertyNode::ObjectIndex() == 0);
|
||||
STATIC_ASSERT(JSStorePropertyNode::KeyIndex() == 1);
|
||||
STATIC_ASSERT(JSStorePropertyNode::ValueIndex() == 2);
|
||||
STATIC_ASSERT(JSStorePropertyNode::FeedbackVectorIndex() == 3);
|
||||
node = NewNode(op, object, key, value, feedback_vector_node());
|
||||
}
|
||||
|
||||
environment()->RecordAfterState(node, Environment::kAttachFrameState);
|
||||
@ -2177,8 +2184,10 @@ void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
|
||||
int const slot_id = bytecode_iterator().GetIndexOperand(1);
|
||||
FeedbackSource pair = CreateFeedbackSource(slot_id);
|
||||
int literal_flags = bytecode_iterator().GetFlagOperand(2);
|
||||
STATIC_ASSERT(JSCreateLiteralRegExpNode::FeedbackVectorIndex() == 0);
|
||||
Node* literal = NewNode(javascript()->CreateLiteralRegExp(
|
||||
constant_pattern.object(), pair, literal_flags));
|
||||
constant_pattern.object(), pair, literal_flags),
|
||||
feedback_vector_node());
|
||||
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
@ -2197,9 +2206,11 @@ void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
|
||||
literal_flags |= ArrayLiteral::kDisableMementos;
|
||||
int number_of_elements =
|
||||
array_boilerplate_description.constants_elements_length();
|
||||
Node* literal = NewNode(javascript()->CreateLiteralArray(
|
||||
array_boilerplate_description.object(), pair, literal_flags,
|
||||
number_of_elements));
|
||||
STATIC_ASSERT(JSCreateLiteralArrayNode::FeedbackVectorIndex() == 0);
|
||||
Node* literal = NewNode(
|
||||
javascript()->CreateLiteralArray(array_boilerplate_description.object(),
|
||||
pair, literal_flags, number_of_elements),
|
||||
feedback_vector_node());
|
||||
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
@ -2225,8 +2236,11 @@ void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
|
||||
int literal_flags =
|
||||
interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
|
||||
int number_of_properties = constant_properties.size();
|
||||
Node* literal = NewNode(javascript()->CreateLiteralObject(
|
||||
constant_properties.object(), pair, literal_flags, number_of_properties));
|
||||
STATIC_ASSERT(JSCreateLiteralObjectNode::FeedbackVectorIndex() == 0);
|
||||
Node* literal = NewNode(
|
||||
javascript()->CreateLiteralObject(constant_properties.object(), pair,
|
||||
literal_flags, number_of_properties),
|
||||
feedback_vector_node());
|
||||
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
@ -2243,7 +2257,9 @@ void BytecodeGraphBuilder::VisitCloneObject() {
|
||||
int slot = bytecode_iterator().GetIndexOperand(2);
|
||||
const Operator* op =
|
||||
javascript()->CloneObject(CreateFeedbackSource(slot), flags);
|
||||
Node* value = NewNode(op, source);
|
||||
STATIC_ASSERT(JSCloneObjectNode::SourceIndex() == 0);
|
||||
STATIC_ASSERT(JSCloneObjectNode::FeedbackVectorIndex() == 1);
|
||||
Node* value = NewNode(op, source, feedback_vector_node());
|
||||
environment()->BindAccumulator(value, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
@ -2253,8 +2269,11 @@ void BytecodeGraphBuilder::VisitGetTemplateObject() {
|
||||
CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
|
||||
TemplateObjectDescriptionRef description(
|
||||
broker(), bytecode_iterator().GetConstantForIndexOperand(0, isolate()));
|
||||
Node* template_object = NewNode(javascript()->GetTemplateObject(
|
||||
description.object(), shared_info().object(), source));
|
||||
STATIC_ASSERT(JSGetTemplateObjectNode::FeedbackVectorIndex() == 0);
|
||||
Node* template_object =
|
||||
NewNode(javascript()->GetTemplateObject(description.object(),
|
||||
shared_info().object(), source),
|
||||
feedback_vector_node());
|
||||
environment()->BindAccumulator(template_object);
|
||||
}
|
||||
|
||||
@ -3173,7 +3192,11 @@ void BytecodeGraphBuilder::VisitTestIn() {
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
||||
FeedbackSource feedback =
|
||||
CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
|
||||
Node* node = NewNode(javascript()->HasProperty(feedback), object, key);
|
||||
STATIC_ASSERT(JSHasPropertyNode::ObjectIndex() == 0);
|
||||
STATIC_ASSERT(JSHasPropertyNode::KeyIndex() == 1);
|
||||
STATIC_ASSERT(JSHasPropertyNode::FeedbackVectorIndex() == 2);
|
||||
Node* node = NewNode(javascript()->HasProperty(feedback), object, key,
|
||||
feedback_vector_node());
|
||||
environment()->BindAccumulator(node, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
@ -3548,7 +3571,9 @@ void BytecodeGraphBuilder::VisitGetIterator() {
|
||||
if (lowering.IsExit()) return;
|
||||
|
||||
DCHECK(!lowering.Changed());
|
||||
Node* iterator = NewNode(op, receiver);
|
||||
STATIC_ASSERT(JSGetIteratorNode::ReceiverIndex() == 0);
|
||||
STATIC_ASSERT(JSGetIteratorNode::FeedbackVectorIndex() == 1);
|
||||
Node* iterator = NewNode(op, receiver, feedback_vector_node());
|
||||
environment()->BindAccumulator(iterator, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,11 @@ namespace v8 {
|
||||
namespace internal {
|
||||
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) {
|
||||
return base::hash_value(sc.parameter_);
|
||||
}
|
||||
|
@ -140,13 +140,13 @@ size_t hash_value(FrameStateInfo const&);
|
||||
|
||||
std::ostream& operator<<(std::ostream&, FrameStateInfo const&);
|
||||
|
||||
static const int kFrameStateParametersInput = 0;
|
||||
static const int kFrameStateLocalsInput = 1;
|
||||
static const int kFrameStateStackInput = 2;
|
||||
static const int kFrameStateContextInput = 3;
|
||||
static const int kFrameStateFunctionInput = 4;
|
||||
static const int kFrameStateOuterStateInput = 5;
|
||||
static const int kFrameStateInputCount = kFrameStateOuterStateInput + 1;
|
||||
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 };
|
||||
|
||||
|
@ -130,37 +130,6 @@ class BasicBlock;
|
||||
|
||||
class GraphAssembler;
|
||||
|
||||
// Wrapper classes for special node/edge types (effect, control, frame states)
|
||||
// that otherwise don't fit into the type system.
|
||||
|
||||
class Effect : public NodeWrapper {
|
||||
public:
|
||||
explicit constexpr Effect(Node* node) : NodeWrapper(node) {
|
||||
// TODO(jgruber): Remove the End special case.
|
||||
SLOW_DCHECK(node == nullptr || node->op()->opcode() == IrOpcode::kEnd ||
|
||||
node->op()->EffectOutputCount() > 0);
|
||||
}
|
||||
};
|
||||
|
||||
class Control : public NodeWrapper {
|
||||
public:
|
||||
explicit constexpr Control(Node* node) : NodeWrapper(node) {
|
||||
// TODO(jgruber): Remove the End special case.
|
||||
SLOW_DCHECK(node == nullptr || node->opcode() == IrOpcode::kEnd ||
|
||||
node->op()->ControlOutputCount() > 0);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
enum class GraphAssemblerLabelType { kDeferred, kNonDeferred, kLoop };
|
||||
|
||||
// Label with statically known count of incoming branches and phis.
|
||||
|
@ -3089,9 +3089,9 @@ Reduction JSCallReducer::ReduceReflectHas(Node* node) {
|
||||
Node* vtrue;
|
||||
{
|
||||
// TODO(magardn): collect feedback so this can be optimized
|
||||
vtrue = etrue = if_true =
|
||||
graph()->NewNode(javascript()->HasProperty(FeedbackSource()), target,
|
||||
key, context, frame_state, etrue, if_true);
|
||||
vtrue = etrue = if_true = graph()->NewNode(
|
||||
javascript()->HasProperty(FeedbackSource()), target, key,
|
||||
jsgraph()->UndefinedConstant(), context, frame_state, etrue, if_true);
|
||||
}
|
||||
|
||||
// Rewire potential exception edges.
|
||||
|
@ -1088,9 +1088,10 @@ Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) {
|
||||
Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
|
||||
DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
|
||||
node->opcode() == IrOpcode::kJSCreateLiteralObject);
|
||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
JSCreateLiteralOpNode n(node);
|
||||
CreateLiteralParameters const& p = n.Parameters();
|
||||
Effect effect = n.effect();
|
||||
Control control = n.control();
|
||||
ProcessedFeedback const& feedback =
|
||||
broker()->GetFeedbackForArrayOrObjectLiteral(p.feedback());
|
||||
if (!feedback.IsInsufficient()) {
|
||||
@ -1168,10 +1169,10 @@ Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) {
|
||||
}
|
||||
|
||||
Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSCreateLiteralRegExp, node->opcode());
|
||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
JSCreateLiteralRegExpNode n(node);
|
||||
CreateLiteralParameters const& p = n.Parameters();
|
||||
Effect effect = n.effect();
|
||||
Control control = n.control();
|
||||
ProcessedFeedback const& feedback =
|
||||
broker()->GetFeedbackForRegExpLiteral(p.feedback());
|
||||
if (!feedback.IsInsufficient()) {
|
||||
@ -1184,9 +1185,8 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
|
||||
}
|
||||
|
||||
Reduction JSCreateLowering::ReduceJSGetTemplateObject(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSGetTemplateObject, node->opcode());
|
||||
GetTemplateObjectParameters const& parameters =
|
||||
GetTemplateObjectParametersOf(node->op());
|
||||
JSGetTemplateObjectNode n(node);
|
||||
GetTemplateObjectParameters const& parameters = n.Parameters();
|
||||
SharedFunctionInfoRef shared(broker(), parameters.shared());
|
||||
JSArrayRef template_object = shared.GetTemplateObject(
|
||||
TemplateObjectDescriptionRef(broker(), parameters.description()),
|
||||
|
@ -60,7 +60,6 @@ Reduction JSGenericLowering::Reduce(Node* node) {
|
||||
void JSGenericLowering::LowerJS##Name(Node* node) { \
|
||||
ReplaceWithBuiltinCall(node, Builtins::k##Name); \
|
||||
}
|
||||
REPLACE_STUB_CALL(HasProperty)
|
||||
REPLACE_STUB_CALL(ToLength)
|
||||
REPLACE_STUB_CALL(ToNumber)
|
||||
REPLACE_STUB_CALL(ToNumberConvertBigInt)
|
||||
@ -208,6 +207,7 @@ DEF_BINARY_LOWERING(LessThanOrEqual)
|
||||
void JSGenericLowering::LowerJSStrictEqual(Node* node) {
|
||||
// The === operator doesn't need the current context.
|
||||
NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
|
||||
DCHECK_EQ(node->op()->ControlInputCount(), 1);
|
||||
node->RemoveInput(NodeProperties::FirstControlIndex(node));
|
||||
|
||||
Builtins::Name builtin_id;
|
||||
@ -246,20 +246,29 @@ bool ShouldUseMegamorphicLoadBuiltin(FeedbackSource const& source,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void JSGenericLowering::LowerJSHasProperty(Node* node) {
|
||||
// TODO(jgruber,v8:8888): Collect feedback.
|
||||
node->RemoveInput(JSHasPropertyNode::FeedbackVectorIndex());
|
||||
ReplaceWithBuiltinCall(node, Builtins::kHasProperty);
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSLoadProperty(Node* node) {
|
||||
const PropertyAccess& p = PropertyAccessOf(node->op());
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node);
|
||||
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
|
||||
node->InsertInput(zone(), 2,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
JSLoadPropertyNode n(node);
|
||||
const PropertyAccess& p = n.Parameters();
|
||||
FrameState frame_state = n.frame_state();
|
||||
FrameState outer_state = frame_state.outer_frame_state();
|
||||
STATIC_ASSERT(n.FeedbackVectorIndex() == 2);
|
||||
if (outer_state->opcode() != IrOpcode::kFrameState) {
|
||||
n->RemoveInput(n.FeedbackVectorIndex());
|
||||
n->InsertInput(zone(), 2,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
ReplaceWithBuiltinCall(
|
||||
node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
|
||||
? Builtins::kKeyedLoadICTrampoline_Megamorphic
|
||||
: Builtins::kKeyedLoadICTrampoline);
|
||||
} else {
|
||||
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
|
||||
node->InsertInput(zone(), 3, vector);
|
||||
n->InsertInput(zone(), 2,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
ReplaceWithBuiltinCall(
|
||||
node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
|
||||
? Builtins::kKeyedLoadIC_Megamorphic
|
||||
@ -324,30 +333,33 @@ void JSGenericLowering::LowerJSGetIterator(Node* node) {
|
||||
// instead of 2 calls resulting from the generic lowering of the LoadNamed
|
||||
// and Call operators.
|
||||
|
||||
GetIteratorParameters const& p = GetIteratorParametersOf(node->op());
|
||||
JSGetIteratorNode n(node);
|
||||
GetIteratorParameters const& p = n.Parameters();
|
||||
Node* load_slot =
|
||||
jsgraph()->TaggedIndexConstant(p.loadFeedback().slot.ToInt());
|
||||
Node* call_slot =
|
||||
jsgraph()->TaggedIndexConstant(p.callFeedback().slot.ToInt());
|
||||
Node* feedback = jsgraph()->HeapConstant(p.callFeedback().vector);
|
||||
STATIC_ASSERT(n.FeedbackVectorIndex() == 1);
|
||||
node->InsertInput(zone(), 1, load_slot);
|
||||
node->InsertInput(zone(), 2, call_slot);
|
||||
node->InsertInput(zone(), 3, feedback);
|
||||
|
||||
ReplaceWithBuiltinCall(node, Builtins::kGetIteratorWithFeedback);
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSStoreProperty(Node* node) {
|
||||
PropertyAccess const& p = PropertyAccessOf(node->op());
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node);
|
||||
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
|
||||
node->InsertInput(zone(), 3,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
JSStorePropertyNode n(node);
|
||||
const PropertyAccess& p = n.Parameters();
|
||||
FrameState frame_state = n.frame_state();
|
||||
FrameState outer_state = frame_state.outer_frame_state();
|
||||
STATIC_ASSERT(n.FeedbackVectorIndex() == 3);
|
||||
if (outer_state->opcode() != IrOpcode::kFrameState) {
|
||||
n->RemoveInput(n.FeedbackVectorIndex());
|
||||
node->InsertInput(zone(), 3,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
ReplaceWithBuiltinCall(node, Builtins::kKeyedStoreICTrampoline);
|
||||
} else {
|
||||
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
|
||||
node->InsertInput(zone(), 4, vector);
|
||||
node->InsertInput(zone(), 3,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
ReplaceWithBuiltinCall(node, Builtins::kKeyedStoreIC);
|
||||
}
|
||||
}
|
||||
@ -595,13 +607,14 @@ void JSGenericLowering::LowerJSCreateTypedArray(Node* node) {
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
|
||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
||||
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
|
||||
JSCreateLiteralArrayNode n(node);
|
||||
CreateLiteralParameters const& p = n.Parameters();
|
||||
STATIC_ASSERT(n.FeedbackVectorIndex() == 0);
|
||||
node->InsertInput(zone(), 1,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
|
||||
|
||||
// Use the CreateShallowArrayLiteratlr builtin only for shallow boilerplates
|
||||
// Use the CreateShallowArrayLiteral builtin only for shallow boilerplates
|
||||
// without properties up to the number of elements that the stubs can handle.
|
||||
if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
|
||||
p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
|
||||
@ -613,17 +626,19 @@ void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSGetTemplateObject(Node* node) {
|
||||
GetTemplateObjectParameters const& p =
|
||||
GetTemplateObjectParametersOf(node->op());
|
||||
JSGetTemplateObjectNode n(node);
|
||||
GetTemplateObjectParameters const& p = n.Parameters();
|
||||
SharedFunctionInfoRef shared(broker(), p.shared());
|
||||
TemplateObjectDescriptionRef description(broker(), p.description());
|
||||
|
||||
DCHECK_EQ(node->op()->ControlInputCount(), 1);
|
||||
node->RemoveInput(NodeProperties::FirstControlIndex(node));
|
||||
|
||||
STATIC_ASSERT(JSGetTemplateObjectNode::FeedbackVectorIndex() == 0);
|
||||
node->InsertInput(zone(), 0, jsgraph()->Constant(shared));
|
||||
node->InsertInput(zone(), 1, jsgraph()->Constant(description));
|
||||
node->InsertInput(zone(), 2,
|
||||
jsgraph()->UintPtrConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector));
|
||||
node->RemoveInput(6); // control
|
||||
|
||||
ReplaceWithBuiltinCall(node, Builtins::kGetTemplateObject);
|
||||
}
|
||||
@ -642,8 +657,9 @@ void JSGenericLowering::LowerJSCreateArrayFromIterable(Node* node) {
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
|
||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
||||
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
|
||||
JSCreateLiteralObjectNode n(node);
|
||||
CreateLiteralParameters const& p = n.Parameters();
|
||||
STATIC_ASSERT(n.FeedbackVectorIndex() == 0);
|
||||
node->InsertInput(zone(), 1,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
|
||||
@ -661,11 +677,12 @@ void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSCloneObject(Node* node) {
|
||||
CloneObjectParameters const& p = CloneObjectParametersOf(node->op());
|
||||
JSCloneObjectNode n(node);
|
||||
CloneObjectParameters const& p = n.Parameters();
|
||||
STATIC_ASSERT(n.FeedbackVectorIndex() == 1);
|
||||
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.flags()));
|
||||
node->InsertInput(zone(), 2,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector));
|
||||
ReplaceWithBuiltinCall(node, Builtins::kCloneObjectIC);
|
||||
}
|
||||
|
||||
@ -674,8 +691,9 @@ void JSGenericLowering::LowerJSCreateEmptyLiteralObject(Node* node) {
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
|
||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
||||
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
|
||||
JSCreateLiteralRegExpNode n(node);
|
||||
CreateLiteralParameters const& p = n.Parameters();
|
||||
STATIC_ASSERT(n.FeedbackVectorIndex() == 0);
|
||||
node->InsertInput(zone(), 1,
|
||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
|
||||
|
@ -1358,14 +1358,14 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSGetIterator, node->opcode());
|
||||
GetIteratorParameters const& p = GetIteratorParametersOf(node->op());
|
||||
JSGetIteratorNode n(node);
|
||||
GetIteratorParameters const& p = n.Parameters();
|
||||
|
||||
Node* receiver = NodeProperties::GetValueInput(node, 0);
|
||||
Node* context = NodeProperties::GetContextInput(node);
|
||||
Node* frame_state = NodeProperties::GetFrameStateInput(node);
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
TNode<Object> receiver = n.receiver();
|
||||
TNode<Object> context = n.context();
|
||||
FrameState frame_state = n.frame_state();
|
||||
Effect effect = n.effect();
|
||||
Control control = n.control();
|
||||
|
||||
// Load iterator property operator
|
||||
Handle<Name> iterator_symbol = factory()->iterator_symbol();
|
||||
@ -1895,13 +1895,11 @@ Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceJSHasProperty(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSHasProperty, node->opcode());
|
||||
PropertyAccess const& p = PropertyAccessOf(node->op());
|
||||
Node* key = NodeProperties::GetValueInput(node, 1);
|
||||
JSHasPropertyNode n(node);
|
||||
PropertyAccess const& p = n.Parameters();
|
||||
Node* value = jsgraph()->Dead();
|
||||
|
||||
if (!p.feedback().IsValid()) return NoChange();
|
||||
return ReducePropertyAccess(node, key, base::nullopt, value,
|
||||
return ReducePropertyAccess(node, n.key(), base::nullopt, value,
|
||||
FeedbackSource(p.feedback()), AccessMode::kHas);
|
||||
}
|
||||
|
||||
@ -2012,9 +2010,9 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadPropertyWithEnumeratedKey(
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
|
||||
PropertyAccess const& p = PropertyAccessOf(node->op());
|
||||
Node* name = NodeProperties::GetValueInput(node, 1);
|
||||
JSLoadPropertyNode n(node);
|
||||
PropertyAccess const& p = n.Parameters();
|
||||
Node* name = n.key();
|
||||
|
||||
if (name->opcode() == IrOpcode::kJSForInNext) {
|
||||
Reduction reduction = ReduceJSLoadPropertyWithEnumeratedKey(node);
|
||||
@ -2028,13 +2026,10 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
|
||||
}
|
||||
|
||||
Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode());
|
||||
PropertyAccess const& p = PropertyAccessOf(node->op());
|
||||
Node* const key = NodeProperties::GetValueInput(node, 1);
|
||||
Node* const value = NodeProperties::GetValueInput(node, 2);
|
||||
|
||||
JSStorePropertyNode n(node);
|
||||
PropertyAccess const& p = n.Parameters();
|
||||
if (!p.feedback().IsValid()) return NoChange();
|
||||
return ReducePropertyAccess(node, key, base::nullopt, value,
|
||||
return ReducePropertyAccess(node, n.key(), base::nullopt, n.value(),
|
||||
FeedbackSource(p.feedback()), AccessMode::kStore);
|
||||
}
|
||||
|
||||
|
@ -890,7 +890,7 @@ const Operator* JSOperatorBuilder::LoadProperty(
|
||||
return new (zone()) Operator1<PropertyAccess>( // --
|
||||
IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode
|
||||
"JSLoadProperty", // name
|
||||
2, 1, 1, 1, 1, 2, // counts
|
||||
3, 1, 1, 1, 1, 2, // counts
|
||||
access); // parameter
|
||||
}
|
||||
|
||||
@ -900,7 +900,7 @@ const Operator* JSOperatorBuilder::GetIterator(
|
||||
return new (zone()) Operator1<GetIteratorParameters>( // --
|
||||
IrOpcode::kJSGetIterator, Operator::kNoProperties, // opcode
|
||||
"JSGetIterator", // name
|
||||
1, 1, 1, 1, 1, 2, // counts
|
||||
2, 1, 1, 1, 1, 2, // counts
|
||||
access); // parameter
|
||||
}
|
||||
|
||||
@ -909,7 +909,7 @@ const Operator* JSOperatorBuilder::HasProperty(FeedbackSource const& feedback) {
|
||||
return new (zone()) Operator1<PropertyAccess>( // --
|
||||
IrOpcode::kJSHasProperty, Operator::kNoProperties, // opcode
|
||||
"JSHasProperty", // name
|
||||
2, 1, 1, 1, 1, 2, // counts
|
||||
3, 1, 1, 1, 1, 2, // counts
|
||||
access); // parameter
|
||||
}
|
||||
|
||||
@ -987,7 +987,7 @@ const Operator* JSOperatorBuilder::StoreProperty(
|
||||
return new (zone()) Operator1<PropertyAccess>( // --
|
||||
IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode
|
||||
"JSStoreProperty", // name
|
||||
3, 1, 1, 0, 1, 2, // counts
|
||||
4, 1, 1, 0, 1, 2, // counts
|
||||
access); // parameter
|
||||
}
|
||||
|
||||
@ -1167,7 +1167,7 @@ const Operator* JSOperatorBuilder::CreateLiteralArray(
|
||||
IrOpcode::kJSCreateLiteralArray, // opcode
|
||||
Operator::kNoProperties, // properties
|
||||
"JSCreateLiteralArray", // name
|
||||
0, 1, 1, 1, 1, 2, // counts
|
||||
1, 1, 1, 1, 1, 2, // counts
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
@ -1200,7 +1200,7 @@ const Operator* JSOperatorBuilder::CreateLiteralObject(
|
||||
IrOpcode::kJSCreateLiteralObject, // opcode
|
||||
Operator::kNoProperties, // properties
|
||||
"JSCreateLiteralObject", // name
|
||||
0, 1, 1, 1, 1, 2, // counts
|
||||
1, 1, 1, 1, 1, 2, // counts
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
@ -1212,7 +1212,7 @@ const Operator* JSOperatorBuilder::GetTemplateObject(
|
||||
IrOpcode::kJSGetTemplateObject, // opcode
|
||||
Operator::kEliminatable, // properties
|
||||
"JSGetTemplateObject", // name
|
||||
0, 1, 1, 1, 1, 0, // counts
|
||||
1, 1, 1, 1, 1, 0, // counts
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
@ -1223,7 +1223,7 @@ const Operator* JSOperatorBuilder::CloneObject(FeedbackSource const& feedback,
|
||||
IrOpcode::kJSCloneObject, // opcode
|
||||
Operator::kNoProperties, // properties
|
||||
"JSCloneObject", // name
|
||||
1, 1, 1, 1, 1, 2, // counts
|
||||
2, 1, 1, 1, 1, 2, // counts
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
@ -1253,7 +1253,7 @@ const Operator* JSOperatorBuilder::CreateLiteralRegExp(
|
||||
IrOpcode::kJSCreateLiteralRegExp, // opcode
|
||||
Operator::kNoProperties, // properties
|
||||
"JSCreateLiteralRegExp", // name
|
||||
0, 1, 1, 1, 1, 2, // counts
|
||||
1, 1, 1, 1, 1, 2, // counts
|
||||
parameters); // parameter
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,10 @@
|
||||
#define V8_COMPILER_JS_OPERATOR_H_
|
||||
|
||||
#include "src/base/compiler-specific.h"
|
||||
#include "src/codegen/tnode.h"
|
||||
#include "src/compiler/feedback-source.h"
|
||||
#include "src/compiler/globals.h"
|
||||
#include "src/compiler/node-properties.h"
|
||||
#include "src/compiler/node.h"
|
||||
#include "src/compiler/opcodes.h"
|
||||
#include "src/handles/maybe-handles.h"
|
||||
@ -69,37 +71,6 @@ class JSOperator final : public AllStatic {
|
||||
}
|
||||
};
|
||||
|
||||
// Node wrappers.
|
||||
|
||||
class JSUnaryOpNode final : public NodeWrapper {
|
||||
public:
|
||||
explicit constexpr JSUnaryOpNode(Node* node) : NodeWrapper(node) {
|
||||
CONSTEXPR_DCHECK(JSOperator::IsUnaryWithFeedback(node->opcode()));
|
||||
}
|
||||
|
||||
static constexpr int ValueIndex() { return 0; }
|
||||
static constexpr int FeedbackVectorIndex() { return 1; }
|
||||
};
|
||||
|
||||
#define V(JSName, ...) using JSName##Node = JSUnaryOpNode;
|
||||
JS_UNOP_WITH_FEEDBACK(V)
|
||||
#undef V
|
||||
|
||||
class JSBinaryOpNode final : public NodeWrapper {
|
||||
public:
|
||||
explicit constexpr JSBinaryOpNode(Node* node) : NodeWrapper(node) {
|
||||
CONSTEXPR_DCHECK(JSOperator::IsBinaryWithFeedback(node->opcode()));
|
||||
}
|
||||
|
||||
static constexpr int LeftIndex() { return 0; }
|
||||
static constexpr int RightIndex() { return 1; }
|
||||
static constexpr int FeedbackVectorIndex() { return 2; }
|
||||
};
|
||||
|
||||
#define V(JSName, ...) using JSName##Node = JSBinaryOpNode;
|
||||
JS_BINOP_WITH_FEEDBACK(V)
|
||||
#undef V
|
||||
|
||||
// Defines the frequency a given Call/Construct site was executed. For some
|
||||
// call sites the frequency is not known.
|
||||
class CallFrequency final {
|
||||
@ -1043,6 +1014,208 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
|
||||
DISALLOW_COPY_AND_ASSIGN(JSOperatorBuilder);
|
||||
};
|
||||
|
||||
// Node wrappers.
|
||||
|
||||
class JSNodeWrapperBase : public NodeWrapper {
|
||||
public:
|
||||
explicit constexpr JSNodeWrapperBase(Node* node) : NodeWrapper(node) {}
|
||||
|
||||
// Valid iff this node has a context input.
|
||||
TNode<Object> context() const {
|
||||
// Could be a Context or NoContextConstant.
|
||||
return TNode<Object>::UncheckedCast(
|
||||
NodeProperties::GetContextInput(node()));
|
||||
}
|
||||
|
||||
// Valid iff this node has exactly one effect input.
|
||||
Effect effect() const {
|
||||
DCHECK_EQ(node()->op()->EffectInputCount(), 1);
|
||||
return Effect{NodeProperties::GetEffectInput(node())};
|
||||
}
|
||||
|
||||
// Valid iff this node has exactly one control input.
|
||||
Control control() const {
|
||||
DCHECK_EQ(node()->op()->ControlInputCount(), 1);
|
||||
return Control{NodeProperties::GetControlInput(node())};
|
||||
}
|
||||
|
||||
// Valid iff this node has a frame state input.
|
||||
FrameState frame_state() const {
|
||||
return FrameState{NodeProperties::GetFrameStateInput(node())};
|
||||
}
|
||||
};
|
||||
|
||||
#define DEFINE_INPUT_ACCESSORS(Name, name, TheIndex, Type) \
|
||||
static constexpr int Name##Index() { return TheIndex; } \
|
||||
TNode<Type> name() const { \
|
||||
return TNode<Type>::UncheckedCast( \
|
||||
NodeProperties::GetValueInput(node(), TheIndex)); \
|
||||
}
|
||||
|
||||
class JSUnaryOpNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSUnaryOpNode(Node* node) : JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(JSOperator::IsUnaryWithFeedback(node->opcode()));
|
||||
}
|
||||
|
||||
#define INPUTS(V) \
|
||||
V(Value, value, 0, Object) \
|
||||
V(FeedbackVector, feedback_vector, 1, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
#define V(JSName, ...) using JSName##Node = JSUnaryOpNode;
|
||||
JS_UNOP_WITH_FEEDBACK(V)
|
||||
#undef V
|
||||
|
||||
class JSBinaryOpNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSBinaryOpNode(Node* node) : JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(JSOperator::IsBinaryWithFeedback(node->opcode()));
|
||||
}
|
||||
|
||||
#define INPUTS(V) \
|
||||
V(Left, left, 0, Object) \
|
||||
V(Right, right, 1, Object) \
|
||||
V(FeedbackVector, feedback_vector, 2, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
#define V(JSName, ...) using JSName##Node = JSBinaryOpNode;
|
||||
JS_BINOP_WITH_FEEDBACK(V)
|
||||
#undef V
|
||||
|
||||
class JSGetIteratorNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSGetIteratorNode(Node* node) : JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSGetIterator);
|
||||
}
|
||||
|
||||
const GetIteratorParameters& Parameters() const {
|
||||
return GetIteratorParametersOf(node()->op());
|
||||
}
|
||||
|
||||
#define INPUTS(V) \
|
||||
V(Receiver, receiver, 0, Object) \
|
||||
V(FeedbackVector, feedback_vector, 1, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
class JSCloneObjectNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSCloneObjectNode(Node* node) : JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCloneObject);
|
||||
}
|
||||
|
||||
const CloneObjectParameters& Parameters() const {
|
||||
return CloneObjectParametersOf(node()->op());
|
||||
}
|
||||
|
||||
#define INPUTS(V) \
|
||||
V(Source, source, 0, Object) \
|
||||
V(FeedbackVector, feedback_vector, 1, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
class JSGetTemplateObjectNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSGetTemplateObjectNode(Node* node)
|
||||
: JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSGetTemplateObject);
|
||||
}
|
||||
|
||||
const GetTemplateObjectParameters& Parameters() const {
|
||||
return GetTemplateObjectParametersOf(node()->op());
|
||||
}
|
||||
|
||||
#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
class JSCreateLiteralOpNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSCreateLiteralOpNode(Node* node)
|
||||
: JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
|
||||
node->opcode() == IrOpcode::kJSCreateLiteralObject ||
|
||||
node->opcode() == IrOpcode::kJSCreateLiteralRegExp);
|
||||
}
|
||||
|
||||
const CreateLiteralParameters& Parameters() const {
|
||||
return CreateLiteralParametersOf(node()->op());
|
||||
}
|
||||
|
||||
#define INPUTS(V) V(FeedbackVector, feedback_vector, 0, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
using JSCreateLiteralArrayNode = JSCreateLiteralOpNode;
|
||||
using JSCreateLiteralObjectNode = JSCreateLiteralOpNode;
|
||||
using JSCreateLiteralRegExpNode = JSCreateLiteralOpNode;
|
||||
|
||||
class JSHasPropertyNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSHasPropertyNode(Node* node) : JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSHasProperty);
|
||||
}
|
||||
|
||||
const PropertyAccess& Parameters() const {
|
||||
return PropertyAccessOf(node()->op());
|
||||
}
|
||||
|
||||
#define INPUTS(V) \
|
||||
V(Object, object, 0, Object) \
|
||||
V(Key, key, 1, Object) \
|
||||
V(FeedbackVector, feedback_vector, 2, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
class JSLoadPropertyNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSLoadPropertyNode(Node* node) : JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSLoadProperty);
|
||||
}
|
||||
|
||||
const PropertyAccess& Parameters() const {
|
||||
return PropertyAccessOf(node()->op());
|
||||
}
|
||||
|
||||
#define INPUTS(V) \
|
||||
V(Object, object, 0, Object) \
|
||||
V(Key, key, 1, Object) \
|
||||
V(FeedbackVector, feedback_vector, 2, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
class JSStorePropertyNode final : public JSNodeWrapperBase {
|
||||
public:
|
||||
explicit constexpr JSStorePropertyNode(Node* node) : JSNodeWrapperBase(node) {
|
||||
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSStoreProperty);
|
||||
}
|
||||
|
||||
const PropertyAccess& Parameters() const {
|
||||
return PropertyAccessOf(node()->op());
|
||||
}
|
||||
|
||||
#define INPUTS(V) \
|
||||
V(Object, object, 0, Object) \
|
||||
V(Key, key, 1, Object) \
|
||||
V(Value, value, 2, Object) \
|
||||
V(FeedbackVector, feedback_vector, 3, HeapObject)
|
||||
INPUTS(DEFINE_INPUT_ACCESSORS)
|
||||
#undef INPUTS
|
||||
};
|
||||
|
||||
#undef DEFINE_INPUT_ACCESSORS
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -310,10 +310,70 @@ class NodeWrapper {
|
||||
operator Node*() const { return node_; }
|
||||
Node* operator->() const { return node_; }
|
||||
|
||||
protected:
|
||||
Node* node() const { return node_; }
|
||||
void set_node(Node* node) {
|
||||
DCHECK_NOT_NULL(node);
|
||||
node_ = node;
|
||||
}
|
||||
|
||||
private:
|
||||
Node* node_;
|
||||
};
|
||||
|
||||
// Wrapper classes for special node/edge types (effect, control, frame states).
|
||||
|
||||
class Effect : public NodeWrapper {
|
||||
public:
|
||||
explicit constexpr Effect(Node* node) : NodeWrapper(node) {
|
||||
// TODO(jgruber): Remove the End special case.
|
||||
SLOW_DCHECK(node == nullptr || node->op()->opcode() == IrOpcode::kEnd ||
|
||||
node->op()->EffectOutputCount() > 0);
|
||||
}
|
||||
|
||||
// Support the common `Node* x = effect = ...` pattern.
|
||||
Node* operator=(Node* value) {
|
||||
DCHECK_GT(value->op()->EffectOutputCount(), 0);
|
||||
set_node(value);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
class Control : public NodeWrapper {
|
||||
public:
|
||||
explicit constexpr Control(Node* node) : NodeWrapper(node) {
|
||||
// TODO(jgruber): Remove the End special case.
|
||||
SLOW_DCHECK(node == nullptr || node->opcode() == IrOpcode::kEnd ||
|
||||
node->op()->ControlOutputCount() > 0);
|
||||
}
|
||||
|
||||
// Support the common `Node* x = control = ...` pattern.
|
||||
Node* operator=(Node* value) {
|
||||
DCHECK_GT(value->op()->ControlOutputCount(), 0);
|
||||
set_node(value);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
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.
|
||||
using NodeDeque = ZoneDeque<Node*>;
|
||||
using NodeSet = ZoneSet<Node*>;
|
||||
|
Loading…
Reference in New Issue
Block a user