Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler/access-builder.h"
6 : #include "src/compiler/diamond.h"
7 : #include "src/compiler/js-graph.h"
8 : #include "src/compiler/js-intrinsic-lowering.h"
9 : #include "src/compiler/js-operator.h"
10 : #include "test/unittests/compiler/graph-unittest.h"
11 : #include "test/unittests/compiler/node-test-utils.h"
12 : #include "testing/gmock-support.h"
13 :
14 :
15 : using testing::_;
16 : using testing::AllOf;
17 : using testing::BitEq;
18 : using testing::Capture;
19 : using testing::CaptureEq;
20 :
21 :
22 : namespace v8 {
23 : namespace internal {
24 : namespace compiler {
25 :
26 : class JSIntrinsicLoweringTest : public GraphTest {
27 : public:
28 10 : JSIntrinsicLoweringTest() : GraphTest(3), javascript_(zone()) {}
29 5 : ~JSIntrinsicLoweringTest() override = default;
30 :
31 : protected:
32 5 : Reduction Reduce(Node* node) {
33 : MachineOperatorBuilder machine(zone(),
34 5 : MachineType::PointerRepresentation());
35 5 : SimplifiedOperatorBuilder simplified(zone());
36 : JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
37 5 : &machine);
38 : // TODO(titzer): mock the GraphReducer here for better unit testing.
39 10 : GraphReducer graph_reducer(zone(), graph());
40 5 : JSIntrinsicLowering reducer(&graph_reducer, &jsgraph);
41 10 : return reducer.Reduce(node);
42 : }
43 :
44 10 : JSOperatorBuilder* javascript() { return &javascript_; }
45 :
46 : private:
47 : JSOperatorBuilder javascript_;
48 : };
49 :
50 :
51 : // -----------------------------------------------------------------------------
52 : // %_IsSmi
53 :
54 :
55 15419 : TEST_F(JSIntrinsicLoweringTest, InlineIsSmi) {
56 1 : Node* const input = Parameter(0);
57 1 : Node* const context = Parameter(1);
58 : Node* const effect = graph()->start();
59 : Node* const control = graph()->start();
60 : Reduction const r = Reduce(
61 : graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1),
62 2 : input, context, effect, control));
63 1 : ASSERT_TRUE(r.Changed());
64 5 : EXPECT_THAT(r.replacement(), IsObjectIsSmi(input));
65 : }
66 :
67 :
68 : // -----------------------------------------------------------------------------
69 : // %_IsArray
70 :
71 :
72 15419 : TEST_F(JSIntrinsicLoweringTest, InlineIsArray) {
73 1 : Node* const input = Parameter(0);
74 1 : Node* const context = Parameter(1);
75 : Node* const effect = graph()->start();
76 : Node* const control = graph()->start();
77 : Reduction const r = Reduce(
78 : graph()->NewNode(javascript()->CallRuntime(Runtime::kInlineIsArray, 1),
79 2 : input, context, effect, control));
80 1 : ASSERT_TRUE(r.Changed());
81 :
82 1 : Node* phi = r.replacement();
83 : Capture<Node*> branch, if_false;
84 35 : EXPECT_THAT(
85 : phi,
86 : IsPhi(
87 : MachineRepresentation::kTagged, IsFalseConstant(),
88 : IsNumberEqual(IsLoadField(AccessBuilder::ForMapInstanceType(),
89 : IsLoadField(AccessBuilder::ForMap(), input,
90 : effect, CaptureEq(&if_false)),
91 : _, _),
92 : IsNumberConstant(JS_ARRAY_TYPE)),
93 : IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
94 : IsBranch(IsObjectIsSmi(input), control))),
95 0 : AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
96 : }
97 :
98 :
99 : // -----------------------------------------------------------------------------
100 : // %_IsTypedArray
101 :
102 :
103 15419 : TEST_F(JSIntrinsicLoweringTest, InlineIsTypedArray) {
104 1 : Node* const input = Parameter(0);
105 1 : Node* const context = Parameter(1);
106 : Node* const effect = graph()->start();
107 : Node* const control = graph()->start();
108 : Reduction const r = Reduce(graph()->NewNode(
109 : javascript()->CallRuntime(Runtime::kInlineIsTypedArray, 1), input,
110 2 : context, effect, control));
111 1 : ASSERT_TRUE(r.Changed());
112 :
113 1 : Node* phi = r.replacement();
114 : Capture<Node*> branch, if_false;
115 35 : EXPECT_THAT(
116 : phi,
117 : IsPhi(
118 : MachineRepresentation::kTagged, IsFalseConstant(),
119 : IsNumberEqual(IsLoadField(AccessBuilder::ForMapInstanceType(),
120 : IsLoadField(AccessBuilder::ForMap(), input,
121 : effect, CaptureEq(&if_false)),
122 : _, _),
123 : IsNumberConstant(JS_TYPED_ARRAY_TYPE)),
124 : IsMerge(IsIfTrue(AllOf(CaptureEq(&branch),
125 : IsBranch(IsObjectIsSmi(input), control))),
126 0 : AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
127 : }
128 :
129 :
130 : // -----------------------------------------------------------------------------
131 : // %_IsJSReceiver
132 :
133 :
134 15419 : TEST_F(JSIntrinsicLoweringTest, InlineIsJSReceiver) {
135 1 : Node* const input = Parameter(0);
136 1 : Node* const context = Parameter(1);
137 : Node* const effect = graph()->start();
138 : Node* const control = graph()->start();
139 : Reduction const r = Reduce(graph()->NewNode(
140 : javascript()->CallRuntime(Runtime::kInlineIsJSReceiver, 1), input,
141 2 : context, effect, control));
142 1 : ASSERT_TRUE(r.Changed());
143 5 : EXPECT_THAT(r.replacement(), IsObjectIsReceiver(input));
144 : }
145 :
146 : // -----------------------------------------------------------------------------
147 : // %_CreateJSGeneratorObject
148 :
149 15419 : TEST_F(JSIntrinsicLoweringTest, InlineCreateJSGeneratorObject) {
150 1 : Node* const function = Parameter(0);
151 1 : Node* const receiver = Parameter(1);
152 1 : Node* const context = Parameter(2);
153 : Node* const effect = graph()->start();
154 : Node* const control = graph()->start();
155 : Reduction const r = Reduce(graph()->NewNode(
156 : javascript()->CallRuntime(Runtime::kInlineCreateJSGeneratorObject, 2),
157 2 : function, receiver, context, effect, control));
158 1 : ASSERT_TRUE(r.Changed());
159 2 : EXPECT_EQ(IrOpcode::kJSCreateGeneratorObject,
160 0 : r.replacement()->op()->opcode());
161 : }
162 :
163 : } // namespace compiler
164 : } // namespace internal
165 9249 : } // namespace v8
|