Line data Source code
1 : // Copyright 2016 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/js-create-lowering.h"
6 : #include "src/code-factory.h"
7 : #include "src/compiler/access-builder.h"
8 : #include "src/compiler/compilation-dependencies.h"
9 : #include "src/compiler/js-graph.h"
10 : #include "src/compiler/js-operator.h"
11 : #include "src/compiler/machine-operator.h"
12 : #include "src/compiler/node-properties.h"
13 : #include "src/compiler/operator-properties.h"
14 : #include "src/feedback-vector.h"
15 : #include "src/isolate-inl.h"
16 : #include "src/objects/arguments.h"
17 : #include "test/unittests/compiler/compiler-test-utils.h"
18 : #include "test/unittests/compiler/graph-unittest.h"
19 : #include "test/unittests/compiler/node-test-utils.h"
20 : #include "testing/gmock-support.h"
21 :
22 : using testing::_;
23 : using testing::BitEq;
24 : using testing::IsNaN;
25 :
26 : namespace v8 {
27 : namespace internal {
28 : namespace compiler {
29 :
30 : class JSCreateLoweringTest : public TypedGraphTest {
31 : public:
32 7 : JSCreateLoweringTest()
33 : : TypedGraphTest(3),
34 : javascript_(zone()),
35 : deps_(broker(), zone()),
36 28 : handle_scope_(isolate()) {}
37 14 : ~JSCreateLoweringTest() override = default;
38 :
39 : protected:
40 7 : Reduction Reduce(Node* node) {
41 7 : MachineOperatorBuilder machine(zone());
42 7 : SimplifiedOperatorBuilder simplified(zone());
43 : JSGraph jsgraph(isolate(), graph(), common(), javascript(), &simplified,
44 7 : &machine);
45 : // TODO(titzer): mock the GraphReducer here for better unit testing.
46 14 : GraphReducer graph_reducer(zone(), graph());
47 : JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph, broker(),
48 7 : zone());
49 14 : return reducer.Reduce(node);
50 : }
51 :
52 6 : Node* FrameState(Handle<SharedFunctionInfo> shared, Node* outer_frame_state) {
53 : Node* state_values =
54 6 : graph()->NewNode(common()->StateValues(0, SparseInputMask::Dense()));
55 6 : return graph()->NewNode(
56 : common()->FrameState(
57 : BailoutId::None(), OutputFrameStateCombine::Ignore(),
58 : common()->CreateFrameStateFunctionInfo(
59 : FrameStateType::kInterpretedFunction, 1, 0, shared)),
60 : state_values, state_values, state_values, NumberConstant(0),
61 6 : UndefinedConstant(), outer_frame_state);
62 : }
63 :
64 14 : JSOperatorBuilder* javascript() { return &javascript_; }
65 :
66 : private:
67 : JSOperatorBuilder javascript_;
68 : CompilationDependencies deps_;
69 : CanonicalHandleScope handle_scope_;
70 : };
71 :
72 : // -----------------------------------------------------------------------------
73 : // JSCreate
74 :
75 15443 : TEST_F(JSCreateLoweringTest, JSCreate) {
76 1 : Handle<JSFunction> function = isolate()->object_function();
77 2 : Node* const target = graph()->NewNode(common()->HeapConstant(function));
78 1 : Node* const context = Parameter(Type::Any());
79 : Node* const effect = graph()->start();
80 : Node* const control = graph()->start();
81 : Reduction r =
82 : Reduce(graph()->NewNode(javascript()->Create(), target, target, context,
83 3 : EmptyFrameState(), effect, control));
84 1 : ASSERT_TRUE(r.Changed());
85 13 : EXPECT_THAT(
86 : r.replacement(),
87 : IsFinishRegion(
88 : IsAllocate(IsNumberConstant(function->initial_map()->instance_size()),
89 : IsBeginRegion(effect), control),
90 0 : _));
91 : }
92 :
93 : // -----------------------------------------------------------------------------
94 : // JSCreateArguments
95 :
96 15443 : TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedMapped) {
97 1 : Node* const closure = Parameter(Type::Any());
98 1 : Node* const context = UndefinedConstant();
99 : Node* const effect = graph()->start();
100 2 : Handle<SharedFunctionInfo> shared(isolate()->regexp_function()->shared(),
101 : isolate());
102 1 : Node* const frame_state_outer = FrameState(shared, graph()->start());
103 1 : Node* const frame_state_inner = FrameState(shared, frame_state_outer);
104 : Reduction r = Reduce(graph()->NewNode(
105 : javascript()->CreateArguments(CreateArgumentsType::kMappedArguments),
106 2 : closure, context, frame_state_inner, effect));
107 1 : ASSERT_TRUE(r.Changed());
108 11 : EXPECT_THAT(
109 : r.replacement(),
110 : IsFinishRegion(
111 : IsAllocate(IsNumberConstant(JSSloppyArgumentsObject::kSize), _, _),
112 0 : _));
113 : }
114 :
115 15443 : TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedUnmapped) {
116 1 : Node* const closure = Parameter(Type::Any());
117 1 : Node* const context = UndefinedConstant();
118 : Node* const effect = graph()->start();
119 2 : Handle<SharedFunctionInfo> shared(isolate()->regexp_function()->shared(),
120 : isolate());
121 1 : Node* const frame_state_outer = FrameState(shared, graph()->start());
122 1 : Node* const frame_state_inner = FrameState(shared, frame_state_outer);
123 : Reduction r = Reduce(graph()->NewNode(
124 : javascript()->CreateArguments(CreateArgumentsType::kUnmappedArguments),
125 2 : closure, context, frame_state_inner, effect));
126 1 : ASSERT_TRUE(r.Changed());
127 11 : EXPECT_THAT(
128 : r.replacement(),
129 : IsFinishRegion(
130 : IsAllocate(IsNumberConstant(JSStrictArgumentsObject::kSize), _, _),
131 0 : _));
132 : }
133 :
134 15443 : TEST_F(JSCreateLoweringTest, JSCreateArgumentsInlinedRestArray) {
135 1 : Node* const closure = Parameter(Type::Any());
136 1 : Node* const context = UndefinedConstant();
137 : Node* const effect = graph()->start();
138 2 : Handle<SharedFunctionInfo> shared(isolate()->regexp_function()->shared(),
139 : isolate());
140 1 : Node* const frame_state_outer = FrameState(shared, graph()->start());
141 1 : Node* const frame_state_inner = FrameState(shared, frame_state_outer);
142 : Reduction r = Reduce(graph()->NewNode(
143 : javascript()->CreateArguments(CreateArgumentsType::kRestParameter),
144 2 : closure, context, frame_state_inner, effect));
145 1 : ASSERT_TRUE(r.Changed());
146 11 : EXPECT_THAT(
147 : r.replacement(),
148 0 : IsFinishRegion(IsAllocate(IsNumberConstant(JSArray::kSize), _, _), _));
149 : }
150 :
151 : // -----------------------------------------------------------------------------
152 : // JSCreateFunctionContext
153 :
154 15443 : TEST_F(JSCreateLoweringTest, JSCreateFunctionContextViaInlinedAllocation) {
155 1 : Node* const context = Parameter(Type::Any());
156 : Node* const effect = graph()->start();
157 : Node* const control = graph()->start();
158 : Reduction const r = Reduce(graph()->NewNode(
159 : javascript()->CreateFunctionContext(
160 : handle(ScopeInfo::Empty(isolate()), isolate()), 8, FUNCTION_SCOPE),
161 3 : context, effect, control));
162 1 : ASSERT_TRUE(r.Changed());
163 13 : EXPECT_THAT(r.replacement(),
164 : IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
165 : 8 + Context::MIN_CONTEXT_SLOTS)),
166 : IsBeginRegion(_), control),
167 0 : _));
168 : }
169 :
170 : // -----------------------------------------------------------------------------
171 : // JSCreateWithContext
172 :
173 15443 : TEST_F(JSCreateLoweringTest, JSCreateWithContext) {
174 1 : Handle<ScopeInfo> scope_info = ScopeInfo::CreateForEmptyFunction(isolate());
175 1 : Node* const object = Parameter(Type::Receiver());
176 1 : Node* const context = Parameter(Type::Any());
177 : Node* const effect = graph()->start();
178 : Node* const control = graph()->start();
179 : Reduction r =
180 : Reduce(graph()->NewNode(javascript()->CreateWithContext(scope_info),
181 2 : object, context, effect, control));
182 1 : ASSERT_TRUE(r.Changed());
183 13 : EXPECT_THAT(r.replacement(),
184 : IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
185 : Context::MIN_CONTEXT_SLOTS)),
186 : IsBeginRegion(_), control),
187 0 : _));
188 : }
189 :
190 : // -----------------------------------------------------------------------------
191 : // JSCreateCatchContext
192 :
193 15443 : TEST_F(JSCreateLoweringTest, JSCreateCatchContext) {
194 1 : Handle<ScopeInfo> scope_info = ScopeInfo::CreateForEmptyFunction(isolate());
195 1 : Node* const exception = Parameter(Type::Receiver());
196 1 : Node* const context = Parameter(Type::Any());
197 : Node* const effect = graph()->start();
198 : Node* const control = graph()->start();
199 : Reduction r =
200 : Reduce(graph()->NewNode(javascript()->CreateCatchContext(scope_info),
201 2 : exception, context, effect, control));
202 1 : ASSERT_TRUE(r.Changed());
203 13 : EXPECT_THAT(r.replacement(),
204 : IsFinishRegion(IsAllocate(IsNumberConstant(Context::SizeFor(
205 : Context::MIN_CONTEXT_SLOTS + 1)),
206 : IsBeginRegion(_), control),
207 0 : _));
208 : }
209 :
210 : } // namespace compiler
211 : } // namespace internal
212 9264 : } // namespace v8
|