• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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 
10 namespace v8 {
11 namespace internal {
12 namespace compiler {
13 
14 class JSContextRelaxationTest : public GraphTest {
15  public:
JSContextRelaxationTest()16   JSContextRelaxationTest() : GraphTest(3), javascript_(zone()) {}
~JSContextRelaxationTest()17   ~JSContextRelaxationTest() override {}
18 
19  protected:
Reduce(Node * node,MachineOperatorBuilder::Flags flags=MachineOperatorBuilder::kNoFlags)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 
EmptyFrameState()32   Node* EmptyFrameState() {
33     MachineOperatorBuilder machine(zone());
34     JSGraph jsgraph(isolate(), graph(), common(), javascript(), nullptr,
35                     &machine);
36     return jsgraph.EmptyFrameState();
37   }
38 
ShallowFrameStateChain(Node * outer_context,ContextCallingMode context_calling_mode)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 
DeepFrameStateChain(Node * outer_context,ContextCallingMode context_calling_mode)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 
javascript()69   JSOperatorBuilder* javascript() { return &javascript_; }
70 
71  private:
72   JSOperatorBuilder javascript_;
73 };
74 
75 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionShallowFrameStateChainNoCrossCtx)76 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionShallowFrameStateChainCrossCtx)94 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionDeepFrameStateChainNoCrossCtx)112 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionDeepFrameStateChainCrossCtx)130 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionDeepContextChainFullRelaxForCatch)148 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionDeepContextChainFullRelaxForWith)170 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionDeepContextChainFullRelaxForBlock)192 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionDeepContextChainPartialRelaxForScript)215 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionDeepContextChainPartialRelaxForModule)240 TEST_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 
TEST_F(JSContextRelaxationTest,RelaxJSCallFunctionDeepContextChainPartialNoRelax)262 TEST_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
286