OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/compiler-source-position-table.h" | 5 #include "src/compiler/compiler-source-position-table.h" |
6 #include "src/compiler/js-context-specialization.h" | 6 #include "src/compiler/js-context-specialization.h" |
7 #include "src/compiler/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/js-operator.h" | 8 #include "src/compiler/js-operator.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
11 #include "test/cctest/cctest.h" | 11 #include "test/cctest/cctest.h" |
12 #include "test/cctest/compiler/function-tester.h" | 12 #include "test/cctest/compiler/function-tester.h" |
13 #include "test/cctest/compiler/graph-builder-tester.h" | 13 #include "test/cctest/compiler/graph-builder-tester.h" |
14 | 14 |
15 namespace v8 { | 15 namespace v8 { |
16 namespace internal { | 16 namespace internal { |
17 namespace compiler { | 17 namespace compiler { |
18 | 18 |
19 class ContextSpecializationTester : public HandleAndZoneScope { | 19 class ContextSpecializationTester : public HandleAndZoneScope { |
20 public: | 20 public: |
21 ContextSpecializationTester() | 21 explicit ContextSpecializationTester(MaybeHandle<Context> context) |
22 : graph_(new (main_zone()) Graph(main_zone())), | 22 : graph_(new (main_zone()) Graph(main_zone())), |
23 common_(main_zone()), | 23 common_(main_zone()), |
24 javascript_(main_zone()), | 24 javascript_(main_zone()), |
25 machine_(main_zone()), | 25 machine_(main_zone()), |
26 simplified_(main_zone()), | 26 simplified_(main_zone()), |
27 jsgraph_(main_isolate(), graph(), common(), &javascript_, &simplified_, | 27 jsgraph_(main_isolate(), graph(), common(), &javascript_, &simplified_, |
28 &machine_), | 28 &machine_), |
29 reducer_(main_zone(), graph()), | 29 reducer_(main_zone(), graph()), |
30 spec_(&reducer_, jsgraph(), MaybeHandle<Context>()) {} | 30 spec_(&reducer_, jsgraph(), context) {} |
31 | 31 |
32 JSContextSpecialization* spec() { return &spec_; } | 32 JSContextSpecialization* spec() { return &spec_; } |
33 Factory* factory() { return main_isolate()->factory(); } | 33 Factory* factory() { return main_isolate()->factory(); } |
34 CommonOperatorBuilder* common() { return &common_; } | 34 CommonOperatorBuilder* common() { return &common_; } |
35 JSOperatorBuilder* javascript() { return &javascript_; } | 35 JSOperatorBuilder* javascript() { return &javascript_; } |
36 SimplifiedOperatorBuilder* simplified() { return &simplified_; } | 36 SimplifiedOperatorBuilder* simplified() { return &simplified_; } |
37 JSGraph* jsgraph() { return &jsgraph_; } | 37 JSGraph* jsgraph() { return &jsgraph_; } |
38 Graph* graph() { return graph_; } | 38 Graph* graph() { return graph_; } |
39 | 39 |
| 40 void CheckChangesToValue(Node* node, Handle<HeapObject> expected_value); |
| 41 void CheckContextInputAndDepthChanges( |
| 42 Node* node, Handle<Context> expected_new_context_object, |
| 43 size_t expected_new_depth); |
| 44 void CheckContextInputAndDepthChanges(Node* node, Node* expected_new_context, |
| 45 size_t expected_new_depth); |
| 46 |
40 private: | 47 private: |
41 Graph* graph_; | 48 Graph* graph_; |
42 CommonOperatorBuilder common_; | 49 CommonOperatorBuilder common_; |
43 JSOperatorBuilder javascript_; | 50 JSOperatorBuilder javascript_; |
44 MachineOperatorBuilder machine_; | 51 MachineOperatorBuilder machine_; |
45 SimplifiedOperatorBuilder simplified_; | 52 SimplifiedOperatorBuilder simplified_; |
46 JSGraph jsgraph_; | 53 JSGraph jsgraph_; |
47 GraphReducer reducer_; | 54 GraphReducer reducer_; |
48 JSContextSpecialization spec_; | 55 JSContextSpecialization spec_; |
49 }; | 56 }; |
50 | 57 |
| 58 void ContextSpecializationTester::CheckChangesToValue( |
| 59 Node* node, Handle<HeapObject> expected_value) { |
| 60 Reduction r = spec()->Reduce(node); |
| 61 CHECK(r.Changed()); |
| 62 HeapObjectMatcher match(r.replacement()); |
| 63 CHECK(match.HasValue()); |
| 64 CHECK_EQ(*match.Value(), *expected_value); |
| 65 } |
51 | 66 |
52 TEST(ReduceJSLoadContext) { | 67 void ContextSpecializationTester::CheckContextInputAndDepthChanges( |
53 ContextSpecializationTester t; | 68 Node* node, Handle<Context> expected_new_context_object, |
| 69 size_t expected_new_depth) { |
| 70 ContextAccess access = OpParameter<ContextAccess>(node); |
| 71 Reduction r = spec()->Reduce(node); |
| 72 CHECK(r.Changed()); |
| 73 |
| 74 Node* new_context = NodeProperties::GetContextInput(r.replacement()); |
| 75 CHECK_EQ(IrOpcode::kHeapConstant, new_context->opcode()); |
| 76 HeapObjectMatcher match(new_context); |
| 77 CHECK_EQ(*match.Value(), *expected_new_context_object); |
| 78 |
| 79 ContextAccess new_access = OpParameter<ContextAccess>(r.replacement()); |
| 80 CHECK_EQ(new_access.depth(), expected_new_depth); |
| 81 CHECK_EQ(new_access.index(), access.index()); |
| 82 CHECK_EQ(new_access.immutable(), access.immutable()); |
| 83 } |
| 84 |
| 85 void ContextSpecializationTester::CheckContextInputAndDepthChanges( |
| 86 Node* node, Node* expected_new_context, size_t expected_new_depth) { |
| 87 ContextAccess access = OpParameter<ContextAccess>(node); |
| 88 Reduction r = spec()->Reduce(node); |
| 89 CHECK(r.Changed()); |
| 90 |
| 91 Node* new_context = NodeProperties::GetContextInput(r.replacement()); |
| 92 CHECK_EQ(new_context, expected_new_context); |
| 93 |
| 94 ContextAccess new_access = OpParameter<ContextAccess>(r.replacement()); |
| 95 CHECK_EQ(new_access.depth(), expected_new_depth); |
| 96 CHECK_EQ(new_access.index(), access.index()); |
| 97 CHECK_EQ(new_access.immutable(), access.immutable()); |
| 98 } |
| 99 |
| 100 static const int slot_index = Context::NATIVE_CONTEXT_INDEX; |
| 101 |
| 102 TEST(ReduceJSLoadContext0) { |
| 103 ContextSpecializationTester t((MaybeHandle<Context>())); |
54 | 104 |
55 Node* start = t.graph()->NewNode(t.common()->Start(0)); | 105 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
56 t.graph()->SetStart(start); | 106 t.graph()->SetStart(start); |
57 | 107 |
58 // Make a context and initialize it a bit for this test. | 108 // Make a context and initialize it a bit for this test. |
59 Handle<Context> native = t.factory()->NewNativeContext(); | 109 Handle<Context> native = t.factory()->NewNativeContext(); |
60 Handle<Context> subcontext1 = t.factory()->NewNativeContext(); | 110 Handle<Context> subcontext1 = t.factory()->NewNativeContext(); |
61 Handle<Context> subcontext2 = t.factory()->NewNativeContext(); | 111 Handle<Context> subcontext2 = t.factory()->NewNativeContext(); |
62 subcontext2->set_previous(*subcontext1); | 112 subcontext2->set_previous(*subcontext1); |
63 subcontext1->set_previous(*native); | 113 subcontext1->set_previous(*native); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), | 157 Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), |
108 const_context, start); | 158 const_context, start); |
109 Reduction r = t.spec()->Reduce(load); | 159 Reduction r = t.spec()->Reduce(load); |
110 CHECK(r.Changed()); | 160 CHECK(r.Changed()); |
111 CHECK(r.replacement() != load); | 161 CHECK(r.replacement() != load); |
112 | 162 |
113 HeapObjectMatcher match(r.replacement()); | 163 HeapObjectMatcher match(r.replacement()); |
114 CHECK(match.HasValue()); | 164 CHECK(match.HasValue()); |
115 CHECK_EQ(*expected, *match.Value()); | 165 CHECK_EQ(*expected, *match.Value()); |
116 } | 166 } |
117 | 167 } |
118 // TODO(titzer): test with other kinds of contexts, e.g. a function context. | 168 |
119 // TODO(sigurds): test that loads below create context are not optimized | 169 TEST(ReduceJSLoadContext1) { |
120 } | 170 // The graph's context chain ends in the incoming context parameter: |
121 | 171 // |
122 | 172 // context2 <-- context1 <-- context0 (= Parameter(0)) |
123 TEST(ReduceJSStoreContext) { | 173 |
124 ContextSpecializationTester t; | 174 ContextSpecializationTester t((MaybeHandle<Context>())); |
125 | 175 |
126 Node* start = t.graph()->NewNode(t.common()->Start(0)); | 176 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
127 t.graph()->SetStart(start); | 177 t.graph()->SetStart(start); |
| 178 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 179 const i::compiler::Operator* create_function_context = |
| 180 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 181 |
| 182 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); |
| 183 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 184 context0, start, start); |
| 185 Node* context2 = t.graph()->NewNode(create_function_context, undefined, |
| 186 context1, start, start); |
| 187 |
| 188 { |
| 189 Node* load = t.graph()->NewNode( |
| 190 t.javascript()->LoadContext(0, slot_index, false), context2, start); |
| 191 CHECK(!t.spec()->Reduce(load).Changed()); |
| 192 } |
| 193 |
| 194 { |
| 195 Node* load = t.graph()->NewNode( |
| 196 t.javascript()->LoadContext(0, slot_index, true), context2, start); |
| 197 CHECK(!t.spec()->Reduce(load).Changed()); |
| 198 } |
| 199 |
| 200 { |
| 201 Node* load = t.graph()->NewNode( |
| 202 t.javascript()->LoadContext(1, slot_index, false), context2, start); |
| 203 t.CheckContextInputAndDepthChanges(load, context1, 0); |
| 204 } |
| 205 |
| 206 { |
| 207 Node* load = t.graph()->NewNode( |
| 208 t.javascript()->LoadContext(1, slot_index, true), context2, start); |
| 209 t.CheckContextInputAndDepthChanges(load, context1, 0); |
| 210 } |
| 211 |
| 212 { |
| 213 Node* load = t.graph()->NewNode( |
| 214 t.javascript()->LoadContext(2, slot_index, false), context2, start); |
| 215 t.CheckContextInputAndDepthChanges(load, context0, 0); |
| 216 } |
| 217 |
| 218 { |
| 219 Node* load = t.graph()->NewNode( |
| 220 t.javascript()->LoadContext(2, slot_index, true), context2, start); |
| 221 t.CheckContextInputAndDepthChanges(load, context0, 0); |
| 222 } |
| 223 |
| 224 { |
| 225 Node* load = t.graph()->NewNode( |
| 226 t.javascript()->LoadContext(3, slot_index, false), context2, start); |
| 227 t.CheckContextInputAndDepthChanges(load, context0, 1); |
| 228 } |
| 229 |
| 230 { |
| 231 Node* load = t.graph()->NewNode( |
| 232 t.javascript()->LoadContext(3, slot_index, true), context2, start); |
| 233 t.CheckContextInputAndDepthChanges(load, context0, 1); |
| 234 } |
| 235 } |
| 236 |
| 237 TEST(ReduceJSLoadContext2) { |
| 238 // The graph's context chain ends in a constant context (context_object1), |
| 239 // which has has another outer context (context_object0). |
| 240 // |
| 241 // context2 <-- context1 <-- context0 (= HeapConstant(context_object1)) |
| 242 // context_object1 <~~ context_object0 |
| 243 |
| 244 ContextSpecializationTester t((MaybeHandle<Context>())); |
| 245 |
| 246 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 247 t.graph()->SetStart(start); |
| 248 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 249 const i::compiler::Operator* create_function_context = |
| 250 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 251 |
| 252 Handle<HeapObject> slot_value0 = t.factory()->InternalizeUtf8String("0"); |
| 253 Handle<HeapObject> slot_value1 = t.factory()->InternalizeUtf8String("1"); |
| 254 |
| 255 Handle<Context> context_object0 = t.factory()->NewNativeContext(); |
| 256 Handle<Context> context_object1 = t.factory()->NewNativeContext(); |
| 257 context_object1->set_previous(*context_object0); |
| 258 context_object0->set(slot_index, *slot_value0); |
| 259 context_object1->set(slot_index, *slot_value1); |
| 260 |
| 261 Node* context0 = t.jsgraph()->Constant(context_object1); |
| 262 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 263 context0, start, start); |
| 264 Node* context2 = t.graph()->NewNode(create_function_context, undefined, |
| 265 context1, start, start); |
| 266 |
| 267 { |
| 268 Node* load = t.graph()->NewNode( |
| 269 t.javascript()->LoadContext(0, slot_index, false), context2, start); |
| 270 CHECK(!t.spec()->Reduce(load).Changed()); |
| 271 } |
| 272 |
| 273 { |
| 274 Node* load = t.graph()->NewNode( |
| 275 t.javascript()->LoadContext(0, slot_index, true), context2, start); |
| 276 CHECK(!t.spec()->Reduce(load).Changed()); |
| 277 } |
| 278 |
| 279 { |
| 280 Node* load = t.graph()->NewNode( |
| 281 t.javascript()->LoadContext(1, slot_index, false), context2, start); |
| 282 t.CheckContextInputAndDepthChanges(load, context1, 0); |
| 283 } |
| 284 |
| 285 { |
| 286 Node* load = t.graph()->NewNode( |
| 287 t.javascript()->LoadContext(1, slot_index, true), context2, start); |
| 288 t.CheckContextInputAndDepthChanges(load, context1, 0); |
| 289 } |
| 290 |
| 291 { |
| 292 Node* load = t.graph()->NewNode( |
| 293 t.javascript()->LoadContext(2, slot_index, false), context2, start); |
| 294 t.CheckContextInputAndDepthChanges(load, context0, 0); |
| 295 } |
| 296 |
| 297 { |
| 298 Node* load = t.graph()->NewNode( |
| 299 t.javascript()->LoadContext(2, slot_index, true), context2, start); |
| 300 t.CheckChangesToValue(load, slot_value1); |
| 301 } |
| 302 |
| 303 { |
| 304 Node* load = t.graph()->NewNode( |
| 305 t.javascript()->LoadContext(3, slot_index, false), context2, start); |
| 306 t.CheckContextInputAndDepthChanges(load, context_object0, 0); |
| 307 } |
| 308 |
| 309 { |
| 310 Node* load = t.graph()->NewNode( |
| 311 t.javascript()->LoadContext(3, slot_index, true), context2, start); |
| 312 t.CheckChangesToValue(load, slot_value0); |
| 313 } |
| 314 } |
| 315 |
| 316 TEST(ReduceJSLoadContext3) { |
| 317 // Like in ReduceJSLoadContext1, the graph's context chain ends in the |
| 318 // incoming context parameter. However, this time we provide a concrete |
| 319 // context for this parameter as the "specialization context". We choose |
| 320 // context_object2 from ReduceJSLoadContext2 for this, so almost all test |
| 321 // expectations are the same as in ReduceJSLoadContext2. |
| 322 |
| 323 HandleAndZoneScope handle_zone_scope; |
| 324 auto factory = handle_zone_scope.main_isolate()->factory(); |
| 325 |
| 326 Handle<HeapObject> slot_value0 = factory->InternalizeUtf8String("0"); |
| 327 Handle<HeapObject> slot_value1 = factory->InternalizeUtf8String("1"); |
| 328 |
| 329 Handle<Context> context_object0 = factory->NewNativeContext(); |
| 330 Handle<Context> context_object1 = factory->NewNativeContext(); |
| 331 context_object1->set_previous(*context_object0); |
| 332 context_object0->set(slot_index, *slot_value0); |
| 333 context_object1->set(slot_index, *slot_value1); |
| 334 |
| 335 ContextSpecializationTester t(context_object1); |
| 336 |
| 337 Node* start = t.graph()->NewNode(t.common()->Start(2)); |
| 338 t.graph()->SetStart(start); |
| 339 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 340 const i::compiler::Operator* create_function_context = |
| 341 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 342 |
| 343 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); |
| 344 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 345 context0, start, start); |
| 346 Node* context2 = t.graph()->NewNode(create_function_context, undefined, |
| 347 context1, start, start); |
| 348 |
| 349 { |
| 350 Node* load = t.graph()->NewNode( |
| 351 t.javascript()->LoadContext(0, slot_index, false), context2, start); |
| 352 CHECK(!t.spec()->Reduce(load).Changed()); |
| 353 } |
| 354 |
| 355 { |
| 356 Node* load = t.graph()->NewNode( |
| 357 t.javascript()->LoadContext(0, slot_index, true), context2, start); |
| 358 CHECK(!t.spec()->Reduce(load).Changed()); |
| 359 } |
| 360 |
| 361 { |
| 362 Node* load = t.graph()->NewNode( |
| 363 t.javascript()->LoadContext(1, slot_index, false), context2, start); |
| 364 t.CheckContextInputAndDepthChanges(load, context1, 0); |
| 365 } |
| 366 |
| 367 { |
| 368 Node* load = t.graph()->NewNode( |
| 369 t.javascript()->LoadContext(1, slot_index, true), context2, start); |
| 370 t.CheckContextInputAndDepthChanges(load, context1, 0); |
| 371 } |
| 372 |
| 373 { |
| 374 Node* load = t.graph()->NewNode( |
| 375 t.javascript()->LoadContext(2, slot_index, false), context2, start); |
| 376 t.CheckContextInputAndDepthChanges(load, context_object1, 0); |
| 377 } |
| 378 |
| 379 { |
| 380 Node* load = t.graph()->NewNode( |
| 381 t.javascript()->LoadContext(2, slot_index, true), context2, start); |
| 382 t.CheckChangesToValue(load, slot_value1); |
| 383 } |
| 384 |
| 385 { |
| 386 Node* load = t.graph()->NewNode( |
| 387 t.javascript()->LoadContext(3, slot_index, false), context2, start); |
| 388 t.CheckContextInputAndDepthChanges(load, context_object0, 0); |
| 389 } |
| 390 |
| 391 { |
| 392 Node* load = t.graph()->NewNode( |
| 393 t.javascript()->LoadContext(3, slot_index, true), context2, start); |
| 394 t.CheckChangesToValue(load, slot_value0); |
| 395 } |
| 396 } |
| 397 |
| 398 TEST(ReduceJSStoreContext0) { |
| 399 ContextSpecializationTester t((MaybeHandle<Context>())); |
| 400 |
| 401 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 402 t.graph()->SetStart(start); |
128 | 403 |
129 // Make a context and initialize it a bit for this test. | 404 // Make a context and initialize it a bit for this test. |
130 Handle<Context> native = t.factory()->NewNativeContext(); | 405 Handle<Context> native = t.factory()->NewNativeContext(); |
131 Handle<Context> subcontext1 = t.factory()->NewNativeContext(); | 406 Handle<Context> subcontext1 = t.factory()->NewNativeContext(); |
132 Handle<Context> subcontext2 = t.factory()->NewNativeContext(); | 407 Handle<Context> subcontext2 = t.factory()->NewNativeContext(); |
133 subcontext2->set_previous(*subcontext1); | 408 subcontext2->set_previous(*subcontext1); |
134 subcontext1->set_previous(*native); | 409 subcontext1->set_previous(*native); |
135 Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); | 410 Handle<Object> expected = t.factory()->InternalizeUtf8String("gboy!"); |
136 const int slot = Context::NATIVE_CONTEXT_INDEX; | 411 const int slot = Context::NATIVE_CONTEXT_INDEX; |
137 native->set(slot, *expected); | 412 native->set(slot, *expected); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); | 450 CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); |
176 HeapObjectMatcher match(new_context_input); | 451 HeapObjectMatcher match(new_context_input); |
177 CHECK_EQ(*native, *match.Value()); | 452 CHECK_EQ(*native, *match.Value()); |
178 ContextAccess access = OpParameter<ContextAccess>(r.replacement()); | 453 ContextAccess access = OpParameter<ContextAccess>(r.replacement()); |
179 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); | 454 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); |
180 CHECK_EQ(0, static_cast<int>(access.depth())); | 455 CHECK_EQ(0, static_cast<int>(access.depth())); |
181 CHECK_EQ(false, access.immutable()); | 456 CHECK_EQ(false, access.immutable()); |
182 } | 457 } |
183 } | 458 } |
184 | 459 |
| 460 TEST(ReduceJSStoreContext1) { |
| 461 ContextSpecializationTester t((MaybeHandle<Context>())); |
| 462 |
| 463 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 464 t.graph()->SetStart(start); |
| 465 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 466 const i::compiler::Operator* create_function_context = |
| 467 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 468 |
| 469 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); |
| 470 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 471 context0, start, start); |
| 472 Node* context2 = t.graph()->NewNode(create_function_context, undefined, |
| 473 context1, start, start); |
| 474 |
| 475 { |
| 476 Node* store = |
| 477 t.graph()->NewNode(t.javascript()->StoreContext(0, slot_index), |
| 478 context2, context2, start, start); |
| 479 CHECK(!t.spec()->Reduce(store).Changed()); |
| 480 } |
| 481 |
| 482 { |
| 483 Node* store = |
| 484 t.graph()->NewNode(t.javascript()->StoreContext(1, slot_index), |
| 485 context2, context2, start, start); |
| 486 t.CheckContextInputAndDepthChanges(store, context1, 0); |
| 487 } |
| 488 |
| 489 { |
| 490 Node* store = |
| 491 t.graph()->NewNode(t.javascript()->StoreContext(2, slot_index), |
| 492 context2, context2, start, start); |
| 493 t.CheckContextInputAndDepthChanges(store, context0, 0); |
| 494 } |
| 495 |
| 496 { |
| 497 Node* store = |
| 498 t.graph()->NewNode(t.javascript()->StoreContext(3, slot_index), |
| 499 context2, context2, start, start); |
| 500 t.CheckContextInputAndDepthChanges(store, context0, 1); |
| 501 } |
| 502 } |
| 503 |
| 504 TEST(ReduceJSStoreContext2) { |
| 505 ContextSpecializationTester t((MaybeHandle<Context>())); |
| 506 |
| 507 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 508 t.graph()->SetStart(start); |
| 509 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 510 const i::compiler::Operator* create_function_context = |
| 511 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 512 |
| 513 Handle<HeapObject> slot_value0 = t.factory()->InternalizeUtf8String("0"); |
| 514 Handle<HeapObject> slot_value1 = t.factory()->InternalizeUtf8String("1"); |
| 515 |
| 516 Handle<Context> context_object0 = t.factory()->NewNativeContext(); |
| 517 Handle<Context> context_object1 = t.factory()->NewNativeContext(); |
| 518 context_object1->set_previous(*context_object0); |
| 519 context_object0->set(slot_index, *slot_value0); |
| 520 context_object1->set(slot_index, *slot_value1); |
| 521 |
| 522 Node* context0 = t.jsgraph()->Constant(context_object1); |
| 523 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 524 context0, start, start); |
| 525 Node* context2 = t.graph()->NewNode(create_function_context, undefined, |
| 526 context1, start, start); |
| 527 |
| 528 { |
| 529 Node* store = |
| 530 t.graph()->NewNode(t.javascript()->StoreContext(0, slot_index), |
| 531 context2, context2, start, start); |
| 532 CHECK(!t.spec()->Reduce(store).Changed()); |
| 533 } |
| 534 |
| 535 { |
| 536 Node* store = |
| 537 t.graph()->NewNode(t.javascript()->StoreContext(1, slot_index), |
| 538 context2, context2, start, start); |
| 539 t.CheckContextInputAndDepthChanges(store, context1, 0); |
| 540 } |
| 541 |
| 542 { |
| 543 Node* store = |
| 544 t.graph()->NewNode(t.javascript()->StoreContext(2, slot_index), |
| 545 context2, context2, start, start); |
| 546 t.CheckContextInputAndDepthChanges(store, context0, 0); |
| 547 } |
| 548 |
| 549 { |
| 550 Node* store = |
| 551 t.graph()->NewNode(t.javascript()->StoreContext(3, slot_index), |
| 552 context2, context2, start, start); |
| 553 t.CheckContextInputAndDepthChanges(store, context_object0, 0); |
| 554 } |
| 555 } |
| 556 |
| 557 TEST(ReduceJSStoreContext3) { |
| 558 HandleAndZoneScope handle_zone_scope; |
| 559 auto factory = handle_zone_scope.main_isolate()->factory(); |
| 560 |
| 561 Handle<HeapObject> slot_value0 = factory->InternalizeUtf8String("0"); |
| 562 Handle<HeapObject> slot_value1 = factory->InternalizeUtf8String("1"); |
| 563 |
| 564 Handle<Context> context_object0 = factory->NewNativeContext(); |
| 565 Handle<Context> context_object1 = factory->NewNativeContext(); |
| 566 context_object1->set_previous(*context_object0); |
| 567 context_object0->set(slot_index, *slot_value0); |
| 568 context_object1->set(slot_index, *slot_value1); |
| 569 |
| 570 ContextSpecializationTester t(context_object1); |
| 571 |
| 572 Node* start = t.graph()->NewNode(t.common()->Start(2)); |
| 573 t.graph()->SetStart(start); |
| 574 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 575 const i::compiler::Operator* create_function_context = |
| 576 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 577 |
| 578 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); |
| 579 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 580 context0, start, start); |
| 581 Node* context2 = t.graph()->NewNode(create_function_context, undefined, |
| 582 context1, start, start); |
| 583 |
| 584 { |
| 585 Node* store = |
| 586 t.graph()->NewNode(t.javascript()->StoreContext(0, slot_index), |
| 587 context2, context2, start, start); |
| 588 CHECK(!t.spec()->Reduce(store).Changed()); |
| 589 } |
| 590 |
| 591 { |
| 592 Node* store = |
| 593 t.graph()->NewNode(t.javascript()->StoreContext(1, slot_index), |
| 594 context2, context2, start, start); |
| 595 t.CheckContextInputAndDepthChanges(store, context1, 0); |
| 596 } |
| 597 |
| 598 { |
| 599 Node* store = |
| 600 t.graph()->NewNode(t.javascript()->StoreContext(2, slot_index), |
| 601 context2, context2, start, start); |
| 602 t.CheckContextInputAndDepthChanges(store, context_object1, 0); |
| 603 } |
| 604 |
| 605 { |
| 606 Node* store = |
| 607 t.graph()->NewNode(t.javascript()->StoreContext(3, slot_index), |
| 608 context2, context2, start, start); |
| 609 t.CheckContextInputAndDepthChanges(store, context_object0, 0); |
| 610 } |
| 611 } |
185 | 612 |
186 TEST(SpecializeJSFunction_ToConstant1) { | 613 TEST(SpecializeJSFunction_ToConstant1) { |
187 FunctionTester T( | 614 FunctionTester T( |
188 "(function() { var x = 1; function inc(a)" | 615 "(function() { var x = 1; function inc(a)" |
189 " { return a + x; } return inc; })()"); | 616 " { return a + x; } return inc; })()"); |
190 | 617 |
191 T.CheckCall(1.0, 0.0, 0.0); | 618 T.CheckCall(1.0, 0.0, 0.0); |
192 T.CheckCall(2.0, 1.0, 0.0); | 619 T.CheckCall(2.0, 1.0, 0.0); |
193 T.CheckCall(2.1, 1.1, 0.0); | 620 T.CheckCall(2.1, 1.1, 0.0); |
194 } | 621 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 | 666 |
240 CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 667 CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
241 CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 668 CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
242 CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 669 CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
243 } | 670 } |
244 } | 671 } |
245 | 672 |
246 } // namespace compiler | 673 } // namespace compiler |
247 } // namespace internal | 674 } // namespace internal |
248 } // namespace v8 | 675 } // namespace v8 |
OLD | NEW |