From b66226a9d93f3151773a823748c5cdb20dd8c153 Mon Sep 17 00:00:00 2001 From: bmeurer Date: Tue, 26 May 2015 21:23:29 -0700 Subject: [PATCH] [turbofan] Optimize strict equality of unique values. If both inputs to JSStrictEqual/JSStrictNotEqual are unique values (i.e. values with a canonical representation), we can lower the comparison to ReferenceEqual instead of StringEqual or CompareIC. Review URL: https://codereview.chromium.org/1154303002 Cr-Commit-Position: refs/heads/master@{#28646} --- src/compiler/js-typed-lowering.cc | 4 +++ .../compiler/js-typed-lowering-unittest.cc | 17 ++++++++--- test/unittests/compiler/node-test-utils.cc | 34 ++++++++++++++++++++++ test/unittests/compiler/node-test-utils.h | 7 +++++ 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index 168fb48..8715fba 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -566,6 +566,10 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { return r.ChangeToPureOperator( simplified()->ReferenceEqual(Type::Receiver()), invert); } + if (r.BothInputsAre(Type::Unique())) { + return r.ChangeToPureOperator(simplified()->ReferenceEqual(Type::Unique()), + invert); + } if (r.BothInputsAre(Type::String())) { return r.ChangeToPureOperator(simplified()->StringEqual(), invert); } diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc index 9d713cf..ddff925 100644 --- a/test/unittests/compiler/js-typed-lowering-unittest.cc +++ b/test/unittests/compiler/js-typed-lowering-unittest.cc @@ -436,18 +436,27 @@ TEST_F(JSTypedLoweringTest, JSToNumberWithPlainPrimitive) { TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) { Node* const the_hole = HeapConstant(factory()->the_hole_value()); Node* const context = UndefinedConstant(); - Node* const effect = graph()->start(); - Node* const control = graph()->start(); TRACED_FOREACH(Type*, type, kJSTypes) { Node* const lhs = Parameter(type); - Reduction r = Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, - the_hole, context, effect, control)); + Reduction r = Reduce( + graph()->NewNode(javascript()->StrictEqual(), lhs, the_hole, context)); ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsFalseConstant()); } } +TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) { + Node* const lhs = Parameter(Type::Unique(), 0); + Node* const rhs = Parameter(Type::Unique(), 1); + Node* const context = Parameter(Type::Any(), 2); + Reduction r = + Reduce(graph()->NewNode(javascript()->StrictEqual(), lhs, rhs, context)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs)); +} + + // ----------------------------------------------------------------------------- // JSShiftLeft diff --git a/test/unittests/compiler/node-test-utils.cc b/test/unittests/compiler/node-test-utils.cc index 5fe4036..522eecf 100644 --- a/test/unittests/compiler/node-test-utils.cc +++ b/test/unittests/compiler/node-test-utils.cc @@ -748,6 +748,32 @@ class IsTailCallMatcher final : public NodeMatcher { }; +class IsReferenceEqualMatcher final : public NodeMatcher { + public: + IsReferenceEqualMatcher(const Matcher& type_matcher, + const Matcher& lhs_matcher, + const Matcher& rhs_matcher) + : NodeMatcher(IrOpcode::kReferenceEqual), + type_matcher_(type_matcher), + lhs_matcher_(lhs_matcher), + rhs_matcher_(rhs_matcher) {} + + bool MatchAndExplain(Node* node, MatchResultListener* listener) const final { + return (NodeMatcher::MatchAndExplain(node, listener) && + // TODO(bmeurer): The type parameter is currently ignored. + PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "lhs", + lhs_matcher_, listener) && + PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), "rhs", + rhs_matcher_, listener)); + } + + private: + const Matcher type_matcher_; + const Matcher lhs_matcher_; + const Matcher rhs_matcher_; +}; + + class IsAllocateMatcher final : public NodeMatcher { public: IsAllocateMatcher(const Matcher& size_matcher, @@ -1607,6 +1633,14 @@ Matcher IsTailCall( } +Matcher IsReferenceEqual(const Matcher& type_matcher, + const Matcher& lhs_matcher, + const Matcher& rhs_matcher) { + return MakeMatcher( + new IsReferenceEqualMatcher(type_matcher, lhs_matcher, rhs_matcher)); +} + + Matcher IsAllocate(const Matcher& size_matcher, const Matcher& effect_matcher, const Matcher& control_matcher) { diff --git a/test/unittests/compiler/node-test-utils.h b/test/unittests/compiler/node-test-utils.h index 4ab1a6b..d7b17ab 100644 --- a/test/unittests/compiler/node-test-utils.h +++ b/test/unittests/compiler/node-test-utils.h @@ -17,6 +17,10 @@ class ExternalReference; class HeapObject; template class Unique; +template +class TypeImpl; +struct ZoneTypeConfig; +typedef TypeImpl Type; namespace compiler { @@ -127,6 +131,9 @@ Matcher IsTailCall( const Matcher& control_matcher); Matcher IsBooleanNot(const Matcher& value_matcher); +Matcher IsReferenceEqual(const Matcher& type_matcher, + const Matcher& lhs_matcher, + const Matcher& rhs_matcher); Matcher IsNumberEqual(const Matcher& lhs_matcher, const Matcher& rhs_matcher); Matcher IsNumberLessThan(const Matcher& lhs_matcher, -- 2.7.4