[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();
|
node = lowering.value();
|
||||||
} else {
|
} else {
|
||||||
DCHECK(!lowering.Changed());
|
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);
|
environment()->BindAccumulator(node, Environment::kAttachFrameState);
|
||||||
}
|
}
|
||||||
@ -2041,7 +2044,11 @@ void BytecodeGraphBuilder::VisitStaKeyedProperty() {
|
|||||||
node = lowering.value();
|
node = lowering.value();
|
||||||
} else {
|
} else {
|
||||||
DCHECK(!lowering.Changed());
|
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);
|
environment()->RecordAfterState(node, Environment::kAttachFrameState);
|
||||||
@ -2177,8 +2184,10 @@ void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
|
|||||||
int const slot_id = bytecode_iterator().GetIndexOperand(1);
|
int const slot_id = bytecode_iterator().GetIndexOperand(1);
|
||||||
FeedbackSource pair = CreateFeedbackSource(slot_id);
|
FeedbackSource pair = CreateFeedbackSource(slot_id);
|
||||||
int literal_flags = bytecode_iterator().GetFlagOperand(2);
|
int literal_flags = bytecode_iterator().GetFlagOperand(2);
|
||||||
|
STATIC_ASSERT(JSCreateLiteralRegExpNode::FeedbackVectorIndex() == 0);
|
||||||
Node* literal = NewNode(javascript()->CreateLiteralRegExp(
|
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);
|
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2197,9 +2206,11 @@ void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
|
|||||||
literal_flags |= ArrayLiteral::kDisableMementos;
|
literal_flags |= ArrayLiteral::kDisableMementos;
|
||||||
int number_of_elements =
|
int number_of_elements =
|
||||||
array_boilerplate_description.constants_elements_length();
|
array_boilerplate_description.constants_elements_length();
|
||||||
Node* literal = NewNode(javascript()->CreateLiteralArray(
|
STATIC_ASSERT(JSCreateLiteralArrayNode::FeedbackVectorIndex() == 0);
|
||||||
array_boilerplate_description.object(), pair, literal_flags,
|
Node* literal = NewNode(
|
||||||
number_of_elements));
|
javascript()->CreateLiteralArray(array_boilerplate_description.object(),
|
||||||
|
pair, literal_flags, number_of_elements),
|
||||||
|
feedback_vector_node());
|
||||||
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2225,8 +2236,11 @@ void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
|
|||||||
int literal_flags =
|
int literal_flags =
|
||||||
interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
|
interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
|
||||||
int number_of_properties = constant_properties.size();
|
int number_of_properties = constant_properties.size();
|
||||||
Node* literal = NewNode(javascript()->CreateLiteralObject(
|
STATIC_ASSERT(JSCreateLiteralObjectNode::FeedbackVectorIndex() == 0);
|
||||||
constant_properties.object(), pair, literal_flags, number_of_properties));
|
Node* literal = NewNode(
|
||||||
|
javascript()->CreateLiteralObject(constant_properties.object(), pair,
|
||||||
|
literal_flags, number_of_properties),
|
||||||
|
feedback_vector_node());
|
||||||
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2243,7 +2257,9 @@ void BytecodeGraphBuilder::VisitCloneObject() {
|
|||||||
int slot = bytecode_iterator().GetIndexOperand(2);
|
int slot = bytecode_iterator().GetIndexOperand(2);
|
||||||
const Operator* op =
|
const Operator* op =
|
||||||
javascript()->CloneObject(CreateFeedbackSource(slot), flags);
|
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);
|
environment()->BindAccumulator(value, Environment::kAttachFrameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2253,8 +2269,11 @@ void BytecodeGraphBuilder::VisitGetTemplateObject() {
|
|||||||
CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
|
CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
|
||||||
TemplateObjectDescriptionRef description(
|
TemplateObjectDescriptionRef description(
|
||||||
broker(), bytecode_iterator().GetConstantForIndexOperand(0, isolate()));
|
broker(), bytecode_iterator().GetConstantForIndexOperand(0, isolate()));
|
||||||
Node* template_object = NewNode(javascript()->GetTemplateObject(
|
STATIC_ASSERT(JSGetTemplateObjectNode::FeedbackVectorIndex() == 0);
|
||||||
description.object(), shared_info().object(), source));
|
Node* template_object =
|
||||||
|
NewNode(javascript()->GetTemplateObject(description.object(),
|
||||||
|
shared_info().object(), source),
|
||||||
|
feedback_vector_node());
|
||||||
environment()->BindAccumulator(template_object);
|
environment()->BindAccumulator(template_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3173,7 +3192,11 @@ void BytecodeGraphBuilder::VisitTestIn() {
|
|||||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
||||||
FeedbackSource feedback =
|
FeedbackSource feedback =
|
||||||
CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1));
|
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);
|
environment()->BindAccumulator(node, Environment::kAttachFrameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3548,7 +3571,9 @@ void BytecodeGraphBuilder::VisitGetIterator() {
|
|||||||
if (lowering.IsExit()) return;
|
if (lowering.IsExit()) return;
|
||||||
|
|
||||||
DCHECK(!lowering.Changed());
|
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);
|
environment()->BindAccumulator(iterator, Environment::kAttachFrameState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,6 +16,11 @@ 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_);
|
||||||
}
|
}
|
||||||
|
@ -140,13 +140,13 @@ size_t hash_value(FrameStateInfo const&);
|
|||||||
|
|
||||||
std::ostream& operator<<(std::ostream&, FrameStateInfo const&);
|
std::ostream& operator<<(std::ostream&, FrameStateInfo const&);
|
||||||
|
|
||||||
static const int kFrameStateParametersInput = 0;
|
static constexpr int kFrameStateParametersInput = 0;
|
||||||
static const int kFrameStateLocalsInput = 1;
|
static constexpr int kFrameStateLocalsInput = 1;
|
||||||
static const int kFrameStateStackInput = 2;
|
static constexpr int kFrameStateStackInput = 2;
|
||||||
static const int kFrameStateContextInput = 3;
|
static constexpr int kFrameStateContextInput = 3;
|
||||||
static const int kFrameStateFunctionInput = 4;
|
static constexpr int kFrameStateFunctionInput = 4;
|
||||||
static const int kFrameStateOuterStateInput = 5;
|
static constexpr int kFrameStateOuterStateInput = 5;
|
||||||
static const int kFrameStateInputCount = kFrameStateOuterStateInput + 1;
|
static constexpr int kFrameStateInputCount = kFrameStateOuterStateInput + 1;
|
||||||
|
|
||||||
enum class ContinuationFrameStateMode { EAGER, LAZY, LAZY_WITH_CATCH };
|
enum class ContinuationFrameStateMode { EAGER, LAZY, LAZY_WITH_CATCH };
|
||||||
|
|
||||||
|
@ -130,37 +130,6 @@ class BasicBlock;
|
|||||||
|
|
||||||
class GraphAssembler;
|
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 };
|
enum class GraphAssemblerLabelType { kDeferred, kNonDeferred, kLoop };
|
||||||
|
|
||||||
// Label with statically known count of incoming branches and phis.
|
// Label with statically known count of incoming branches and phis.
|
||||||
|
@ -3089,9 +3089,9 @@ Reduction JSCallReducer::ReduceReflectHas(Node* node) {
|
|||||||
Node* vtrue;
|
Node* vtrue;
|
||||||
{
|
{
|
||||||
// TODO(magardn): collect feedback so this can be optimized
|
// TODO(magardn): collect feedback so this can be optimized
|
||||||
vtrue = etrue = if_true =
|
vtrue = etrue = if_true = graph()->NewNode(
|
||||||
graph()->NewNode(javascript()->HasProperty(FeedbackSource()), target,
|
javascript()->HasProperty(FeedbackSource()), target, key,
|
||||||
key, context, frame_state, etrue, if_true);
|
jsgraph()->UndefinedConstant(), context, frame_state, etrue, if_true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewire potential exception edges.
|
// Rewire potential exception edges.
|
||||||
|
@ -1088,9 +1088,10 @@ Reduction JSCreateLowering::ReduceJSCreatePromise(Node* node) {
|
|||||||
Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
|
Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
|
||||||
DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
|
DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray ||
|
||||||
node->opcode() == IrOpcode::kJSCreateLiteralObject);
|
node->opcode() == IrOpcode::kJSCreateLiteralObject);
|
||||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
JSCreateLiteralOpNode n(node);
|
||||||
Node* effect = NodeProperties::GetEffectInput(node);
|
CreateLiteralParameters const& p = n.Parameters();
|
||||||
Node* control = NodeProperties::GetControlInput(node);
|
Effect effect = n.effect();
|
||||||
|
Control control = n.control();
|
||||||
ProcessedFeedback const& feedback =
|
ProcessedFeedback const& feedback =
|
||||||
broker()->GetFeedbackForArrayOrObjectLiteral(p.feedback());
|
broker()->GetFeedbackForArrayOrObjectLiteral(p.feedback());
|
||||||
if (!feedback.IsInsufficient()) {
|
if (!feedback.IsInsufficient()) {
|
||||||
@ -1168,10 +1169,10 @@ Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralObject(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
|
Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
|
||||||
DCHECK_EQ(IrOpcode::kJSCreateLiteralRegExp, node->opcode());
|
JSCreateLiteralRegExpNode n(node);
|
||||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
CreateLiteralParameters const& p = n.Parameters();
|
||||||
Node* effect = NodeProperties::GetEffectInput(node);
|
Effect effect = n.effect();
|
||||||
Node* control = NodeProperties::GetControlInput(node);
|
Control control = n.control();
|
||||||
ProcessedFeedback const& feedback =
|
ProcessedFeedback const& feedback =
|
||||||
broker()->GetFeedbackForRegExpLiteral(p.feedback());
|
broker()->GetFeedbackForRegExpLiteral(p.feedback());
|
||||||
if (!feedback.IsInsufficient()) {
|
if (!feedback.IsInsufficient()) {
|
||||||
@ -1184,9 +1185,8 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Reduction JSCreateLowering::ReduceJSGetTemplateObject(Node* node) {
|
Reduction JSCreateLowering::ReduceJSGetTemplateObject(Node* node) {
|
||||||
DCHECK_EQ(IrOpcode::kJSGetTemplateObject, node->opcode());
|
JSGetTemplateObjectNode n(node);
|
||||||
GetTemplateObjectParameters const& parameters =
|
GetTemplateObjectParameters const& parameters = n.Parameters();
|
||||||
GetTemplateObjectParametersOf(node->op());
|
|
||||||
SharedFunctionInfoRef shared(broker(), parameters.shared());
|
SharedFunctionInfoRef shared(broker(), parameters.shared());
|
||||||
JSArrayRef template_object = shared.GetTemplateObject(
|
JSArrayRef template_object = shared.GetTemplateObject(
|
||||||
TemplateObjectDescriptionRef(broker(), parameters.description()),
|
TemplateObjectDescriptionRef(broker(), parameters.description()),
|
||||||
|
@ -60,7 +60,6 @@ Reduction JSGenericLowering::Reduce(Node* node) {
|
|||||||
void JSGenericLowering::LowerJS##Name(Node* node) { \
|
void JSGenericLowering::LowerJS##Name(Node* node) { \
|
||||||
ReplaceWithBuiltinCall(node, Builtins::k##Name); \
|
ReplaceWithBuiltinCall(node, Builtins::k##Name); \
|
||||||
}
|
}
|
||||||
REPLACE_STUB_CALL(HasProperty)
|
|
||||||
REPLACE_STUB_CALL(ToLength)
|
REPLACE_STUB_CALL(ToLength)
|
||||||
REPLACE_STUB_CALL(ToNumber)
|
REPLACE_STUB_CALL(ToNumber)
|
||||||
REPLACE_STUB_CALL(ToNumberConvertBigInt)
|
REPLACE_STUB_CALL(ToNumberConvertBigInt)
|
||||||
@ -208,6 +207,7 @@ DEF_BINARY_LOWERING(LessThanOrEqual)
|
|||||||
void JSGenericLowering::LowerJSStrictEqual(Node* node) {
|
void JSGenericLowering::LowerJSStrictEqual(Node* node) {
|
||||||
// The === operator doesn't need the current context.
|
// The === operator doesn't need the current context.
|
||||||
NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
|
NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
|
||||||
|
DCHECK_EQ(node->op()->ControlInputCount(), 1);
|
||||||
node->RemoveInput(NodeProperties::FirstControlIndex(node));
|
node->RemoveInput(NodeProperties::FirstControlIndex(node));
|
||||||
|
|
||||||
Builtins::Name builtin_id;
|
Builtins::Name builtin_id;
|
||||||
@ -246,20 +246,29 @@ bool ShouldUseMegamorphicLoadBuiltin(FeedbackSource const& source,
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // 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) {
|
void JSGenericLowering::LowerJSLoadProperty(Node* node) {
|
||||||
const PropertyAccess& p = PropertyAccessOf(node->op());
|
JSLoadPropertyNode n(node);
|
||||||
Node* frame_state = NodeProperties::GetFrameStateInput(node);
|
const PropertyAccess& p = n.Parameters();
|
||||||
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
|
FrameState frame_state = n.frame_state();
|
||||||
node->InsertInput(zone(), 2,
|
FrameState outer_state = frame_state.outer_frame_state();
|
||||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
STATIC_ASSERT(n.FeedbackVectorIndex() == 2);
|
||||||
if (outer_state->opcode() != IrOpcode::kFrameState) {
|
if (outer_state->opcode() != IrOpcode::kFrameState) {
|
||||||
|
n->RemoveInput(n.FeedbackVectorIndex());
|
||||||
|
n->InsertInput(zone(), 2,
|
||||||
|
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||||
ReplaceWithBuiltinCall(
|
ReplaceWithBuiltinCall(
|
||||||
node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
|
node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
|
||||||
? Builtins::kKeyedLoadICTrampoline_Megamorphic
|
? Builtins::kKeyedLoadICTrampoline_Megamorphic
|
||||||
: Builtins::kKeyedLoadICTrampoline);
|
: Builtins::kKeyedLoadICTrampoline);
|
||||||
} else {
|
} else {
|
||||||
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
|
n->InsertInput(zone(), 2,
|
||||||
node->InsertInput(zone(), 3, vector);
|
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||||
ReplaceWithBuiltinCall(
|
ReplaceWithBuiltinCall(
|
||||||
node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
|
node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
|
||||||
? Builtins::kKeyedLoadIC_Megamorphic
|
? Builtins::kKeyedLoadIC_Megamorphic
|
||||||
@ -324,30 +333,33 @@ void JSGenericLowering::LowerJSGetIterator(Node* node) {
|
|||||||
// instead of 2 calls resulting from the generic lowering of the LoadNamed
|
// instead of 2 calls resulting from the generic lowering of the LoadNamed
|
||||||
// and Call operators.
|
// and Call operators.
|
||||||
|
|
||||||
GetIteratorParameters const& p = GetIteratorParametersOf(node->op());
|
JSGetIteratorNode n(node);
|
||||||
|
GetIteratorParameters const& p = n.Parameters();
|
||||||
Node* load_slot =
|
Node* load_slot =
|
||||||
jsgraph()->TaggedIndexConstant(p.loadFeedback().slot.ToInt());
|
jsgraph()->TaggedIndexConstant(p.loadFeedback().slot.ToInt());
|
||||||
Node* call_slot =
|
Node* call_slot =
|
||||||
jsgraph()->TaggedIndexConstant(p.callFeedback().slot.ToInt());
|
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(), 1, load_slot);
|
||||||
node->InsertInput(zone(), 2, call_slot);
|
node->InsertInput(zone(), 2, call_slot);
|
||||||
node->InsertInput(zone(), 3, feedback);
|
|
||||||
|
|
||||||
ReplaceWithBuiltinCall(node, Builtins::kGetIteratorWithFeedback);
|
ReplaceWithBuiltinCall(node, Builtins::kGetIteratorWithFeedback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JSGenericLowering::LowerJSStoreProperty(Node* node) {
|
void JSGenericLowering::LowerJSStoreProperty(Node* node) {
|
||||||
PropertyAccess const& p = PropertyAccessOf(node->op());
|
JSStorePropertyNode n(node);
|
||||||
Node* frame_state = NodeProperties::GetFrameStateInput(node);
|
const PropertyAccess& p = n.Parameters();
|
||||||
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
|
FrameState frame_state = n.frame_state();
|
||||||
node->InsertInput(zone(), 3,
|
FrameState outer_state = frame_state.outer_frame_state();
|
||||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
STATIC_ASSERT(n.FeedbackVectorIndex() == 3);
|
||||||
if (outer_state->opcode() != IrOpcode::kFrameState) {
|
if (outer_state->opcode() != IrOpcode::kFrameState) {
|
||||||
|
n->RemoveInput(n.FeedbackVectorIndex());
|
||||||
|
node->InsertInput(zone(), 3,
|
||||||
|
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||||
ReplaceWithBuiltinCall(node, Builtins::kKeyedStoreICTrampoline);
|
ReplaceWithBuiltinCall(node, Builtins::kKeyedStoreICTrampoline);
|
||||||
} else {
|
} else {
|
||||||
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
|
node->InsertInput(zone(), 3,
|
||||||
node->InsertInput(zone(), 4, vector);
|
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||||
ReplaceWithBuiltinCall(node, Builtins::kKeyedStoreIC);
|
ReplaceWithBuiltinCall(node, Builtins::kKeyedStoreIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,13 +607,14 @@ void JSGenericLowering::LowerJSCreateTypedArray(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
|
void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
|
||||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
JSCreateLiteralArrayNode n(node);
|
||||||
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
|
CreateLiteralParameters const& p = n.Parameters();
|
||||||
|
STATIC_ASSERT(n.FeedbackVectorIndex() == 0);
|
||||||
node->InsertInput(zone(), 1,
|
node->InsertInput(zone(), 1,
|
||||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||||
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
|
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.
|
// without properties up to the number of elements that the stubs can handle.
|
||||||
if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
|
if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
|
||||||
p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
|
p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
|
||||||
@ -613,17 +626,19 @@ void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JSGenericLowering::LowerJSGetTemplateObject(Node* node) {
|
void JSGenericLowering::LowerJSGetTemplateObject(Node* node) {
|
||||||
GetTemplateObjectParameters const& p =
|
JSGetTemplateObjectNode n(node);
|
||||||
GetTemplateObjectParametersOf(node->op());
|
GetTemplateObjectParameters const& p = n.Parameters();
|
||||||
SharedFunctionInfoRef shared(broker(), p.shared());
|
SharedFunctionInfoRef shared(broker(), p.shared());
|
||||||
TemplateObjectDescriptionRef description(broker(), p.description());
|
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(), 0, jsgraph()->Constant(shared));
|
||||||
node->InsertInput(zone(), 1, jsgraph()->Constant(description));
|
node->InsertInput(zone(), 1, jsgraph()->Constant(description));
|
||||||
node->InsertInput(zone(), 2,
|
node->InsertInput(zone(), 2,
|
||||||
jsgraph()->UintPtrConstant(p.feedback().index()));
|
jsgraph()->UintPtrConstant(p.feedback().index()));
|
||||||
node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector));
|
|
||||||
node->RemoveInput(6); // control
|
|
||||||
|
|
||||||
ReplaceWithBuiltinCall(node, Builtins::kGetTemplateObject);
|
ReplaceWithBuiltinCall(node, Builtins::kGetTemplateObject);
|
||||||
}
|
}
|
||||||
@ -642,8 +657,9 @@ void JSGenericLowering::LowerJSCreateArrayFromIterable(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
|
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
|
||||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
JSCreateLiteralObjectNode n(node);
|
||||||
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
|
CreateLiteralParameters const& p = n.Parameters();
|
||||||
|
STATIC_ASSERT(n.FeedbackVectorIndex() == 0);
|
||||||
node->InsertInput(zone(), 1,
|
node->InsertInput(zone(), 1,
|
||||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||||
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
|
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
|
||||||
@ -661,11 +677,12 @@ void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JSGenericLowering::LowerJSCloneObject(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(), 1, jsgraph()->SmiConstant(p.flags()));
|
||||||
node->InsertInput(zone(), 2,
|
node->InsertInput(zone(), 2,
|
||||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||||
node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector));
|
|
||||||
ReplaceWithBuiltinCall(node, Builtins::kCloneObjectIC);
|
ReplaceWithBuiltinCall(node, Builtins::kCloneObjectIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,8 +691,9 @@ void JSGenericLowering::LowerJSCreateEmptyLiteralObject(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
|
void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
|
||||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
JSCreateLiteralRegExpNode n(node);
|
||||||
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
|
CreateLiteralParameters const& p = n.Parameters();
|
||||||
|
STATIC_ASSERT(n.FeedbackVectorIndex() == 0);
|
||||||
node->InsertInput(zone(), 1,
|
node->InsertInput(zone(), 1,
|
||||||
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
jsgraph()->TaggedIndexConstant(p.feedback().index()));
|
||||||
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
|
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
|
||||||
|
@ -1358,14 +1358,14 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
|
Reduction JSNativeContextSpecialization::ReduceJSGetIterator(Node* node) {
|
||||||
DCHECK_EQ(IrOpcode::kJSGetIterator, node->opcode());
|
JSGetIteratorNode n(node);
|
||||||
GetIteratorParameters const& p = GetIteratorParametersOf(node->op());
|
GetIteratorParameters const& p = n.Parameters();
|
||||||
|
|
||||||
Node* receiver = NodeProperties::GetValueInput(node, 0);
|
TNode<Object> receiver = n.receiver();
|
||||||
Node* context = NodeProperties::GetContextInput(node);
|
TNode<Object> context = n.context();
|
||||||
Node* frame_state = NodeProperties::GetFrameStateInput(node);
|
FrameState frame_state = n.frame_state();
|
||||||
Node* effect = NodeProperties::GetEffectInput(node);
|
Effect effect = n.effect();
|
||||||
Node* control = NodeProperties::GetControlInput(node);
|
Control control = n.control();
|
||||||
|
|
||||||
// Load iterator property operator
|
// Load iterator property operator
|
||||||
Handle<Name> iterator_symbol = factory()->iterator_symbol();
|
Handle<Name> iterator_symbol = factory()->iterator_symbol();
|
||||||
@ -1895,13 +1895,11 @@ Reduction JSNativeContextSpecialization::ReduceSoftDeoptimize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Reduction JSNativeContextSpecialization::ReduceJSHasProperty(Node* node) {
|
Reduction JSNativeContextSpecialization::ReduceJSHasProperty(Node* node) {
|
||||||
DCHECK_EQ(IrOpcode::kJSHasProperty, node->opcode());
|
JSHasPropertyNode n(node);
|
||||||
PropertyAccess const& p = PropertyAccessOf(node->op());
|
PropertyAccess const& p = n.Parameters();
|
||||||
Node* key = NodeProperties::GetValueInput(node, 1);
|
|
||||||
Node* value = jsgraph()->Dead();
|
Node* value = jsgraph()->Dead();
|
||||||
|
|
||||||
if (!p.feedback().IsValid()) return NoChange();
|
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);
|
FeedbackSource(p.feedback()), AccessMode::kHas);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2012,9 +2010,9 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadPropertyWithEnumeratedKey(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
|
Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
|
||||||
DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode());
|
JSLoadPropertyNode n(node);
|
||||||
PropertyAccess const& p = PropertyAccessOf(node->op());
|
PropertyAccess const& p = n.Parameters();
|
||||||
Node* name = NodeProperties::GetValueInput(node, 1);
|
Node* name = n.key();
|
||||||
|
|
||||||
if (name->opcode() == IrOpcode::kJSForInNext) {
|
if (name->opcode() == IrOpcode::kJSForInNext) {
|
||||||
Reduction reduction = ReduceJSLoadPropertyWithEnumeratedKey(node);
|
Reduction reduction = ReduceJSLoadPropertyWithEnumeratedKey(node);
|
||||||
@ -2028,13 +2026,10 @@ Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
|
Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) {
|
||||||
DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode());
|
JSStorePropertyNode n(node);
|
||||||
PropertyAccess const& p = PropertyAccessOf(node->op());
|
PropertyAccess const& p = n.Parameters();
|
||||||
Node* const key = NodeProperties::GetValueInput(node, 1);
|
|
||||||
Node* const value = NodeProperties::GetValueInput(node, 2);
|
|
||||||
|
|
||||||
if (!p.feedback().IsValid()) return NoChange();
|
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);
|
FeedbackSource(p.feedback()), AccessMode::kStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -890,7 +890,7 @@ const Operator* JSOperatorBuilder::LoadProperty(
|
|||||||
return new (zone()) Operator1<PropertyAccess>( // --
|
return new (zone()) Operator1<PropertyAccess>( // --
|
||||||
IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode
|
IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode
|
||||||
"JSLoadProperty", // name
|
"JSLoadProperty", // name
|
||||||
2, 1, 1, 1, 1, 2, // counts
|
3, 1, 1, 1, 1, 2, // counts
|
||||||
access); // parameter
|
access); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,7 +900,7 @@ const Operator* JSOperatorBuilder::GetIterator(
|
|||||||
return new (zone()) Operator1<GetIteratorParameters>( // --
|
return new (zone()) Operator1<GetIteratorParameters>( // --
|
||||||
IrOpcode::kJSGetIterator, Operator::kNoProperties, // opcode
|
IrOpcode::kJSGetIterator, Operator::kNoProperties, // opcode
|
||||||
"JSGetIterator", // name
|
"JSGetIterator", // name
|
||||||
1, 1, 1, 1, 1, 2, // counts
|
2, 1, 1, 1, 1, 2, // counts
|
||||||
access); // parameter
|
access); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -909,7 +909,7 @@ const Operator* JSOperatorBuilder::HasProperty(FeedbackSource const& feedback) {
|
|||||||
return new (zone()) Operator1<PropertyAccess>( // --
|
return new (zone()) Operator1<PropertyAccess>( // --
|
||||||
IrOpcode::kJSHasProperty, Operator::kNoProperties, // opcode
|
IrOpcode::kJSHasProperty, Operator::kNoProperties, // opcode
|
||||||
"JSHasProperty", // name
|
"JSHasProperty", // name
|
||||||
2, 1, 1, 1, 1, 2, // counts
|
3, 1, 1, 1, 1, 2, // counts
|
||||||
access); // parameter
|
access); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -987,7 +987,7 @@ const Operator* JSOperatorBuilder::StoreProperty(
|
|||||||
return new (zone()) Operator1<PropertyAccess>( // --
|
return new (zone()) Operator1<PropertyAccess>( // --
|
||||||
IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode
|
IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode
|
||||||
"JSStoreProperty", // name
|
"JSStoreProperty", // name
|
||||||
3, 1, 1, 0, 1, 2, // counts
|
4, 1, 1, 0, 1, 2, // counts
|
||||||
access); // parameter
|
access); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1167,7 +1167,7 @@ const Operator* JSOperatorBuilder::CreateLiteralArray(
|
|||||||
IrOpcode::kJSCreateLiteralArray, // opcode
|
IrOpcode::kJSCreateLiteralArray, // opcode
|
||||||
Operator::kNoProperties, // properties
|
Operator::kNoProperties, // properties
|
||||||
"JSCreateLiteralArray", // name
|
"JSCreateLiteralArray", // name
|
||||||
0, 1, 1, 1, 1, 2, // counts
|
1, 1, 1, 1, 1, 2, // counts
|
||||||
parameters); // parameter
|
parameters); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1200,7 +1200,7 @@ const Operator* JSOperatorBuilder::CreateLiteralObject(
|
|||||||
IrOpcode::kJSCreateLiteralObject, // opcode
|
IrOpcode::kJSCreateLiteralObject, // opcode
|
||||||
Operator::kNoProperties, // properties
|
Operator::kNoProperties, // properties
|
||||||
"JSCreateLiteralObject", // name
|
"JSCreateLiteralObject", // name
|
||||||
0, 1, 1, 1, 1, 2, // counts
|
1, 1, 1, 1, 1, 2, // counts
|
||||||
parameters); // parameter
|
parameters); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1212,7 +1212,7 @@ const Operator* JSOperatorBuilder::GetTemplateObject(
|
|||||||
IrOpcode::kJSGetTemplateObject, // opcode
|
IrOpcode::kJSGetTemplateObject, // opcode
|
||||||
Operator::kEliminatable, // properties
|
Operator::kEliminatable, // properties
|
||||||
"JSGetTemplateObject", // name
|
"JSGetTemplateObject", // name
|
||||||
0, 1, 1, 1, 1, 0, // counts
|
1, 1, 1, 1, 1, 0, // counts
|
||||||
parameters); // parameter
|
parameters); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1223,7 +1223,7 @@ const Operator* JSOperatorBuilder::CloneObject(FeedbackSource const& feedback,
|
|||||||
IrOpcode::kJSCloneObject, // opcode
|
IrOpcode::kJSCloneObject, // opcode
|
||||||
Operator::kNoProperties, // properties
|
Operator::kNoProperties, // properties
|
||||||
"JSCloneObject", // name
|
"JSCloneObject", // name
|
||||||
1, 1, 1, 1, 1, 2, // counts
|
2, 1, 1, 1, 1, 2, // counts
|
||||||
parameters); // parameter
|
parameters); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1253,7 +1253,7 @@ const Operator* JSOperatorBuilder::CreateLiteralRegExp(
|
|||||||
IrOpcode::kJSCreateLiteralRegExp, // opcode
|
IrOpcode::kJSCreateLiteralRegExp, // opcode
|
||||||
Operator::kNoProperties, // properties
|
Operator::kNoProperties, // properties
|
||||||
"JSCreateLiteralRegExp", // name
|
"JSCreateLiteralRegExp", // name
|
||||||
0, 1, 1, 1, 1, 2, // counts
|
1, 1, 1, 1, 1, 2, // counts
|
||||||
parameters); // parameter
|
parameters); // parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,10 @@
|
|||||||
#define V8_COMPILER_JS_OPERATOR_H_
|
#define V8_COMPILER_JS_OPERATOR_H_
|
||||||
|
|
||||||
#include "src/base/compiler-specific.h"
|
#include "src/base/compiler-specific.h"
|
||||||
|
#include "src/codegen/tnode.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.h"
|
#include "src/compiler/node.h"
|
||||||
#include "src/compiler/opcodes.h"
|
#include "src/compiler/opcodes.h"
|
||||||
#include "src/handles/maybe-handles.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
|
// Defines the frequency a given Call/Construct site was executed. For some
|
||||||
// call sites the frequency is not known.
|
// call sites the frequency is not known.
|
||||||
class CallFrequency final {
|
class CallFrequency final {
|
||||||
@ -1043,6 +1014,208 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
|
|||||||
DISALLOW_COPY_AND_ASSIGN(JSOperatorBuilder);
|
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 compiler
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -310,10 +310,70 @@ class NodeWrapper {
|
|||||||
operator Node*() const { return node_; }
|
operator Node*() const { return node_; }
|
||||||
Node* operator->() 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:
|
private:
|
||||||
Node* node_;
|
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.
|
// Typedefs to shorten commonly used Node containers.
|
||||||
using NodeDeque = ZoneDeque<Node*>;
|
using NodeDeque = ZoneDeque<Node*>;
|
||||||
using NodeSet = ZoneSet<Node*>;
|
using NodeSet = ZoneSet<Node*>;
|
||||||
|
Loading…
Reference in New Issue
Block a user