Commit aa4e381b authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[nci] Add feedback vector as input to binary ops

Following up on previous changes for unary ops:
https://crrev.com/c/2246576

Bug: v8:8888
Change-Id: Ie4dd9a307fb0415e93babf412e3d8d9e86791761
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2257227
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68479}
parent 1052dfb3
...@@ -209,6 +209,7 @@ class BytecodeGraphBuilder { ...@@ -209,6 +209,7 @@ class BytecodeGraphBuilder {
void BuildUnaryOp(const Operator* op); void BuildUnaryOp(const Operator* op);
void BuildBinaryOp(const Operator* op); void BuildBinaryOp(const Operator* op);
void BuildBinaryOpWithImmediate(const Operator* op); void BuildBinaryOpWithImmediate(const Operator* op);
void BuildInstanceOf(const Operator* op);
void BuildCompareOp(const Operator* op); void BuildCompareOp(const Operator* op);
void BuildDelete(LanguageMode language_mode); void BuildDelete(LanguageMode language_mode);
void BuildCastOperator(const Operator* op); void BuildCastOperator(const Operator* op);
...@@ -2759,6 +2760,7 @@ void BytecodeGraphBuilder::VisitThrowSuperAlreadyCalledIfNotHole() { ...@@ -2759,6 +2760,7 @@ void BytecodeGraphBuilder::VisitThrowSuperAlreadyCalledIfNotHole() {
} }
void BytecodeGraphBuilder::BuildUnaryOp(const Operator* op) { void BytecodeGraphBuilder::BuildUnaryOp(const Operator* op) {
DCHECK(JSOperator::IsUnaryWithFeedback(op->opcode()));
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Node* operand = environment()->LookupAccumulator(); Node* operand = environment()->LookupAccumulator();
...@@ -2780,6 +2782,7 @@ void BytecodeGraphBuilder::BuildUnaryOp(const Operator* op) { ...@@ -2780,6 +2782,7 @@ void BytecodeGraphBuilder::BuildUnaryOp(const Operator* op) {
} }
void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) { void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) {
DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode()));
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Node* left = Node* left =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
...@@ -2796,7 +2799,7 @@ void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) { ...@@ -2796,7 +2799,7 @@ void BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) {
node = lowering.value(); node = lowering.value();
} else { } else {
DCHECK(!lowering.Changed()); DCHECK(!lowering.Changed());
node = NewNode(op, left, right); node = NewNode(op, left, right, feedback_vector_node());
} }
environment()->BindAccumulator(node, Environment::kAttachFrameState); environment()->BindAccumulator(node, Environment::kAttachFrameState);
...@@ -2937,6 +2940,7 @@ void BytecodeGraphBuilder::VisitShiftRightLogical() { ...@@ -2937,6 +2940,7 @@ void BytecodeGraphBuilder::VisitShiftRightLogical() {
} }
void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) { void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) {
DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode()));
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Node* left = environment()->LookupAccumulator(); Node* left = environment()->LookupAccumulator();
Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
...@@ -2952,7 +2956,7 @@ void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) { ...@@ -2952,7 +2956,7 @@ void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) {
node = lowering.value(); node = lowering.value();
} else { } else {
DCHECK(!lowering.Changed()); DCHECK(!lowering.Changed());
node = NewNode(op, left, right); node = NewNode(op, left, right, feedback_vector_node());
} }
environment()->BindAccumulator(node, Environment::kAttachFrameState); environment()->BindAccumulator(node, Environment::kAttachFrameState);
} }
...@@ -3073,7 +3077,9 @@ void BytecodeGraphBuilder::VisitGetSuperConstructor() { ...@@ -3073,7 +3077,9 @@ void BytecodeGraphBuilder::VisitGetSuperConstructor() {
Environment::kAttachFrameState); Environment::kAttachFrameState);
} }
void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) { void BytecodeGraphBuilder::BuildInstanceOf(const Operator* op) {
// TODO(jgruber, v8:8888): Treat InstanceOf like other compare ops.
DCHECK_EQ(op->opcode(), IrOpcode::kJSInstanceOf);
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Node* left = Node* left =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
...@@ -3094,6 +3100,28 @@ void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) { ...@@ -3094,6 +3100,28 @@ void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) {
environment()->BindAccumulator(node, Environment::kAttachFrameState); environment()->BindAccumulator(node, Environment::kAttachFrameState);
} }
void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) {
DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode()));
PrepareEagerCheckpoint();
Node* left =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* right = environment()->LookupAccumulator();
FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
JSTypeHintLowering::LoweringResult lowering =
TryBuildSimplifiedBinaryOp(op, left, right, slot);
if (lowering.IsExit()) return;
Node* node = nullptr;
if (lowering.IsSideEffectFree()) {
node = lowering.value();
} else {
DCHECK(!lowering.Changed());
node = NewNode(op, left, right, feedback_vector_node());
}
environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitTestEqual() { void BytecodeGraphBuilder::VisitTestEqual() {
FeedbackSource feedback = CreateFeedbackSource( FeedbackSource feedback = CreateFeedbackSource(
bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
...@@ -3151,7 +3179,7 @@ void BytecodeGraphBuilder::VisitTestIn() { ...@@ -3151,7 +3179,7 @@ void BytecodeGraphBuilder::VisitTestIn() {
void BytecodeGraphBuilder::VisitTestInstanceOf() { void BytecodeGraphBuilder::VisitTestInstanceOf() {
int const slot_index = bytecode_iterator().GetIndexOperand(1); int const slot_index = bytecode_iterator().GetIndexOperand(1);
BuildCompareOp(javascript()->InstanceOf(CreateFeedbackSource(slot_index))); BuildInstanceOf(javascript()->InstanceOf(CreateFeedbackSource(slot_index)));
} }
void BytecodeGraphBuilder::VisitTestUndetectable() { void BytecodeGraphBuilder::VisitTestUndetectable() {
......
...@@ -157,65 +157,71 @@ DEF_UNARY_LOWERING(Increment) ...@@ -157,65 +157,71 @@ DEF_UNARY_LOWERING(Increment)
DEF_UNARY_LOWERING(Negate) DEF_UNARY_LOWERING(Negate)
#undef DEF_UNARY_LOWERING #undef DEF_UNARY_LOWERING
void JSGenericLowering::ReplaceBinaryOrCompareOpWithBuiltinCall( void JSGenericLowering::ReplaceBinaryOpWithBuiltinCall(
Node* node, Builtins::Name builtin_without_feedback, Node* node, Builtins::Name builtin_without_feedback,
Builtins::Name builtin_with_feedback) { Builtins::Name builtin_with_feedback) {
DCHECK(JSOperator::IsBinaryWithFeedback(node->opcode())); DCHECK(JSOperator::IsBinaryWithFeedback(node->opcode()));
Builtins::Name builtin_id; Builtins::Name builtin_id;
const FeedbackParameter& p = FeedbackParameterOf(node->op()); const FeedbackParameter& p = FeedbackParameterOf(node->op());
if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) { if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
Node* slot = jsgraph()->UintPtrConstant(p.feedback().slot.ToInt()); Node* slot = jsgraph()->UintPtrConstant(p.feedback().slot.ToInt());
STATIC_ASSERT(JSBinaryOpNode::LeftIndex() == 0);
STATIC_ASSERT(JSBinaryOpNode::RightIndex() == 1);
STATIC_ASSERT(JSBinaryOpNode::FeedbackVectorIndex() == 2);
DCHECK_EQ(node->op()->ValueInputCount(), 3);
node->InsertInput(zone(), 2, slot); node->InsertInput(zone(), 2, slot);
node->InsertInput(zone(), 3, feedback_vector);
builtin_id = builtin_with_feedback; builtin_id = builtin_with_feedback;
} else { } else {
node->RemoveInput(JSBinaryOpNode::FeedbackVectorIndex());
builtin_id = builtin_without_feedback; builtin_id = builtin_without_feedback;
} }
ReplaceWithBuiltinCall(node, builtin_id); ReplaceWithBuiltinCall(node, builtin_id);
} }
#define DEF_BINARY_OR_COMPARE_LOWERING(Name) \ #define DEF_BINARY_LOWERING(Name) \
void JSGenericLowering::LowerJS##Name(Node* node) { \ void JSGenericLowering::LowerJS##Name(Node* node) { \
ReplaceBinaryOrCompareOpWithBuiltinCall(node, Builtins::k##Name, \ ReplaceBinaryOpWithBuiltinCall(node, Builtins::k##Name, \
Builtins::k##Name##_WithFeedback); \ Builtins::k##Name##_WithFeedback); \
} }
// Binary ops. // Binary ops.
DEF_BINARY_OR_COMPARE_LOWERING(Add) DEF_BINARY_LOWERING(Add)
DEF_BINARY_OR_COMPARE_LOWERING(BitwiseAnd) DEF_BINARY_LOWERING(BitwiseAnd)
DEF_BINARY_OR_COMPARE_LOWERING(BitwiseOr) DEF_BINARY_LOWERING(BitwiseOr)
DEF_BINARY_OR_COMPARE_LOWERING(BitwiseXor) DEF_BINARY_LOWERING(BitwiseXor)
DEF_BINARY_OR_COMPARE_LOWERING(Divide) DEF_BINARY_LOWERING(Divide)
DEF_BINARY_OR_COMPARE_LOWERING(Exponentiate) DEF_BINARY_LOWERING(Exponentiate)
DEF_BINARY_OR_COMPARE_LOWERING(Modulus) DEF_BINARY_LOWERING(Modulus)
DEF_BINARY_OR_COMPARE_LOWERING(Multiply) DEF_BINARY_LOWERING(Multiply)
DEF_BINARY_OR_COMPARE_LOWERING(ShiftLeft) DEF_BINARY_LOWERING(ShiftLeft)
DEF_BINARY_OR_COMPARE_LOWERING(ShiftRight) DEF_BINARY_LOWERING(ShiftRight)
DEF_BINARY_OR_COMPARE_LOWERING(ShiftRightLogical) DEF_BINARY_LOWERING(ShiftRightLogical)
DEF_BINARY_OR_COMPARE_LOWERING(Subtract) DEF_BINARY_LOWERING(Subtract)
// Compare ops. // Compare ops.
DEF_BINARY_OR_COMPARE_LOWERING(Equal) DEF_BINARY_LOWERING(Equal)
DEF_BINARY_OR_COMPARE_LOWERING(GreaterThan) DEF_BINARY_LOWERING(GreaterThan)
DEF_BINARY_OR_COMPARE_LOWERING(GreaterThanOrEqual) DEF_BINARY_LOWERING(GreaterThanOrEqual)
DEF_BINARY_OR_COMPARE_LOWERING(LessThan) DEF_BINARY_LOWERING(LessThan)
DEF_BINARY_OR_COMPARE_LOWERING(LessThanOrEqual) DEF_BINARY_LOWERING(LessThanOrEqual)
#undef DEF_BINARY_OR_COMPARE_LOWERING #undef DEF_BINARY_LOWERING
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());
node->RemoveInput(4); // control node->RemoveInput(NodeProperties::FirstControlIndex(node));
Builtins::Name builtin_id; Builtins::Name builtin_id;
const FeedbackParameter& p = FeedbackParameterOf(node->op()); const FeedbackParameter& p = FeedbackParameterOf(node->op());
if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) { if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
Node* slot = jsgraph()->UintPtrConstant(p.feedback().slot.ToInt()); Node* slot = jsgraph()->UintPtrConstant(p.feedback().slot.ToInt());
STATIC_ASSERT(JSStrictEqualNode::LeftIndex() == 0);
STATIC_ASSERT(JSStrictEqualNode::RightIndex() == 1);
STATIC_ASSERT(JSStrictEqualNode::FeedbackVectorIndex() == 2);
DCHECK_EQ(node->op()->ValueInputCount(), 3);
node->InsertInput(zone(), 2, slot); node->InsertInput(zone(), 2, slot);
node->InsertInput(zone(), 3, feedback_vector);
builtin_id = Builtins::kStrictEqual_WithFeedback; builtin_id = Builtins::kStrictEqual_WithFeedback;
} else { } else {
node->RemoveInput(JSStrictEqualNode::FeedbackVectorIndex());
builtin_id = Builtins::kStrictEqual; builtin_id = Builtins::kStrictEqual;
} }
...@@ -432,6 +438,7 @@ void JSGenericLowering::LowerJSHasInPrototypeChain(Node* node) { ...@@ -432,6 +438,7 @@ void JSGenericLowering::LowerJSHasInPrototypeChain(Node* node) {
} }
void JSGenericLowering::LowerJSInstanceOf(Node* node) { void JSGenericLowering::LowerJSInstanceOf(Node* node) {
// TODO(jgruber, v8:8888): Collect feedback.
ReplaceWithBuiltinCall(node, Builtins::kInstanceOf); ReplaceWithBuiltinCall(node, Builtins::kInstanceOf);
} }
......
...@@ -48,9 +48,9 @@ class JSGenericLowering final : public AdvancedReducer { ...@@ -48,9 +48,9 @@ class JSGenericLowering final : public AdvancedReducer {
void ReplaceUnaryOpWithBuiltinCall(Node* node, void ReplaceUnaryOpWithBuiltinCall(Node* node,
Builtins::Name builtin_without_feedback, Builtins::Name builtin_without_feedback,
Builtins::Name builtin_with_feedback); Builtins::Name builtin_with_feedback);
void ReplaceBinaryOrCompareOpWithBuiltinCall( void ReplaceBinaryOpWithBuiltinCall(Node* node,
Node* node, Builtins::Name builtin_without_feedback, Builtins::Name builtin_without_feedback,
Builtins::Name builtin_with_feedback); Builtins::Name builtin_with_feedback);
Zone* zone() const; Zone* zone() const;
Isolate* isolate() const; Isolate* isolate() const;
......
...@@ -725,7 +725,7 @@ JS_UNOP_WITH_FEEDBACK(UNARY_OP) ...@@ -725,7 +725,7 @@ JS_UNOP_WITH_FEEDBACK(UNARY_OP)
static constexpr auto kProperties = BinopProperties(IrOpcode::k##JSName); \ static constexpr auto kProperties = BinopProperties(IrOpcode::k##JSName); \
FeedbackParameter parameters(feedback); \ FeedbackParameter parameters(feedback); \
return new (zone()) Operator1<FeedbackParameter>( \ return new (zone()) Operator1<FeedbackParameter>( \
IrOpcode::k##JSName, kProperties, #JSName, 2, 1, 1, 1, 1, \ IrOpcode::k##JSName, kProperties, #JSName, 3, 1, 1, 1, 1, \
Operator::ZeroIfNoThrow(kProperties), parameters); \ Operator::ZeroIfNoThrow(kProperties), parameters); \
} }
JS_BINOP_WITH_FEEDBACK(BINARY_OP) JS_BINOP_WITH_FEEDBACK(BINARY_OP)
......
...@@ -81,10 +81,24 @@ class JSUnaryOpNode final : public NodeWrapper { ...@@ -81,10 +81,24 @@ class JSUnaryOpNode final : public NodeWrapper {
static constexpr int FeedbackVectorIndex() { return 1; } static constexpr int FeedbackVectorIndex() { return 1; }
}; };
using JSBitwiseNotNode = JSUnaryOpNode; #define V(JSName, ...) using JSName##Node = JSUnaryOpNode;
using JSDecrementNode = JSUnaryOpNode; JS_UNOP_WITH_FEEDBACK(V)
using JSIncrementNode = JSUnaryOpNode; #undef V
using JSNegateNode = JSUnaryOpNode;
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.
......
...@@ -270,6 +270,10 @@ class JSBinopReduction final { ...@@ -270,6 +270,10 @@ class JSBinopReduction final {
} }
// Remove the inputs corresponding to context, effect, and control. // Remove the inputs corresponding to context, effect, and control.
NodeProperties::RemoveNonValueInputs(node_); NodeProperties::RemoveNonValueInputs(node_);
// Remove the feedback vector input, if applicable.
if (JSOperator::IsBinaryWithFeedback(node_->opcode())) {
node_->RemoveInput(JSBinaryOpNode::FeedbackVectorIndex());
}
// Finally, update the operator to the new one. // Finally, update the operator to the new one.
NodeProperties::ChangeOp(node_, op); NodeProperties::ChangeOp(node_, op);
...@@ -293,7 +297,6 @@ class JSBinopReduction final { ...@@ -293,7 +297,6 @@ class JSBinopReduction final {
DCHECK_EQ(1, node_->op()->EffectInputCount()); DCHECK_EQ(1, node_->op()->EffectInputCount());
DCHECK_EQ(1, node_->op()->EffectOutputCount()); DCHECK_EQ(1, node_->op()->EffectOutputCount());
DCHECK_EQ(1, node_->op()->ControlInputCount()); DCHECK_EQ(1, node_->op()->ControlInputCount());
DCHECK_EQ(2, node_->op()->ValueInputCount());
// Reconnect the control output to bypass the IfSuccess node and // Reconnect the control output to bypass the IfSuccess node and
// possibly disconnect from the IfException node. // possibly disconnect from the IfException node.
...@@ -305,6 +308,11 @@ class JSBinopReduction final { ...@@ -305,6 +308,11 @@ class JSBinopReduction final {
} }
node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
// Remove the feedback vector input, if applicable.
if (JSOperator::IsBinaryWithFeedback(node_->opcode())) {
node_->RemoveInput(JSBinaryOpNode::FeedbackVectorIndex());
}
// Finally, update the operator to the new one.
NodeProperties::ChangeOp(node_, op); NodeProperties::ChangeOp(node_, op);
// Update the type to number. // Update the type to number.
...@@ -455,7 +463,6 @@ Reduction JSTypedLowering::ReduceJSBitwiseNot(Node* node) { ...@@ -455,7 +463,6 @@ Reduction JSTypedLowering::ReduceJSBitwiseNot(Node* node) {
if (input_type.Is(Type::PlainPrimitive())) { if (input_type.Is(Type::PlainPrimitive())) {
// JSBitwiseNot(x) => NumberBitwiseXor(ToInt32(x), -1) // JSBitwiseNot(x) => NumberBitwiseXor(ToInt32(x), -1)
const FeedbackParameter& p = FeedbackParameterOf(node->op()); const FeedbackParameter& p = FeedbackParameterOf(node->op());
node->RemoveInput(JSBitwiseNotNode::FeedbackVectorIndex());
node->InsertInput(graph()->zone(), 1, jsgraph()->SmiConstant(-1)); node->InsertInput(graph()->zone(), 1, jsgraph()->SmiConstant(-1));
NodeProperties::ChangeOp(node, javascript()->BitwiseXor(p.feedback())); NodeProperties::ChangeOp(node, javascript()->BitwiseXor(p.feedback()));
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
...@@ -472,7 +479,6 @@ Reduction JSTypedLowering::ReduceJSDecrement(Node* node) { ...@@ -472,7 +479,6 @@ Reduction JSTypedLowering::ReduceJSDecrement(Node* node) {
if (input_type.Is(Type::PlainPrimitive())) { if (input_type.Is(Type::PlainPrimitive())) {
// JSDecrement(x) => NumberSubtract(ToNumber(x), 1) // JSDecrement(x) => NumberSubtract(ToNumber(x), 1)
const FeedbackParameter& p = FeedbackParameterOf(node->op()); const FeedbackParameter& p = FeedbackParameterOf(node->op());
node->RemoveInput(JSDecrementNode::FeedbackVectorIndex());
node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant()); node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant());
NodeProperties::ChangeOp(node, javascript()->Subtract(p.feedback())); NodeProperties::ChangeOp(node, javascript()->Subtract(p.feedback()));
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
...@@ -489,7 +495,6 @@ Reduction JSTypedLowering::ReduceJSIncrement(Node* node) { ...@@ -489,7 +495,6 @@ Reduction JSTypedLowering::ReduceJSIncrement(Node* node) {
if (input_type.Is(Type::PlainPrimitive())) { if (input_type.Is(Type::PlainPrimitive())) {
// JSIncrement(x) => NumberAdd(ToNumber(x), 1) // JSIncrement(x) => NumberAdd(ToNumber(x), 1)
const FeedbackParameter& p = FeedbackParameterOf(node->op()); const FeedbackParameter& p = FeedbackParameterOf(node->op());
node->RemoveInput(JSIncrementNode::FeedbackVectorIndex());
node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant()); node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant());
NodeProperties::ChangeOp(node, javascript()->Add(p.feedback())); NodeProperties::ChangeOp(node, javascript()->Add(p.feedback()));
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
...@@ -506,7 +511,6 @@ Reduction JSTypedLowering::ReduceJSNegate(Node* node) { ...@@ -506,7 +511,6 @@ Reduction JSTypedLowering::ReduceJSNegate(Node* node) {
if (input_type.Is(Type::PlainPrimitive())) { if (input_type.Is(Type::PlainPrimitive())) {
// JSNegate(x) => NumberMultiply(ToNumber(x), -1) // JSNegate(x) => NumberMultiply(ToNumber(x), -1)
const FeedbackParameter& p = FeedbackParameterOf(node->op()); const FeedbackParameter& p = FeedbackParameterOf(node->op());
node->RemoveInput(JSNegateNode::FeedbackVectorIndex());
node->InsertInput(graph()->zone(), 1, jsgraph()->SmiConstant(-1)); node->InsertInput(graph()->zone(), 1, jsgraph()->SmiConstant(-1));
NodeProperties::ChangeOp(node, javascript()->Multiply(p.feedback())); NodeProperties::ChangeOp(node, javascript()->Multiply(p.feedback()));
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
...@@ -672,6 +676,7 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) { ...@@ -672,6 +676,7 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
callable.descriptor().GetStackParameterCount(), callable.descriptor().GetStackParameterCount(),
CallDescriptor::kNeedsFrameState, properties); CallDescriptor::kNeedsFrameState, properties);
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
node->RemoveInput(JSAddNode::FeedbackVectorIndex());
node->InsertInput(graph()->zone(), 0, node->InsertInput(graph()->zone(), 0,
jsgraph()->HeapConstant(callable.code())); jsgraph()->HeapConstant(callable.code()));
NodeProperties::ChangeOp(node, common()->Call(call_descriptor)); NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
......
...@@ -133,6 +133,9 @@ class JSTypedLoweringTester : public HandleAndZoneScope { ...@@ -133,6 +133,9 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
std::vector<Node*> inputs; std::vector<Node*> inputs;
inputs.push_back(left); inputs.push_back(left);
inputs.push_back(right); inputs.push_back(right);
if (JSOperator::IsBinaryWithFeedback(op->opcode())) {
inputs.push_back(UndefinedConstant()); // Feedback vector.
}
if (OperatorProperties::HasContextInput(op)) { if (OperatorProperties::HasContextInput(op)) {
inputs.push_back(context()); inputs.push_back(context());
} }
...@@ -150,6 +153,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope { ...@@ -150,6 +153,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
} }
Node* Unop(const Operator* op, Node* input) { Node* Unop(const Operator* op, Node* input) {
DCHECK(!JSOperator::IsUnaryWithFeedback(op->opcode()));
// JS unops also require context, effect, and control // JS unops also require context, effect, and control
if (OperatorProperties::GetFrameStateInputCount(op) > 0) { if (OperatorProperties::GetFrameStateInputCount(op) > 0) {
CHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(op)); CHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(op));
...@@ -703,6 +707,7 @@ TEST(RemoveToNumberEffects) { ...@@ -703,6 +707,7 @@ TEST(RemoveToNumberEffects) {
JSTypedLoweringTester R; JSTypedLoweringTester R;
FeedbackSource feedback_source = FeedbackSourceWithOneBinarySlot(&R); FeedbackSource feedback_source = FeedbackSourceWithOneBinarySlot(&R);
Node* feedback = R.UndefinedConstant();
Node* effect_use = nullptr; Node* effect_use = nullptr;
Node* zero = R.graph.NewNode(R.common.NumberConstant(0)); Node* zero = R.graph.NewNode(R.common.NumberConstant(0));
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
...@@ -730,11 +735,12 @@ TEST(RemoveToNumberEffects) { ...@@ -730,11 +735,12 @@ TEST(RemoveToNumberEffects) {
case 3: case 3:
effect_use = effect_use =
R.graph.NewNode(R.javascript.Add(feedback_source), ton, ton, R.graph.NewNode(R.javascript.Add(feedback_source), ton, ton,
R.context(), frame_state, ton, R.start()); feedback, R.context(), frame_state, ton, R.start());
break; break;
case 4: case 4:
effect_use = R.graph.NewNode(R.javascript.Add(feedback_source), p0, p0, effect_use =
R.context(), frame_state, ton, R.start()); R.graph.NewNode(R.javascript.Add(feedback_source), p0, p0, feedback,
R.context(), frame_state, ton, R.start());
break; break;
case 5: case 5:
effect_use = effect_use =
......
...@@ -186,6 +186,7 @@ FeedbackSource FeedbackSourceWithOneCompareSlot(JSTypedLoweringTest* R) { ...@@ -186,6 +186,7 @@ FeedbackSource FeedbackSourceWithOneCompareSlot(JSTypedLoweringTest* R) {
TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) { TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) {
Node* const the_hole = HeapConstant(factory()->the_hole_value()); Node* const the_hole = HeapConstant(factory()->the_hole_value());
Node* const feedback = UndefinedConstant();
Node* const context = UndefinedConstant(); Node* const context = UndefinedConstant();
Node* const effect = graph()->start(); Node* const effect = graph()->start();
Node* const control = graph()->start(); Node* const control = graph()->start();
...@@ -193,7 +194,7 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) { ...@@ -193,7 +194,7 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) {
Node* const lhs = Parameter(type); Node* const lhs = Parameter(type);
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->StrictEqual(FeedbackSourceWithOneCompareSlot(this)), lhs, javascript()->StrictEqual(FeedbackSourceWithOneCompareSlot(this)), lhs,
the_hole, context, effect, control)); the_hole, feedback, context, effect, control));
ASSERT_FALSE(r.Changed()); ASSERT_FALSE(r.Changed());
} }
} }
...@@ -202,12 +203,13 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) { ...@@ -202,12 +203,13 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) {
TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) { TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) {
Node* const lhs = Parameter(Type::Unique(), 0); Node* const lhs = Parameter(Type::Unique(), 0);
Node* const rhs = Parameter(Type::Unique(), 1); Node* const rhs = Parameter(Type::Unique(), 1);
Node* const feedback = UndefinedConstant();
Node* const context = Parameter(Type::Any(), 2); Node* const context = Parameter(Type::Any(), 2);
Node* const effect = graph()->start(); Node* const effect = graph()->start();
Node* const control = graph()->start(); Node* const control = graph()->start();
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->StrictEqual(FeedbackSourceWithOneCompareSlot(this)), lhs, javascript()->StrictEqual(FeedbackSourceWithOneCompareSlot(this)), lhs,
rhs, context, effect, control)); rhs, feedback, context, effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsReferenceEqual(lhs, rhs)); EXPECT_THAT(r.replacement(), IsReferenceEqual(lhs, rhs));
} }
...@@ -218,13 +220,15 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) { ...@@ -218,13 +220,15 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) {
TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) { TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) {
Node* const lhs = Parameter(Type::Signed32()); Node* const lhs = Parameter(Type::Signed32());
Node* const feedback = UndefinedConstant();
Node* const context = UndefinedConstant(); Node* const context = UndefinedConstant();
Node* const effect = graph()->start(); Node* const effect = graph()->start();
Node* const control = graph()->start(); Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) { TRACED_FORRANGE(double, rhs, 0, 31) {
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftLeft(FeedbackSourceWithOneBinarySlot(this)), lhs, javascript()->ShiftLeft(FeedbackSourceWithOneBinarySlot(this)), lhs,
NumberConstant(rhs), context, EmptyFrameState(), effect, control)); NumberConstant(rhs), feedback, context, EmptyFrameState(), effect,
control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), EXPECT_THAT(r.replacement(),
IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs)))); IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
...@@ -234,12 +238,13 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) { ...@@ -234,12 +238,13 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) {
TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) { TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) {
Node* const lhs = Parameter(Type::Signed32()); Node* const lhs = Parameter(Type::Signed32());
Node* const rhs = Parameter(Type::Unsigned32()); Node* const rhs = Parameter(Type::Unsigned32());
Node* const feedback = UndefinedConstant();
Node* const context = UndefinedConstant(); Node* const context = UndefinedConstant();
Node* const effect = graph()->start(); Node* const effect = graph()->start();
Node* const control = graph()->start(); Node* const control = graph()->start();
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftLeft(FeedbackSourceWithOneBinarySlot(this)), lhs, rhs, javascript()->ShiftLeft(FeedbackSourceWithOneBinarySlot(this)), lhs, rhs,
context, EmptyFrameState(), effect, control)); feedback, context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs)); EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
} }
...@@ -251,13 +256,15 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) { ...@@ -251,13 +256,15 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) {
TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) { TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) {
Node* const lhs = Parameter(Type::Signed32()); Node* const lhs = Parameter(Type::Signed32());
Node* const feedback = UndefinedConstant();
Node* const context = UndefinedConstant(); Node* const context = UndefinedConstant();
Node* const effect = graph()->start(); Node* const effect = graph()->start();
Node* const control = graph()->start(); Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) { TRACED_FORRANGE(double, rhs, 0, 31) {
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftRight(FeedbackSourceWithOneBinarySlot(this)), lhs, javascript()->ShiftRight(FeedbackSourceWithOneBinarySlot(this)), lhs,
NumberConstant(rhs), context, EmptyFrameState(), effect, control)); NumberConstant(rhs), feedback, context, EmptyFrameState(), effect,
control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), EXPECT_THAT(r.replacement(),
IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs)))); IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
...@@ -268,12 +275,13 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) { ...@@ -268,12 +275,13 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) {
TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) { TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) {
Node* const lhs = Parameter(Type::Signed32()); Node* const lhs = Parameter(Type::Signed32());
Node* const rhs = Parameter(Type::Unsigned32()); Node* const rhs = Parameter(Type::Unsigned32());
Node* const feedback = UndefinedConstant();
Node* const context = UndefinedConstant(); Node* const context = UndefinedConstant();
Node* const effect = graph()->start(); Node* const effect = graph()->start();
Node* const control = graph()->start(); Node* const control = graph()->start();
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftRight(FeedbackSourceWithOneBinarySlot(this)), lhs, rhs, javascript()->ShiftRight(FeedbackSourceWithOneBinarySlot(this)), lhs, rhs,
context, EmptyFrameState(), effect, control)); feedback, context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs)); EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
} }
...@@ -286,13 +294,15 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) { ...@@ -286,13 +294,15 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) {
TEST_F(JSTypedLoweringTest, TEST_F(JSTypedLoweringTest,
JSShiftRightLogicalWithUnsigned32AndConstant) { JSShiftRightLogicalWithUnsigned32AndConstant) {
Node* const lhs = Parameter(Type::Unsigned32()); Node* const lhs = Parameter(Type::Unsigned32());
Node* const feedback = UndefinedConstant();
Node* const context = UndefinedConstant(); Node* const context = UndefinedConstant();
Node* const effect = graph()->start(); Node* const effect = graph()->start();
Node* const control = graph()->start(); Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) { TRACED_FORRANGE(double, rhs, 0, 31) {
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftRightLogical(FeedbackSourceWithOneBinarySlot(this)), javascript()->ShiftRightLogical(FeedbackSourceWithOneBinarySlot(this)),
lhs, NumberConstant(rhs), context, EmptyFrameState(), effect, control)); lhs, NumberConstant(rhs), feedback, context, EmptyFrameState(), effect,
control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), EXPECT_THAT(r.replacement(),
IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs)))); IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
...@@ -303,12 +313,13 @@ TEST_F(JSTypedLoweringTest, ...@@ -303,12 +313,13 @@ TEST_F(JSTypedLoweringTest,
TEST_F(JSTypedLoweringTest, JSShiftRightLogicalWithUnsigned32AndUnsigned32) { TEST_F(JSTypedLoweringTest, JSShiftRightLogicalWithUnsigned32AndUnsigned32) {
Node* const lhs = Parameter(Type::Unsigned32()); Node* const lhs = Parameter(Type::Unsigned32());
Node* const rhs = Parameter(Type::Unsigned32()); Node* const rhs = Parameter(Type::Unsigned32());
Node* const feedback = UndefinedConstant();
Node* const context = UndefinedConstant(); Node* const context = UndefinedConstant();
Node* const effect = graph()->start(); Node* const effect = graph()->start();
Node* const control = graph()->start(); Node* const control = graph()->start();
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftRightLogical(FeedbackSourceWithOneBinarySlot(this)), javascript()->ShiftRightLogical(FeedbackSourceWithOneBinarySlot(this)),
lhs, rhs, context, EmptyFrameState(), effect, control)); lhs, rhs, feedback, context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs)); EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
} }
...@@ -408,13 +419,14 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedStringLength) { ...@@ -408,13 +419,14 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedStringLength) {
TEST_F(JSTypedLoweringTest, JSAddWithString) { TEST_F(JSTypedLoweringTest, JSAddWithString) {
Node* lhs = Parameter(Type::String(), 0); Node* lhs = Parameter(Type::String(), 0);
Node* rhs = Parameter(Type::String(), 1); Node* rhs = Parameter(Type::String(), 1);
Node* const feedback = UndefinedConstant();
Node* context = Parameter(Type::Any(), 2); Node* context = Parameter(Type::Any(), 2);
Node* frame_state = EmptyFrameState(); Node* frame_state = EmptyFrameState();
Node* effect = graph()->start(); Node* effect = graph()->start();
Node* control = graph()->start(); Node* control = graph()->start();
Reduction r = Reduce( Reduction r = Reduce(graph()->NewNode(
graph()->NewNode(javascript()->Add(FeedbackSourceWithOneBinarySlot(this)), javascript()->Add(FeedbackSourceWithOneBinarySlot(this)), lhs, rhs,
lhs, rhs, context, frame_state, effect, control)); feedback, context, frame_state, effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsStringConcat(_, lhs, rhs)); EXPECT_THAT(r.replacement(), IsStringConcat(_, lhs, rhs));
} }
......
...@@ -88,6 +88,11 @@ class TyperTest : public TypedGraphTest { ...@@ -88,6 +88,11 @@ class TyperTest : public TypedGraphTest {
return NodeProperties::GetType(n); return NodeProperties::GetType(n);
} }
Node* UndefinedConstant() {
Handle<HeapObject> value = isolate()->factory()->undefined_value();
return graph()->NewNode(common()->HeapConstant(value));
}
Type TypeBinaryOp(const Operator* op, Type lhs, Type rhs) { Type TypeBinaryOp(const Operator* op, Type lhs, Type rhs) {
Node* p0 = Parameter(0); Node* p0 = Parameter(0);
Node* p1 = Parameter(1); Node* p1 = Parameter(1);
...@@ -96,6 +101,9 @@ class TyperTest : public TypedGraphTest { ...@@ -96,6 +101,9 @@ class TyperTest : public TypedGraphTest {
std::vector<Node*> inputs; std::vector<Node*> inputs;
inputs.push_back(p0); inputs.push_back(p0);
inputs.push_back(p1); inputs.push_back(p1);
if (JSOperator::IsBinaryWithFeedback(op->opcode())) {
inputs.push_back(UndefinedConstant()); // Feedback vector.
}
if (OperatorProperties::HasContextInput(op)) { if (OperatorProperties::HasContextInput(op)) {
inputs.push_back(context_node_); inputs.push_back(context_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