Commit 5d417c0d authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[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: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68538}
parent bc8efc9a
......@@ -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*>;
......
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