| OLD | NEW |
| (Empty) |
| 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: | |
| 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 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 87 input0, input1, context, frame_state, | |
| 88 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 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 105 input0, input1, context, frame_state, | |
| 106 frame_state, effect, control); | |
| 107 Reduction const r = Reduce(node); | |
| 108 EXPECT_FALSE(r.Changed()); | |
| 109 EXPECT_EQ(context, NodeProperties::GetContextInput(node)); | |
| 110 } | |
| 111 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 123 input0, input1, context, frame_state, | |
| 124 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 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 141 input0, input1, context, frame_state, | |
| 142 frame_state, effect, control); | |
| 143 Reduction const r = Reduce(node); | |
| 144 EXPECT_FALSE(r.Changed()); | |
| 145 EXPECT_EQ(context, NodeProperties::GetContextInput(node)); | |
| 146 } | |
| 147 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 162 input0, input1, context, frame_state_2, | |
| 163 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 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 184 input0, input1, context, frame_state_2, | |
| 185 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 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 207 input0, input1, context, frame_state_2, | |
| 208 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 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 232 input0, input1, context, frame_state_2, | |
| 233 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 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 254 input0, input1, context, frame_state_2, | |
| 255 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 | |
| 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(javascript()->CallFunction(2, VectorSlotPair()), | |
| 276 input0, input1, context, frame_state_2, | |
| 277 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 | |
| OLD | NEW |