| // Copyright 2015 the V8 project authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "src/compiler/access-builder.h" | 
 | #include "src/compiler/diamond.h" | 
 | #include "src/compiler/js-graph.h" | 
 | #include "src/compiler/js-intrinsic-lowering.h" | 
 | #include "src/compiler/js-operator.h" | 
 | #include "test/unittests/compiler/graph-unittest.h" | 
 | #include "test/unittests/compiler/node-test-utils.h" | 
 | #include "testing/gmock-support.h" | 
 |  | 
 |  | 
 | using testing::_; | 
 | using testing::AllOf; | 
 | using testing::BitEq; | 
 | using testing::Capture; | 
 | using testing::CaptureEq; | 
 |  | 
 |  | 
 | namespace v8 { | 
 | namespace internal { | 
 | namespace compiler { | 
 |  | 
 | class JSIntrinsicLoweringTest : public GraphTest { | 
 |  public: | 
 |   JSIntrinsicLoweringTest() : GraphTest(3), javascript_(zone()) {} | 
 |   ~JSIntrinsicLoweringTest() override {} | 
 |  | 
 |  protected: | 
 |   Reduction Reduce(Node* node) { | 
 |     MachineOperatorBuilder machine(zone(), | 
 |                                    MachineType::PointerRepresentation()); | 
 |     SimplifiedOperatorBuilder simplified(zone()); | 
 |     JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified, | 
 |                     &machine); | 
 |     // TODO(titzer): mock the GraphReducer here for better unit testing. | 
 |     GraphReducer graph_reducer(zone(), graph()); | 
 |     JSIntrinsicLowering reducer(&graph_reducer, &jsgraph); | 
 |     return reducer.Reduce(node); | 
 |   } | 
 |  | 
 |   JSOperatorBuilder* javascript() { return &javascript_; } | 
 |  | 
 |  private: | 
 |   JSOperatorBuilder javascript_; | 
 | }; | 
 |  | 
 |  | 
 | // ----------------------------------------------------------------------------- | 
 | // %_IsSmi | 
 |  | 
 |  | 
 | TEST_F(JSIntrinsicLoweringTest, InlineIsSmi) { | 
 |   Node* const input = Parameter(0); | 
 |   Node* const context = Parameter(1); | 
 |   Node* const effect = graph()->start(); | 
 |   Node* const control = graph()->start(); | 
 |   Reduction const r = Reduce( | 
 |       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1), | 
 |                        input, context, effect, control)); | 
 |   ASSERT_TRUE(r.Changed()); | 
 |   EXPECT_THAT(r.replacement(), IsObjectIsSmi(input)); | 
 | } | 
 |  | 
 |  | 
 | // ----------------------------------------------------------------------------- | 
 | // %_IsArray | 
 |  | 
 |  | 
 | TEST_F(JSIntrinsicLoweringTest, InlineIsArray) { | 
 |   Node* const input = Parameter(0); | 
 |   Node* const context = Parameter(1); | 
 |   Node* const effect = graph()->start(); | 
 |   Node* const control = graph()->start(); | 
 |   Reduction const r = Reduce( | 
 |       graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsArray, 1), | 
 |                        input, context, effect, control)); | 
 |   ASSERT_TRUE(r.Changed()); | 
 |  | 
 |   Node* phi = r.replacement(); | 
 |   Capture<Node*> branch, if_false; | 
 |   EXPECT_THAT( | 
 |       phi, | 
 |       IsPhi( | 
 |           MachineRepresentation::kTagged, IsFalseConstant(), | 
 |           IsNumberEqual(IsLoadField(AccessBuilder::ForMapInstanceType(), | 
 |                                     IsLoadField(AccessBuilder::ForMap(), input, | 
 |                                                 effect, CaptureEq(&if_false)), | 
 |                                     _, _), | 
 |                         IsNumberConstant(JS_ARRAY_TYPE)), | 
 |           IsMerge(IsIfTrue(AllOf(CaptureEq(&branch), | 
 |                                  IsBranch(IsObjectIsSmi(input), control))), | 
 |                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch)))))); | 
 | } | 
 |  | 
 |  | 
 | // ----------------------------------------------------------------------------- | 
 | // %_IsTypedArray | 
 |  | 
 |  | 
 | TEST_F(JSIntrinsicLoweringTest, InlineIsTypedArray) { | 
 |   Node* const input = Parameter(0); | 
 |   Node* const context = Parameter(1); | 
 |   Node* const effect = graph()->start(); | 
 |   Node* const control = graph()->start(); | 
 |   Reduction const r = Reduce(graph()->NewNode( | 
 |       javascript()->CallRuntime(Runtime::kInlineIsTypedArray, 1), input, | 
 |       context, effect, control)); | 
 |   ASSERT_TRUE(r.Changed()); | 
 |  | 
 |   Node* phi = r.replacement(); | 
 |   Capture<Node*> branch, if_false; | 
 |   EXPECT_THAT( | 
 |       phi, | 
 |       IsPhi( | 
 |           MachineRepresentation::kTagged, IsFalseConstant(), | 
 |           IsNumberEqual(IsLoadField(AccessBuilder::ForMapInstanceType(), | 
 |                                     IsLoadField(AccessBuilder::ForMap(), input, | 
 |                                                 effect, CaptureEq(&if_false)), | 
 |                                     _, _), | 
 |                         IsNumberConstant(JS_TYPED_ARRAY_TYPE)), | 
 |           IsMerge(IsIfTrue(AllOf(CaptureEq(&branch), | 
 |                                  IsBranch(IsObjectIsSmi(input), control))), | 
 |                   AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch)))))); | 
 | } | 
 |  | 
 |  | 
 | // ----------------------------------------------------------------------------- | 
 | // %_IsJSReceiver | 
 |  | 
 |  | 
 | TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiver) { | 
 |   Node* const input = Parameter(0); | 
 |   Node* const context = Parameter(1); | 
 |   Node* const effect = graph()->start(); | 
 |   Node* const control = graph()->start(); | 
 |   Reduction const r = Reduce(graph()->NewNode( | 
 |       javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input, | 
 |       context, effect, control)); | 
 |   ASSERT_TRUE(r.Changed()); | 
 |   EXPECT_THAT(r.replacement(), IsObjectIsReceiver(input)); | 
 | } | 
 |  | 
 | // ----------------------------------------------------------------------------- | 
 | // %_CreateJSGeneratorObject | 
 |  | 
 | TEST_F(JSIntrinsicLoweringTest, InlineCreateJSGeneratorObject) { | 
 |   Node* const function = Parameter(0); | 
 |   Node* const receiver = Parameter(1); | 
 |   Node* const context = Parameter(2); | 
 |   Node* const effect = graph()->start(); | 
 |   Node* const control = graph()->start(); | 
 |   Reduction const r = Reduce(graph()->NewNode( | 
 |       javascript()->CallRuntime(Runtime::kInlineCreateJSGeneratorObject, 2), | 
 |       function, receiver, context, effect, control)); | 
 |   ASSERT_TRUE(r.Changed()); | 
 |   EXPECT_EQ(IrOpcode::kJSCreateGeneratorObject, | 
 |             r.replacement()->op()->opcode()); | 
 | } | 
 |  | 
 | }  // namespace compiler | 
 | }  // namespace internal | 
 | }  // namespace v8 |