Commit 8748613f authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[compiler] Hook in binary op builtins with feedback in generic lowering

If --turbo-nci is enabled, use binary op builtins with feedback
collection during generic lowering.

Bug: v8:8888
Change-Id: I307dc742488982bdc68006be5bcd1da8e68768f5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2228614
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68227}
parent 31c66193
This diff is collapsed.
......@@ -61,18 +61,6 @@ Reduction JSGenericLowering::Reduce(Node* node) {
Callable callable = Builtins::CallableFor(isolate(), Builtins::k##Name); \
ReplaceWithStubCall(node, callable, flags); \
}
REPLACE_STUB_CALL(Add)
REPLACE_STUB_CALL(Subtract)
REPLACE_STUB_CALL(Multiply)
REPLACE_STUB_CALL(Divide)
REPLACE_STUB_CALL(Modulus)
REPLACE_STUB_CALL(Exponentiate)
REPLACE_STUB_CALL(BitwiseAnd)
REPLACE_STUB_CALL(BitwiseOr)
REPLACE_STUB_CALL(BitwiseXor)
REPLACE_STUB_CALL(ShiftLeft)
REPLACE_STUB_CALL(ShiftRight)
REPLACE_STUB_CALL(ShiftRightLogical)
REPLACE_STUB_CALL(HasProperty)
REPLACE_STUB_CALL(ToLength)
REPLACE_STUB_CALL(ToNumber)
......@@ -92,8 +80,6 @@ REPLACE_STUB_CALL(RejectPromise)
REPLACE_STUB_CALL(ResolvePromise)
#undef REPLACE_STUB_CALL
// TODO(jgruber): Hook in binary and compare op builtins with feedback.
void JSGenericLowering::ReplaceWithStubCall(Node* node,
Callable callable,
CallDescriptor::Flags flags) {
......@@ -171,14 +157,26 @@ DEF_UNARY_LOWERING(Increment)
DEF_UNARY_LOWERING(Negate)
#undef DEF_UNARY_LOWERING
void JSGenericLowering::ReplaceCompareOpWithBuiltinCall(
void JSGenericLowering::ReplaceBinaryOrCompareOpWithBuiltinCall(
Node* node, Builtins::Name builtin_without_feedback,
Builtins::Name builtin_with_feedback) {
DCHECK(node->opcode() == IrOpcode::kJSEqual ||
DCHECK(node->opcode() == IrOpcode::kJSAdd ||
node->opcode() == IrOpcode::kJSBitwiseAnd ||
node->opcode() == IrOpcode::kJSBitwiseOr ||
node->opcode() == IrOpcode::kJSBitwiseXor ||
node->opcode() == IrOpcode::kJSDivide ||
node->opcode() == IrOpcode::kJSEqual ||
node->opcode() == IrOpcode::kJSExponentiate ||
node->opcode() == IrOpcode::kJSGreaterThan ||
node->opcode() == IrOpcode::kJSGreaterThanOrEqual ||
node->opcode() == IrOpcode::kJSLessThan ||
node->opcode() == IrOpcode::kJSLessThanOrEqual);
node->opcode() == IrOpcode::kJSLessThanOrEqual ||
node->opcode() == IrOpcode::kJSModulus ||
node->opcode() == IrOpcode::kJSMultiply ||
node->opcode() == IrOpcode::kJSShiftLeft ||
node->opcode() == IrOpcode::kJSShiftRight ||
node->opcode() == IrOpcode::kJSShiftRightLogical ||
node->opcode() == IrOpcode::kJSSubtract);
Builtins::Name builtin_id;
const FeedbackParameter& p = FeedbackParameterOf(node->op());
if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
......@@ -196,17 +194,31 @@ void JSGenericLowering::ReplaceCompareOpWithBuiltinCall(
ReplaceWithStubCall(node, callable, flags);
}
#define DEF_COMPARE_LOWERING(Name) \
#define DEF_BINARY_OR_COMPARE_LOWERING(Name) \
void JSGenericLowering::LowerJS##Name(Node* node) { \
ReplaceCompareOpWithBuiltinCall(node, Builtins::k##Name, \
ReplaceBinaryOrCompareOpWithBuiltinCall(node, Builtins::k##Name, \
Builtins::k##Name##_WithFeedback); \
}
DEF_COMPARE_LOWERING(Equal)
DEF_COMPARE_LOWERING(GreaterThan)
DEF_COMPARE_LOWERING(GreaterThanOrEqual)
DEF_COMPARE_LOWERING(LessThan)
DEF_COMPARE_LOWERING(LessThanOrEqual)
#undef DEF_COMPARE_LOWERING
// Binary ops.
DEF_BINARY_OR_COMPARE_LOWERING(Add)
DEF_BINARY_OR_COMPARE_LOWERING(BitwiseAnd)
DEF_BINARY_OR_COMPARE_LOWERING(BitwiseOr)
DEF_BINARY_OR_COMPARE_LOWERING(BitwiseXor)
DEF_BINARY_OR_COMPARE_LOWERING(Divide)
DEF_BINARY_OR_COMPARE_LOWERING(Exponentiate)
DEF_BINARY_OR_COMPARE_LOWERING(Modulus)
DEF_BINARY_OR_COMPARE_LOWERING(Multiply)
DEF_BINARY_OR_COMPARE_LOWERING(ShiftLeft)
DEF_BINARY_OR_COMPARE_LOWERING(ShiftRight)
DEF_BINARY_OR_COMPARE_LOWERING(ShiftRightLogical)
DEF_BINARY_OR_COMPARE_LOWERING(Subtract)
// Compare ops.
DEF_BINARY_OR_COMPARE_LOWERING(Equal)
DEF_BINARY_OR_COMPARE_LOWERING(GreaterThan)
DEF_BINARY_OR_COMPARE_LOWERING(GreaterThanOrEqual)
DEF_BINARY_OR_COMPARE_LOWERING(LessThan)
DEF_BINARY_OR_COMPARE_LOWERING(LessThanOrEqual)
#undef DEF_BINARY_OR_COMPARE_LOWERING
void JSGenericLowering::LowerJSStrictEqual(Node* node) {
// The === operator doesn't need the current context.
......
......@@ -45,8 +45,8 @@ class JSGenericLowering final : public AdvancedReducer {
void ReplaceUnaryOpWithBuiltinCall(Node* node,
Builtins::Name builtin_without_feedback,
Builtins::Name builtin_with_feedback);
void ReplaceCompareOpWithBuiltinCall(Node* node,
Builtins::Name builtin_without_feedback,
void ReplaceBinaryOrCompareOpWithBuiltinCall(
Node* node, Builtins::Name builtin_without_feedback,
Builtins::Name builtin_with_feedback);
Zone* zone() const;
......
......@@ -85,16 +85,38 @@ Reduction JSHeapCopyReducer::Reduce(Node* node) {
}
break;
}
/* Unary ops. */
case IrOpcode::kJSBitwiseNot:
case IrOpcode::kJSDecrement:
case IrOpcode::kJSIncrement:
case IrOpcode::kJSNegate: {
FeedbackParameter const& p = FeedbackParameterOf(node->op());
if (p.feedback().IsValid()) {
// Unary ops are treated as binary ops with respect to feedback.
broker()->ProcessFeedbackForBinaryOperation(p.feedback());
}
break;
}
/* Binary ops. */
case IrOpcode::kJSAdd:
case IrOpcode::kJSSubtract:
case IrOpcode::kJSMultiply:
case IrOpcode::kJSDivide:
case IrOpcode::kJSModulus:
case IrOpcode::kJSExponentiate:
case IrOpcode::kJSBitwiseOr:
case IrOpcode::kJSBitwiseXor:
case IrOpcode::kJSBitwiseAnd:
case IrOpcode::kJSShiftLeft:
case IrOpcode::kJSShiftRight:
case IrOpcode::kJSShiftRightLogical: {
FeedbackParameter const& p = FeedbackParameterOf(node->op());
if (p.feedback().IsValid()) {
broker()->ProcessFeedbackForBinaryOperation(p.feedback());
}
break;
}
/* Compare ops. */
case IrOpcode::kJSEqual:
case IrOpcode::kJSGreaterThan:
case IrOpcode::kJSGreaterThanOrEqual:
......
......@@ -225,21 +225,46 @@ std::ostream& operator<<(std::ostream& os, FeedbackParameter const& p) {
return os << p.feedback();
}
#define UNARY_OP_LIST(V) \
V(BitwiseNot) \
V(Decrement) \
V(Increment) \
V(Negate)
#define BINARY_OP_LIST(V) \
V(Add) \
V(Subtract) \
V(Multiply) \
V(Divide) \
V(Modulus) \
V(Exponentiate) \
V(BitwiseOr) \
V(BitwiseXor) \
V(BitwiseAnd) \
V(ShiftLeft) \
V(ShiftRight) \
V(ShiftRightLogical)
#define COMPARE_OP_LIST(V) \
V(Equal, Operator::kNoProperties) \
V(StrictEqual, Operator::kPure) \
V(LessThan, Operator::kNoProperties) \
V(GreaterThan, Operator::kNoProperties) \
V(LessThanOrEqual, Operator::kNoProperties) \
V(GreaterThanOrEqual, Operator::kNoProperties)
FeedbackParameter const& FeedbackParameterOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kJSBitwiseNot ||
#define V(Name, ...) op->opcode() == IrOpcode::kJS##Name ||
// clang-format off
DCHECK(UNARY_OP_LIST(V)
BINARY_OP_LIST(V)
COMPARE_OP_LIST(V)
op->opcode() == IrOpcode::kJSCreateEmptyLiteralArray ||
op->opcode() == IrOpcode::kJSDecrement ||
op->opcode() == IrOpcode::kJSEqual ||
op->opcode() == IrOpcode::kJSGreaterThan ||
op->opcode() == IrOpcode::kJSGreaterThanOrEqual ||
op->opcode() == IrOpcode::kJSIncrement ||
op->opcode() == IrOpcode::kJSInstanceOf ||
op->opcode() == IrOpcode::kJSLessThan ||
op->opcode() == IrOpcode::kJSLessThanOrEqual ||
op->opcode() == IrOpcode::kJSNegate ||
op->opcode() == IrOpcode::kJSStoreDataPropertyInLiteral ||
op->opcode() == IrOpcode::kJSStoreInArrayLiteral ||
op->opcode() == IrOpcode::kJSStrictEqual);
op->opcode() == IrOpcode::kJSStoreInArrayLiteral);
// clang-format on
#undef V
return OpParameter<FeedbackParameter>(op);
}
......@@ -648,17 +673,6 @@ BinaryOperationHint BinaryOperationHintOf(const Operator* op) {
}
#define CACHED_OP_LIST(V) \
V(BitwiseOr, Operator::kNoProperties, 2, 1) \
V(BitwiseXor, Operator::kNoProperties, 2, 1) \
V(BitwiseAnd, Operator::kNoProperties, 2, 1) \
V(ShiftLeft, Operator::kNoProperties, 2, 1) \
V(ShiftRight, Operator::kNoProperties, 2, 1) \
V(ShiftRightLogical, Operator::kNoProperties, 2, 1) \
V(Subtract, Operator::kNoProperties, 2, 1) \
V(Multiply, Operator::kNoProperties, 2, 1) \
V(Divide, Operator::kNoProperties, 2, 1) \
V(Modulus, Operator::kNoProperties, 2, 1) \
V(Exponentiate, Operator::kNoProperties, 2, 1) \
V(ToLength, Operator::kNoProperties, 1, 1) \
V(ToName, Operator::kNoProperties, 1, 1) \
V(ToNumber, Operator::kNoProperties, 1, 1) \
......@@ -695,22 +709,6 @@ BinaryOperationHint BinaryOperationHintOf(const Operator* op) {
V(ParseInt, Operator::kNoProperties, 2, 1) \
V(RegExpTest, Operator::kNoProperties, 2, 1)
#define UNARY_OP_LIST(V) \
V(BitwiseNot) \
V(Decrement) \
V(Increment) \
V(Negate)
#define BINARY_OP_LIST(V) V(Add)
#define COMPARE_OP_LIST(V) \
V(Equal, Operator::kNoProperties) \
V(GreaterThan, Operator::kNoProperties) \
V(GreaterThanOrEqual, Operator::kNoProperties) \
V(LessThan, Operator::kNoProperties) \
V(LessThanOrEqual, Operator::kNoProperties) \
V(StrictEqual, Operator::kPure)
struct JSOperatorGlobalCache final {
#define CACHED_OP(Name, properties, value_input_count, value_output_count) \
struct Name##Operator final : public Operator { \
......@@ -724,29 +722,6 @@ struct JSOperatorGlobalCache final {
Name##Operator k##Name##Operator;
CACHED_OP_LIST(CACHED_OP)
#undef CACHED_OP
#define BINARY_OP(Name) \
template <BinaryOperationHint kHint> \
struct Name##Operator final : public Operator1<BinaryOperationHint> { \
Name##Operator() \
: Operator1<BinaryOperationHint>(IrOpcode::kJS##Name, \
Operator::kNoProperties, "JS" #Name, \
2, 1, 1, 1, 1, 2, kHint) {} \
}; \
Name##Operator<BinaryOperationHint::kNone> k##Name##NoneOperator; \
Name##Operator<BinaryOperationHint::kSignedSmall> \
k##Name##SignedSmallOperator; \
Name##Operator<BinaryOperationHint::kSignedSmallInputs> \
k##Name##SignedSmallInputsOperator; \
Name##Operator<BinaryOperationHint::kSigned32> k##Name##Signed32Operator; \
Name##Operator<BinaryOperationHint::kNumber> k##Name##NumberOperator; \
Name##Operator<BinaryOperationHint::kNumberOrOddball> \
k##Name##NumberOrOddballOperator; \
Name##Operator<BinaryOperationHint::kString> k##Name##StringOperator; \
Name##Operator<BinaryOperationHint::kBigInt> k##Name##BigIntOperator; \
Name##Operator<BinaryOperationHint::kAny> k##Name##AnyOperator;
BINARY_OP_LIST(BINARY_OP)
#undef BINARY_OP
};
namespace {
......@@ -763,34 +738,6 @@ JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
CACHED_OP_LIST(CACHED_OP)
#undef CACHED_OP
#define BINARY_OP(Name) \
const Operator* JSOperatorBuilder::Name(BinaryOperationHint hint) { \
switch (hint) { \
case BinaryOperationHint::kNone: \
return &cache_.k##Name##NoneOperator; \
case BinaryOperationHint::kSignedSmall: \
return &cache_.k##Name##SignedSmallOperator; \
case BinaryOperationHint::kSignedSmallInputs: \
return &cache_.k##Name##SignedSmallInputsOperator; \
case BinaryOperationHint::kSigned32: \
return &cache_.k##Name##Signed32Operator; \
case BinaryOperationHint::kNumber: \
return &cache_.k##Name##NumberOperator; \
case BinaryOperationHint::kNumberOrOddball: \
return &cache_.k##Name##NumberOrOddballOperator; \
case BinaryOperationHint::kString: \
return &cache_.k##Name##StringOperator; \
case BinaryOperationHint::kBigInt: \
return &cache_.k##Name##BigIntOperator; \
case BinaryOperationHint::kAny: \
return &cache_.k##Name##AnyOperator; \
} \
UNREACHABLE(); \
return nullptr; \
}
BINARY_OP_LIST(BINARY_OP)
#undef BINARY_OP
#define UNARY_OP(Name) \
const Operator* JSOperatorBuilder::Name(FeedbackSource const& feedback) { \
FeedbackParameter parameters(feedback); \
......@@ -801,6 +748,16 @@ BINARY_OP_LIST(BINARY_OP)
UNARY_OP_LIST(UNARY_OP)
#undef UNARY_OP
#define BINARY_OP(Name) \
const Operator* JSOperatorBuilder::Name(FeedbackSource const& feedback) { \
FeedbackParameter parameters(feedback); \
return new (zone()) Operator1<FeedbackParameter>( \
IrOpcode::kJS##Name, Operator::kNoProperties, "JS" #Name, 2, 1, 1, 1, \
1, 2, parameters); \
}
BINARY_OP_LIST(BINARY_OP)
#undef BINARY_OP
#define COMPARE_OP(Name, Properties) \
const Operator* JSOperatorBuilder::Name(FeedbackSource const& feedback) { \
FeedbackParameter parameters(feedback); \
......
......@@ -784,18 +784,18 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* LessThanOrEqual(FeedbackSource const& feedback);
const Operator* GreaterThanOrEqual(FeedbackSource const& feedback);
const Operator* BitwiseOr();
const Operator* BitwiseXor();
const Operator* BitwiseAnd();
const Operator* ShiftLeft();
const Operator* ShiftRight();
const Operator* ShiftRightLogical();
const Operator* Add(BinaryOperationHint hint);
const Operator* Subtract();
const Operator* Multiply();
const Operator* Divide();
const Operator* Modulus();
const Operator* Exponentiate();
const Operator* BitwiseOr(FeedbackSource const& feedback);
const Operator* BitwiseXor(FeedbackSource const& feedback);
const Operator* BitwiseAnd(FeedbackSource const& feedback);
const Operator* ShiftLeft(FeedbackSource const& feedback);
const Operator* ShiftRight(FeedbackSource const& feedback);
const Operator* ShiftRightLogical(FeedbackSource const& feedback);
const Operator* Add(FeedbackSource const& feedback);
const Operator* Subtract(FeedbackSource const& feedback);
const Operator* Multiply(FeedbackSource const& feedback);
const Operator* Divide(FeedbackSource const& feedback);
const Operator* Modulus(FeedbackSource const& feedback);
const Operator* Exponentiate(FeedbackSource const& feedback);
const Operator* BitwiseNot(FeedbackSource const& feedback);
const Operator* Decrement(FeedbackSource const& feedback);
......
......@@ -285,31 +285,33 @@ JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceUnaryOperation(
return LoweringResult::Exit(node);
}
// Note: Unary and binary operations collect the same kind of feedback.
FeedbackSource feedback(feedback_vector(), slot);
Node* node;
switch (op->opcode()) {
case IrOpcode::kJSBitwiseNot: {
// Lower to a speculative xor with -1 if we have some kind of Number
// feedback.
JSSpeculativeBinopBuilder b(this, jsgraph()->javascript()->BitwiseXor(),
operand, jsgraph()->SmiConstant(-1), effect,
control, slot);
JSSpeculativeBinopBuilder b(
this, jsgraph()->javascript()->BitwiseXor(feedback), operand,
jsgraph()->SmiConstant(-1), effect, control, slot);
node = b.TryBuildNumberBinop();
break;
}
case IrOpcode::kJSDecrement: {
// Lower to a speculative subtraction of 1 if we have some kind of Number
// feedback.
JSSpeculativeBinopBuilder b(this, jsgraph()->javascript()->Subtract(),
operand, jsgraph()->SmiConstant(1), effect,
control, slot);
JSSpeculativeBinopBuilder b(
this, jsgraph()->javascript()->Subtract(feedback), operand,
jsgraph()->SmiConstant(1), effect, control, slot);
node = b.TryBuildNumberBinop();
break;
}
case IrOpcode::kJSIncrement: {
// Lower to a speculative addition of 1 if we have some kind of Number
// feedback.
BinaryOperationHint hint = BinaryOperationHint::kAny; // Dummy.
JSSpeculativeBinopBuilder b(this, jsgraph()->javascript()->Add(hint),
JSSpeculativeBinopBuilder b(this, jsgraph()->javascript()->Add(feedback),
operand, jsgraph()->SmiConstant(1), effect,
control, slot);
node = b.TryBuildNumberBinop();
......@@ -318,9 +320,9 @@ JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceUnaryOperation(
case IrOpcode::kJSNegate: {
// Lower to a speculative multiplication with -1 if we have some kind of
// Number feedback.
JSSpeculativeBinopBuilder b(this, jsgraph()->javascript()->Multiply(),
operand, jsgraph()->SmiConstant(-1), effect,
control, slot);
JSSpeculativeBinopBuilder b(
this, jsgraph()->javascript()->Multiply(feedback), operand,
jsgraph()->SmiConstant(-1), effect, control, slot);
node = b.TryBuildNumberBinop();
if (!node) {
if (GetBinaryOperationHint(slot) == BinaryOperationHint::kBigInt) {
......
......@@ -449,8 +449,9 @@ Reduction JSTypedLowering::ReduceJSBitwiseNot(Node* node) {
Type input_type = NodeProperties::GetType(input);
if (input_type.Is(Type::PlainPrimitive())) {
// JSBitwiseNot(x) => NumberBitwiseXor(ToInt32(x), -1)
const FeedbackParameter& p = FeedbackParameterOf(node->op());
node->InsertInput(graph()->zone(), 1, jsgraph()->SmiConstant(-1));
NodeProperties::ChangeOp(node, javascript()->BitwiseXor());
NodeProperties::ChangeOp(node, javascript()->BitwiseXor(p.feedback()));
JSBinopReduction r(this, node);
r.ConvertInputsToNumber();
r.ConvertInputsToUI32(kSigned, kSigned);
......@@ -464,8 +465,9 @@ Reduction JSTypedLowering::ReduceJSDecrement(Node* node) {
Type input_type = NodeProperties::GetType(input);
if (input_type.Is(Type::PlainPrimitive())) {
// JSDecrement(x) => NumberSubtract(ToNumber(x), 1)
const FeedbackParameter& p = FeedbackParameterOf(node->op());
node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant());
NodeProperties::ChangeOp(node, javascript()->Subtract());
NodeProperties::ChangeOp(node, javascript()->Subtract(p.feedback()));
JSBinopReduction r(this, node);
r.ConvertInputsToNumber();
DCHECK_EQ(simplified()->NumberSubtract(), r.NumberOp());
......@@ -479,9 +481,9 @@ Reduction JSTypedLowering::ReduceJSIncrement(Node* node) {
Type input_type = NodeProperties::GetType(input);
if (input_type.Is(Type::PlainPrimitive())) {
// JSIncrement(x) => NumberAdd(ToNumber(x), 1)
const FeedbackParameter& p = FeedbackParameterOf(node->op());
node->InsertInput(graph()->zone(), 1, jsgraph()->OneConstant());
BinaryOperationHint hint = BinaryOperationHint::kAny; // Dummy.
NodeProperties::ChangeOp(node, javascript()->Add(hint));
NodeProperties::ChangeOp(node, javascript()->Add(p.feedback()));
JSBinopReduction r(this, node);
r.ConvertInputsToNumber();
DCHECK_EQ(simplified()->NumberAdd(), r.NumberOp());
......@@ -495,8 +497,9 @@ Reduction JSTypedLowering::ReduceJSNegate(Node* node) {
Type input_type = NodeProperties::GetType(input);
if (input_type.Is(Type::PlainPrimitive())) {
// JSNegate(x) => NumberMultiply(ToNumber(x), -1)
const FeedbackParameter& p = FeedbackParameterOf(node->op());
node->InsertInput(graph()->zone(), 1, jsgraph()->SmiConstant(-1));
NodeProperties::ChangeOp(node, javascript()->Multiply());
NodeProperties::ChangeOp(node, javascript()->Multiply(p.feedback()));
JSBinopReduction r(this, node);
r.ConvertInputsToNumber();
return r.ChangeToPureOperator(r.NumberOp(), Type::Number());
......
......@@ -324,13 +324,11 @@ Handle<FeedbackVector> FeedbackVector::New(
return result;
}
// static
Handle<FeedbackVector> FeedbackVector::NewWithOneCompareSlotForTesting(
Zone* zone, Isolate* isolate) {
FeedbackVectorSpec one_slot(zone);
one_slot.AddCompareICSlot();
namespace {
Handle<FeedbackMetadata> metadata = FeedbackMetadata::New(isolate, &one_slot);
Handle<FeedbackVector> NewFeedbackVectorForTesting(
Isolate* isolate, const FeedbackVectorSpec* spec) {
Handle<FeedbackMetadata> metadata = FeedbackMetadata::New(isolate, spec);
Handle<SharedFunctionInfo> shared =
isolate->factory()->NewSharedFunctionInfoForBuiltin(
isolate->factory()->empty_string(), Builtins::kIllegal);
......@@ -345,6 +343,24 @@ Handle<FeedbackVector> FeedbackVector::NewWithOneCompareSlotForTesting(
&is_compiled_scope);
}
} // namespace
// static
Handle<FeedbackVector> FeedbackVector::NewWithOneBinarySlotForTesting(
Zone* zone, Isolate* isolate) {
FeedbackVectorSpec one_slot(zone);
one_slot.AddBinaryOpICSlot();
return NewFeedbackVectorForTesting(isolate, &one_slot);
}
// static
Handle<FeedbackVector> FeedbackVector::NewWithOneCompareSlotForTesting(
Zone* zone, Isolate* isolate) {
FeedbackVectorSpec one_slot(zone);
one_slot.AddCompareICSlot();
return NewFeedbackVectorForTesting(isolate, &one_slot);
}
// static
void FeedbackVector::AddToVectorsForProfilingTools(
Isolate* isolate, Handle<FeedbackVector> vector) {
......
......@@ -265,6 +265,8 @@ class FeedbackVector : public HeapObject {
Handle<ClosureFeedbackCellArray> closure_feedback_cell_array,
IsCompiledScope* is_compiled_scope);
V8_EXPORT_PRIVATE static Handle<FeedbackVector>
NewWithOneBinarySlotForTesting(Zone* zone, Isolate* isolate);
V8_EXPORT_PRIVATE static Handle<FeedbackVector>
NewWithOneCompareSlotForTesting(Zone* zone, Isolate* isolate);
......
......@@ -55,7 +55,6 @@ class JSTypedLoweringTester : public HandleAndZoneScope {
Graph graph;
Typer typer;
Node* context_node;
BinaryOperationHint const binop_hints = BinaryOperationHint::kAny;
Node* Parameter(Type t, int32_t index = 0) {
Node* n = graph.NewNode(common.Parameter(index), graph.start());
......@@ -218,6 +217,21 @@ static IrOpcode::Value NumberToI32(bool is_signed) {
return is_signed ? IrOpcode::kNumberToInt32 : IrOpcode::kNumberToUint32;
}
namespace {
FeedbackSource FeedbackSourceWithOneBinarySlot(JSTypedLoweringTester* R) {
return FeedbackSource{FeedbackVector::NewWithOneBinarySlotForTesting(
R->main_zone(), R->main_isolate()),
FeedbackSlot{0}};
}
FeedbackSource FeedbackSourceWithOneCompareSlot(JSTypedLoweringTester* R) {
return FeedbackSource{FeedbackVector::NewWithOneCompareSlotForTesting(
R->main_zone(), R->main_isolate()),
FeedbackSlot{0}};
}
} // namespace
TEST(StringBinops) {
JSTypedLoweringTester R;
......@@ -228,7 +242,8 @@ TEST(StringBinops) {
for (size_t j = 0; j < arraysize(kStringTypes); ++j) {
Node* p1 = R.Parameter(kStringTypes[j], 1);
Node* add = R.Binop(R.javascript.Add(BinaryOperationHint::kAny), p0, p1);
Node* add = R.Binop(R.javascript.Add(FeedbackSourceWithOneBinarySlot(&R)),
p0, p1);
Node* r = R.reduce(add);
R.CheckBinop(IrOpcode::kStringConcat, r);
......@@ -243,7 +258,8 @@ TEST(AddNumber1) {
for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
Node* p0 = R.Parameter(kNumberTypes[i], 0);
Node* p1 = R.Parameter(kNumberTypes[i], 1);
Node* add = R.Binop(R.javascript.Add(BinaryOperationHint::kAny), p0, p1);
Node* add =
R.Binop(R.javascript.Add(FeedbackSourceWithOneBinarySlot(&R)), p0, p1);
Node* r = R.reduce(add);
R.CheckBinop(IrOpcode::kNumberAdd, r);
......@@ -254,12 +270,13 @@ TEST(AddNumber1) {
TEST(NumberBinops) {
JSTypedLoweringTester R;
FeedbackSource feedback_source = FeedbackSourceWithOneBinarySlot(&R);
const Operator* ops[] = {
R.javascript.Add(R.binop_hints), R.simplified.NumberAdd(),
R.javascript.Subtract(), R.simplified.NumberSubtract(),
R.javascript.Multiply(), R.simplified.NumberMultiply(),
R.javascript.Divide(), R.simplified.NumberDivide(),
R.javascript.Modulus(), R.simplified.NumberModulus(),
R.javascript.Add(feedback_source), R.simplified.NumberAdd(),
R.javascript.Subtract(feedback_source), R.simplified.NumberSubtract(),
R.javascript.Multiply(feedback_source), R.simplified.NumberMultiply(),
R.javascript.Divide(feedback_source), R.simplified.NumberDivide(),
R.javascript.Modulus(feedback_source), R.simplified.NumberModulus(),
};
for (size_t i = 0; i < arraysize(kNumberTypes); ++i) {
......@@ -301,11 +318,12 @@ class JSBitwiseShiftTypedLoweringTester : public JSTypedLoweringTester {
public:
JSBitwiseShiftTypedLoweringTester() : JSTypedLoweringTester() {
int i = 0;
set(i++, javascript.ShiftLeft(), true);
FeedbackSource feedback_source = FeedbackSourceWithOneBinarySlot(this);
set(i++, javascript.ShiftLeft(feedback_source), true);
set(i++, simplified.NumberShiftLeft(), false);
set(i++, javascript.ShiftRight(), true);
set(i++, javascript.ShiftRight(feedback_source), true);
set(i++, simplified.NumberShiftRight(), false);
set(i++, javascript.ShiftRightLogical(), false);
set(i++, javascript.ShiftRightLogical(feedback_source), false);
set(i++, simplified.NumberShiftRightLogical(), false);
}
static const int kNumberOps = 6;
......@@ -357,11 +375,12 @@ class JSBitwiseTypedLoweringTester : public JSTypedLoweringTester {
public:
JSBitwiseTypedLoweringTester() : JSTypedLoweringTester() {
int i = 0;
set(i++, javascript.BitwiseOr(), true);
FeedbackSource feedback_source = FeedbackSourceWithOneBinarySlot(this);
set(i++, javascript.BitwiseOr(feedback_source), true);
set(i++, simplified.NumberBitwiseOr(), true);
set(i++, javascript.BitwiseXor(), true);
set(i++, javascript.BitwiseXor(feedback_source), true);
set(i++, simplified.NumberBitwiseXor(), true);
set(i++, javascript.BitwiseAnd(), true);
set(i++, javascript.BitwiseAnd(feedback_source), true);
set(i++, simplified.NumberBitwiseAnd(), true);
}
static const int kNumberOps = 6;
......@@ -566,16 +585,6 @@ TEST(JSToString_replacement) {
}
}
namespace {
FeedbackSource FeedbackSourceWithOneCompareSlot(JSTypedLoweringTester* R) {
return FeedbackSource{FeedbackVector::NewWithOneCompareSlotForTesting(
R->main_zone(), R->main_isolate()),
FeedbackSlot{0}};
}
} // namespace
TEST(StringComparison) {
JSTypedLoweringTester R;
FeedbackSource feedback_source = FeedbackSourceWithOneCompareSlot(&R);
......@@ -693,6 +702,7 @@ TEST(MixedComparison1) {
TEST(RemoveToNumberEffects) {
JSTypedLoweringTester R;
FeedbackSource feedback_source = FeedbackSourceWithOneBinarySlot(&R);
Node* effect_use = nullptr;
Node* zero = R.graph.NewNode(R.common.NumberConstant(0));
for (int i = 0; i < 10; i++) {
......@@ -718,11 +728,12 @@ TEST(RemoveToNumberEffects) {
effect_use = R.graph.NewNode(R.common.EffectPhi(1), ton, R.start());
break;
case 3:
effect_use = R.graph.NewNode(R.javascript.Add(R.binop_hints), ton, ton,
effect_use =
R.graph.NewNode(R.javascript.Add(feedback_source), ton, ton,
R.context(), frame_state, ton, R.start());
break;
case 4:
effect_use = R.graph.NewNode(R.javascript.Add(R.binop_hints), p0, p0,
effect_use = R.graph.NewNode(R.javascript.Add(feedback_source), p0, p0,
R.context(), frame_state, ton, R.start());
break;
case 5:
......@@ -882,24 +893,25 @@ TEST(StringEquality) {
TEST(RemovePureNumberBinopEffects) {
JSTypedLoweringTester R;
FeedbackSource feedback_source = FeedbackSourceWithOneCompareSlot(&R);
FeedbackSource binary_source = FeedbackSourceWithOneBinarySlot(&R);
FeedbackSource compare_source = FeedbackSourceWithOneCompareSlot(&R);
const Operator* ops[] = {
R.javascript.Equal(feedback_source),
R.javascript.Equal(compare_source),
R.simplified.NumberEqual(),
R.javascript.Add(R.binop_hints),
R.javascript.Add(binary_source),
R.simplified.NumberAdd(),
R.javascript.Subtract(),
R.javascript.Subtract(binary_source),
R.simplified.NumberSubtract(),
R.javascript.Multiply(),
R.javascript.Multiply(binary_source),
R.simplified.NumberMultiply(),
R.javascript.Divide(),
R.javascript.Divide(binary_source),
R.simplified.NumberDivide(),
R.javascript.Modulus(),
R.javascript.Modulus(binary_source),
R.simplified.NumberModulus(),
R.javascript.LessThan(feedback_source),
R.javascript.LessThan(compare_source),
R.simplified.NumberLessThan(),
R.javascript.LessThanOrEqual(feedback_source),
R.javascript.LessThanOrEqual(compare_source),
R.simplified.NumberLessThanOrEqual(),
};
......
......@@ -166,6 +166,12 @@ TEST_F(JSTypedLoweringTest, JSToStringWithBoolean) {
namespace {
FeedbackSource FeedbackSourceWithOneBinarySlot(JSTypedLoweringTest* R) {
return FeedbackSource{
FeedbackVector::NewWithOneBinarySlotForTesting(R->zone(), R->isolate()),
FeedbackSlot{0}};
}
FeedbackSource FeedbackSourceWithOneCompareSlot(JSTypedLoweringTest* R) {
return FeedbackSource{
FeedbackVector::NewWithOneCompareSlotForTesting(R->zone(), R->isolate()),
......@@ -212,9 +218,9 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndConstant) {
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) {
Reduction r = Reduce(graph()->NewNode(javascript()->ShiftLeft(), lhs,
NumberConstant(rhs), context,
EmptyFrameState(), effect, control));
Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftLeft(FeedbackSourceWithOneBinarySlot(this)), lhs,
NumberConstant(rhs), context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsNumberShiftLeft(lhs, IsNumberConstant(BitEq(rhs))));
......@@ -227,9 +233,9 @@ TEST_F(JSTypedLoweringTest, JSShiftLeftWithSigned32AndUnsigned32) {
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r =
Reduce(graph()->NewNode(javascript()->ShiftLeft(), lhs, rhs, context,
EmptyFrameState(), effect, control));
Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftLeft(FeedbackSourceWithOneBinarySlot(this)), lhs, rhs,
context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberShiftLeft(lhs, rhs));
}
......@@ -245,9 +251,9 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndConstant) {
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) {
Reduction r = Reduce(graph()->NewNode(javascript()->ShiftRight(), lhs,
NumberConstant(rhs), context,
EmptyFrameState(), effect, control));
Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftRight(FeedbackSourceWithOneBinarySlot(this)), lhs,
NumberConstant(rhs), context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsNumberShiftRight(lhs, IsNumberConstant(BitEq(rhs))));
......@@ -261,9 +267,9 @@ TEST_F(JSTypedLoweringTest, JSShiftRightWithSigned32AndUnsigned32) {
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r =
Reduce(graph()->NewNode(javascript()->ShiftRight(), lhs, rhs, context,
EmptyFrameState(), effect, control));
Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftRight(FeedbackSourceWithOneBinarySlot(this)), lhs, rhs,
context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberShiftRight(lhs, rhs));
}
......@@ -280,9 +286,9 @@ TEST_F(JSTypedLoweringTest,
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FORRANGE(double, rhs, 0, 31) {
Reduction r = Reduce(graph()->NewNode(javascript()->ShiftRightLogical(),
lhs, NumberConstant(rhs), context,
EmptyFrameState(), effect, control));
Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftRightLogical(FeedbackSourceWithOneBinarySlot(this)),
lhs, NumberConstant(rhs), context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsNumberShiftRightLogical(lhs, IsNumberConstant(BitEq(rhs))));
......@@ -296,9 +302,9 @@ TEST_F(JSTypedLoweringTest, JSShiftRightLogicalWithUnsigned32AndUnsigned32) {
Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r =
Reduce(graph()->NewNode(javascript()->ShiftRightLogical(), lhs, rhs,
context, EmptyFrameState(), effect, control));
Reduction r = Reduce(graph()->NewNode(
javascript()->ShiftRightLogical(FeedbackSourceWithOneBinarySlot(this)),
lhs, rhs, context, EmptyFrameState(), effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberShiftRightLogical(lhs, rhs));
}
......@@ -396,15 +402,15 @@ TEST_F(JSTypedLoweringTest, JSLoadNamedStringLength) {
TEST_F(JSTypedLoweringTest, JSAddWithString) {
BinaryOperationHint const hint = BinaryOperationHint::kAny;
Node* lhs = Parameter(Type::String(), 0);
Node* rhs = Parameter(Type::String(), 1);
Node* context = Parameter(Type::Any(), 2);
Node* frame_state = EmptyFrameState();
Node* effect = graph()->start();
Node* control = graph()->start();
Reduction r = Reduce(graph()->NewNode(javascript()->Add(hint), lhs, rhs,
context, frame_state, effect, control));
Reduction r = Reduce(
graph()->NewNode(javascript()->Add(FeedbackSourceWithOneBinarySlot(this)),
lhs, rhs, context, frame_state, effect, control));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsStringConcat(_, lhs, rhs));
}
......
......@@ -61,7 +61,6 @@ class TyperTest : public TypedGraphTest {
Types types_;
JSOperatorBuilder javascript_;
SimplifiedOperatorBuilder simplified_;
BinaryOperationHint const hints_ = BinaryOperationHint::kAny;
Node* context_node_;
v8::base::RandomNumberGenerator* rng_;
std::vector<double> integers;
......@@ -313,6 +312,18 @@ int32_t bit_xor(int32_t x, int32_t y) { return x ^ y; }
double divide_double_double(double x, double y) { return base::Divide(x, y); }
double modulo_double_double(double x, double y) { return Modulo(x, y); }
FeedbackSource FeedbackSourceWithOneBinarySlot(TyperTest* R) {
return FeedbackSource{
FeedbackVector::NewWithOneBinarySlotForTesting(R->zone(), R->isolate()),
FeedbackSlot{0}};
}
FeedbackSource FeedbackSourceWithOneCompareSlot(TyperTest* R) {
return FeedbackSource{
FeedbackVector::NewWithOneCompareSlotForTesting(R->zone(), R->isolate()),
FeedbackSlot{0}};
}
} // namespace
......@@ -323,55 +334,55 @@ double modulo_double_double(double x, double y) { return Modulo(x, y); }
// to ranges as input types.
TEST_F(TyperTest, TypeJSAdd) {
TestBinaryArithOp(javascript_.Add(hints_), std::plus<double>());
TestBinaryArithOp(javascript_.Add(FeedbackSourceWithOneBinarySlot(this)),
std::plus<double>());
}
TEST_F(TyperTest, TypeJSSubtract) {
TestBinaryArithOp(javascript_.Subtract(), std::minus<double>());
TestBinaryArithOp(javascript_.Subtract(FeedbackSourceWithOneBinarySlot(this)),
std::minus<double>());
}
TEST_F(TyperTest, TypeJSMultiply) {
TestBinaryArithOp(javascript_.Multiply(), std::multiplies<double>());
TestBinaryArithOp(javascript_.Multiply(FeedbackSourceWithOneBinarySlot(this)),
std::multiplies<double>());
}
TEST_F(TyperTest, TypeJSDivide) {
TestBinaryArithOp(javascript_.Divide(), divide_double_double);
TestBinaryArithOp(javascript_.Divide(FeedbackSourceWithOneBinarySlot(this)),
divide_double_double);
}
TEST_F(TyperTest, TypeJSModulus) {
TestBinaryArithOp(javascript_.Modulus(), modulo_double_double);
TestBinaryArithOp(javascript_.Modulus(FeedbackSourceWithOneBinarySlot(this)),
modulo_double_double);
}
TEST_F(TyperTest, TypeJSBitwiseOr) {
TestBinaryBitOp(javascript_.BitwiseOr(), bit_or);
TestBinaryBitOp(javascript_.BitwiseOr(FeedbackSourceWithOneBinarySlot(this)),
bit_or);
}
TEST_F(TyperTest, TypeJSBitwiseAnd) {
TestBinaryBitOp(javascript_.BitwiseAnd(), bit_and);
TestBinaryBitOp(javascript_.BitwiseAnd(FeedbackSourceWithOneBinarySlot(this)),
bit_and);
}
TEST_F(TyperTest, TypeJSBitwiseXor) {
TestBinaryBitOp(javascript_.BitwiseXor(), bit_xor);
TestBinaryBitOp(javascript_.BitwiseXor(FeedbackSourceWithOneBinarySlot(this)),
bit_xor);
}
TEST_F(TyperTest, TypeJSShiftLeft) {
TestBinaryBitOp(javascript_.ShiftLeft(), shift_left);
TestBinaryBitOp(javascript_.ShiftLeft(FeedbackSourceWithOneBinarySlot(this)),
shift_left);
}
TEST_F(TyperTest, TypeJSShiftRight) {
TestBinaryBitOp(javascript_.ShiftRight(), shift_right);
}
namespace {
FeedbackSource FeedbackSourceWithOneCompareSlot(TyperTest* R) {
return FeedbackSource{
FeedbackVector::NewWithOneCompareSlotForTesting(R->zone(), R->isolate()),
FeedbackSlot{0}};
TestBinaryBitOp(javascript_.ShiftRight(FeedbackSourceWithOneBinarySlot(this)),
shift_right);
}
} // namespace
TEST_F(TyperTest, TypeJSLessThan) {
TestBinaryCompareOp(
javascript_.LessThan(FeedbackSourceWithOneCompareSlot(this)),
......@@ -455,7 +466,7 @@ TEST_MONOTONICITY(ToObject)
TEST_MONOTONICITY(ToString)
#undef TEST_MONOTONICITY
// JS BINOPs with CompareOperationHint
// JS compare ops.
#define TEST_MONOTONICITY(name) \
TEST_F(TyperTest, Monotonicity_##name) { \
TestBinaryMonotonicity( \
......@@ -469,36 +480,33 @@ TEST_MONOTONICITY(LessThanOrEqual)
TEST_MONOTONICITY(GreaterThanOrEqual)
#undef TEST_MONOTONICITY
// JS BINOPs with BinaryOperationHint
// JS binary ops.
#define TEST_MONOTONICITY(name) \
TEST_F(TyperTest, Monotonicity_##name) { \
TestBinaryMonotonicity(javascript_.name(BinaryOperationHint::kAny)); \
TestBinaryMonotonicity( \
javascript_.name(FeedbackSourceWithOneBinarySlot(this))); \
}
TEST_MONOTONICITY(Add)
#undef TEST_MONOTONICITY
TEST_F(TyperTest, Monotonicity_InstanceOf) {
TestBinaryMonotonicity(javascript_.InstanceOf(FeedbackSource()));
}
// JS BINOPS without hint
#define TEST_MONOTONICITY(name) \
TEST_F(TyperTest, Monotonicity_##name) { \
TestBinaryMonotonicity(javascript_.name()); \
}
TEST_MONOTONICITY(BitwiseAnd)
TEST_MONOTONICITY(BitwiseOr)
TEST_MONOTONICITY(BitwiseXor)
TEST_MONOTONICITY(BitwiseAnd)
TEST_MONOTONICITY(Divide)
TEST_MONOTONICITY(Modulus)
TEST_MONOTONICITY(Multiply)
TEST_MONOTONICITY(ShiftLeft)
TEST_MONOTONICITY(ShiftRight)
TEST_MONOTONICITY(ShiftRightLogical)
TEST_MONOTONICITY(Subtract)
TEST_MONOTONICITY(Multiply)
TEST_MONOTONICITY(Divide)
TEST_MONOTONICITY(Modulus)
TEST_MONOTONICITY(OrdinaryHasInstance)
#undef TEST_MONOTONICITY
TEST_F(TyperTest, Monotonicity_InstanceOf) {
TestBinaryMonotonicity(javascript_.InstanceOf(FeedbackSource()));
}
TEST_F(TyperTest, Monotonicity_OrdinaryHasInstance) {
TestBinaryMonotonicity(javascript_.OrdinaryHasInstance());
}
// SIMPLIFIED UNOPs without hint
#define TEST_MONOTONICITY(name) \
TEST_F(TyperTest, Monotonicity_##name) { \
......
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