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