blob: a44bd0278da61a7d5a111c512dfe273cf7f4fe03 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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/js-context-relaxation.h"
6#include "src/compiler/js-graph.h"
7#include "test/unittests/compiler/graph-unittest.h"
8#include "test/unittests/compiler/node-test-utils.h"
9
10namespace v8 {
11namespace internal {
12namespace compiler {
13
14class JSContextRelaxationTest : public GraphTest {
15 public:
16 JSContextRelaxationTest() : GraphTest(3), javascript_(zone()) {}
17 ~JSContextRelaxationTest() override {}
18
19 protected:
20 Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags =
21 MachineOperatorBuilder::kNoFlags) {
22 MachineOperatorBuilder machine(zone(), MachineType::PointerRepresentation(),
23 flags);
24 JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
25 &machine);
26 // TODO(titzer): mock the GraphReducer here for better unit testing.
27 GraphReducer graph_reducer(zone(), graph());
28 JSContextRelaxation reducer;
29 return reducer.Reduce(node);
30 }
31
32 Node* EmptyFrameState() {
33 MachineOperatorBuilder machine(zone());
34 JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
35 &machine);
36 return jsgraph.EmptyFrameState();
37 }
38
39 Node* ShallowFrameStateChain(Node* outer_context,
40 ContextCallingMode context_calling_mode) {
41 const FrameStateFunctionInfo* const frame_state_function_info =
42 common()->CreateFrameStateFunctionInfo(
43 FrameStateType::kJavaScriptFunction, 3, 0,
44 Handle<SharedFunctionInfo>(), context_calling_mode);
45 const Operator* op = common()->FrameState(BailoutId::None(),
46 OutputFrameStateCombine::Ignore(),
47 frame_state_function_info);
48 return graph()->NewNode(op, graph()->start(), graph()->start(),
49 graph()->start(), outer_context, graph()->start(),
50 graph()->start());
51 }
52
53 Node* DeepFrameStateChain(Node* outer_context,
54 ContextCallingMode context_calling_mode) {
55 const FrameStateFunctionInfo* const frame_state_function_info =
56 common()->CreateFrameStateFunctionInfo(
57 FrameStateType::kJavaScriptFunction, 3, 0,
58 Handle<SharedFunctionInfo>(), context_calling_mode);
59 const Operator* op = common()->FrameState(BailoutId::None(),
60 OutputFrameStateCombine::Ignore(),
61 frame_state_function_info);
62 Node* shallow_frame_state =
63 ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
64 return graph()->NewNode(op, graph()->start(), graph()->start(),
65 graph()->start(), graph()->start(),
66 graph()->start(), shallow_frame_state);
67 }
68
69 JSOperatorBuilder* javascript() { return &javascript_; }
70
71 private:
72 JSOperatorBuilder javascript_;
73};
74
75
76TEST_F(JSContextRelaxationTest,
77 RelaxJSCallFunctionShallowFrameStateChainNoCrossCtx) {
78 Node* const input0 = Parameter(0);
79 Node* const input1 = Parameter(1);
80 Node* const context = Parameter(2);
81 Node* const outer_context = Parameter(3);
82 Node* const frame_state =
83 ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
84 Node* const effect = graph()->start();
85 Node* const control = graph()->start();
86 Node* node = graph()->NewNode(
87 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
88 context, frame_state, frame_state, effect, control);
89 Reduction const r = Reduce(node);
90 EXPECT_TRUE(r.Changed());
91 EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
92}
93
94TEST_F(JSContextRelaxationTest,
95 RelaxJSCallFunctionShallowFrameStateChainCrossCtx) {
96 Node* const input0 = Parameter(0);
97 Node* const input1 = Parameter(1);
98 Node* const context = Parameter(2);
99 Node* const outer_context = Parameter(3);
100 Node* const frame_state =
101 ShallowFrameStateChain(outer_context, CALL_CHANGES_NATIVE_CONTEXT);
102 Node* const effect = graph()->start();
103 Node* const control = graph()->start();
104 Node* node = graph()->NewNode(
105 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
106 context, frame_state, frame_state, effect, control);
107 Reduction const r = Reduce(node);
108 EXPECT_FALSE(r.Changed());
109 EXPECT_EQ(context, NodeProperties::GetContextInput(node));
110}
111
112TEST_F(JSContextRelaxationTest,
113 RelaxJSCallFunctionDeepFrameStateChainNoCrossCtx) {
114 Node* const input0 = Parameter(0);
115 Node* const input1 = Parameter(1);
116 Node* const context = Parameter(2);
117 Node* const outer_context = Parameter(3);
118 Node* const frame_state =
119 DeepFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
120 Node* const effect = graph()->start();
121 Node* const control = graph()->start();
122 Node* node = graph()->NewNode(
123 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
124 context, frame_state, frame_state, effect, control);
125 Reduction const r = Reduce(node);
126 EXPECT_TRUE(r.Changed());
127 EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
128}
129
130TEST_F(JSContextRelaxationTest,
131 RelaxJSCallFunctionDeepFrameStateChainCrossCtx) {
132 Node* const input0 = Parameter(0);
133 Node* const input1 = Parameter(1);
134 Node* const context = Parameter(2);
135 Node* const outer_context = Parameter(3);
136 Node* const frame_state =
137 DeepFrameStateChain(outer_context, CALL_CHANGES_NATIVE_CONTEXT);
138 Node* const effect = graph()->start();
139 Node* const control = graph()->start();
140 Node* node = graph()->NewNode(
141 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
142 context, frame_state, frame_state, effect, control);
143 Reduction const r = Reduce(node);
144 EXPECT_FALSE(r.Changed());
145 EXPECT_EQ(context, NodeProperties::GetContextInput(node));
146}
147
148TEST_F(JSContextRelaxationTest,
149 RelaxJSCallFunctionDeepContextChainFullRelaxForCatch) {
150 Node* const input0 = Parameter(0);
151 Node* const input1 = Parameter(1);
152 Node* const context = Parameter(2);
153 Node* const outer_context = Parameter(3);
154 const Operator* op = javascript()->CreateCatchContext(Handle<String>());
155 Node* const effect = graph()->start();
156 Node* const control = graph()->start();
157 Node* nested_context = graph()->NewNode(
158 op, graph()->start(), graph()->start(), outer_context, effect, control);
159 Node* const frame_state_2 =
160 ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
161 Node* node = graph()->NewNode(
162 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
163 context, frame_state_2, frame_state_2, effect, control);
164 Reduction const r = Reduce(node);
165 EXPECT_TRUE(r.Changed());
166 EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
167}
168
169
170TEST_F(JSContextRelaxationTest,
171 RelaxJSCallFunctionDeepContextChainFullRelaxForWith) {
172 Node* const input0 = Parameter(0);
173 Node* const input1 = Parameter(1);
174 Node* const context = Parameter(2);
175 Node* const outer_context = Parameter(3);
176 const Operator* op = javascript()->CreateWithContext();
177 Node* const effect = graph()->start();
178 Node* const control = graph()->start();
179 Node* nested_context = graph()->NewNode(
180 op, graph()->start(), graph()->start(), outer_context, effect, control);
181 Node* const frame_state_2 =
182 ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
183 Node* node = graph()->NewNode(
184 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
185 context, frame_state_2, frame_state_2, effect, control);
186 Reduction const r = Reduce(node);
187 EXPECT_TRUE(r.Changed());
188 EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
189}
190
191
192TEST_F(JSContextRelaxationTest,
193 RelaxJSCallFunctionDeepContextChainFullRelaxForBlock) {
194 Node* const input0 = Parameter(0);
195 Node* const input1 = Parameter(1);
196 Node* const context = Parameter(2);
197 Node* const outer_context = Parameter(3);
198 Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::null();
199 const Operator* op = javascript()->CreateBlockContext(scope_info);
200 Node* const effect = graph()->start();
201 Node* const control = graph()->start();
202 Node* nested_context =
203 graph()->NewNode(op, graph()->start(), outer_context, effect, control);
204 Node* const frame_state_2 =
205 ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
206 Node* node = graph()->NewNode(
207 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
208 context, frame_state_2, frame_state_2, effect, control);
209 Reduction const r = Reduce(node);
210 EXPECT_TRUE(r.Changed());
211 EXPECT_EQ(outer_context, NodeProperties::GetContextInput(node));
212}
213
214
215TEST_F(JSContextRelaxationTest,
216 RelaxJSCallFunctionDeepContextChainPartialRelaxForScript) {
217 Node* const input0 = Parameter(0);
218 Node* const input1 = Parameter(1);
219 Node* const context = Parameter(2);
220 Node* const outer_context = Parameter(3);
221 Handle<ScopeInfo> scope_info = Handle<ScopeInfo>::null();
222 const Operator* op = javascript()->CreateScriptContext(scope_info);
223 Node* const frame_state_1 =
224 ShallowFrameStateChain(outer_context, CALL_MAINTAINS_NATIVE_CONTEXT);
225 Node* const effect = graph()->start();
226 Node* const control = graph()->start();
227 Node* nested_context = graph()->NewNode(op, graph()->start(), outer_context,
228 frame_state_1, effect, control);
229 Node* const frame_state_2 =
230 ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
231 Node* node = graph()->NewNode(
232 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
233 context, frame_state_2, frame_state_2, effect, control);
234 Reduction const r = Reduce(node);
235 EXPECT_TRUE(r.Changed());
236 EXPECT_EQ(nested_context, NodeProperties::GetContextInput(node));
237}
238
239
240TEST_F(JSContextRelaxationTest,
241 RelaxJSCallFunctionDeepContextChainPartialRelaxForModule) {
242 Node* const input0 = Parameter(0);
243 Node* const input1 = Parameter(1);
244 Node* const context = Parameter(2);
245 Node* const outer_context = Parameter(3);
246 const Operator* op = javascript()->CreateModuleContext();
247 Node* const effect = graph()->start();
248 Node* const control = graph()->start();
249 Node* nested_context = graph()->NewNode(
250 op, graph()->start(), graph()->start(), outer_context, effect, control);
251 Node* const frame_state_2 =
252 ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
253 Node* node = graph()->NewNode(
254 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
255 context, frame_state_2, frame_state_2, effect, control);
256 Reduction const r = Reduce(node);
257 EXPECT_TRUE(r.Changed());
258 EXPECT_EQ(nested_context, NodeProperties::GetContextInput(node));
259}
260
261
262TEST_F(JSContextRelaxationTest,
263 RelaxJSCallFunctionDeepContextChainPartialNoRelax) {
264 Node* const input0 = Parameter(0);
265 Node* const input1 = Parameter(1);
266 Node* const context = Parameter(2);
267 Node* const outer_context = Parameter(3);
268 const Operator* op = javascript()->CreateFunctionContext(0);
269 Node* const effect = graph()->start();
270 Node* const control = graph()->start();
271 Node* nested_context =
272 graph()->NewNode(op, graph()->start(), outer_context, effect, control);
273 Node* const frame_state_2 =
274 ShallowFrameStateChain(nested_context, CALL_MAINTAINS_NATIVE_CONTEXT);
275 Node* node = graph()->NewNode(
276 javascript()->CallFunction(2, STRICT, VectorSlotPair()), input0, input1,
277 context, frame_state_2, frame_state_2, effect, control);
278 Reduction const r = Reduce(node);
279 EXPECT_FALSE(r.Changed());
280 EXPECT_EQ(context, NodeProperties::GetContextInput(node));
281}
282
283} // namespace compiler
284} // namespace internal
285} // namespace v8