| 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 "src/factory.h" | 11 #include "src/factory.h" |
| 12 #include "src/objects-inl.h" | 12 #include "src/objects-inl.h" |
| 13 #include "src/property.h" | 13 #include "src/property.h" |
| 14 #include "test/cctest/cctest.h" | 14 #include "test/cctest/cctest.h" |
| 15 #include "test/cctest/compiler/function-tester.h" | 15 #include "test/cctest/compiler/function-tester.h" |
| 16 #include "test/cctest/compiler/graph-builder-tester.h" | 16 #include "test/cctest/compiler/graph-builder-tester.h" |
| 17 | 17 |
| 18 namespace v8 { | 18 namespace v8 { |
| 19 namespace internal { | 19 namespace internal { |
| 20 namespace compiler { | 20 namespace compiler { |
| 21 | 21 |
| 22 class ContextSpecializationTester : public HandleAndZoneScope { | 22 class ContextSpecializationTester : public HandleAndZoneScope { |
| 23 public: | 23 public: |
| 24 explicit ContextSpecializationTester(MaybeHandle<Context> context) | 24 explicit ContextSpecializationTester(Maybe<OuterContext> context) |
| 25 : graph_(new (main_zone()) Graph(main_zone())), | 25 : graph_(new (main_zone()) Graph(main_zone())), |
| 26 common_(main_zone()), | 26 common_(main_zone()), |
| 27 javascript_(main_zone()), | 27 javascript_(main_zone()), |
| 28 machine_(main_zone()), | 28 machine_(main_zone()), |
| 29 simplified_(main_zone()), | 29 simplified_(main_zone()), |
| 30 jsgraph_(main_isolate(), graph(), common(), &javascript_, &simplified_, | 30 jsgraph_(main_isolate(), graph(), common(), &javascript_, &simplified_, |
| 31 &machine_), | 31 &machine_), |
| 32 reducer_(main_zone(), graph()), | 32 reducer_(main_zone(), graph()), |
| 33 spec_(&reducer_, jsgraph(), context, MaybeHandle<JSFunction>()) {} | 33 spec_(&reducer_, jsgraph(), context, MaybeHandle<JSFunction>()) {} |
| 34 | 34 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 | 96 |
| 97 ContextAccess new_access = OpParameter<ContextAccess>(r.replacement()); | 97 ContextAccess new_access = OpParameter<ContextAccess>(r.replacement()); |
| 98 CHECK_EQ(new_access.depth(), expected_new_depth); | 98 CHECK_EQ(new_access.depth(), expected_new_depth); |
| 99 CHECK_EQ(new_access.index(), access.index()); | 99 CHECK_EQ(new_access.index(), access.index()); |
| 100 CHECK_EQ(new_access.immutable(), access.immutable()); | 100 CHECK_EQ(new_access.immutable(), access.immutable()); |
| 101 } | 101 } |
| 102 | 102 |
| 103 static const int slot_index = Context::NATIVE_CONTEXT_INDEX; | 103 static const int slot_index = Context::NATIVE_CONTEXT_INDEX; |
| 104 | 104 |
| 105 TEST(ReduceJSLoadContext0) { | 105 TEST(ReduceJSLoadContext0) { |
| 106 ContextSpecializationTester t((MaybeHandle<Context>())); | 106 ContextSpecializationTester t(Nothing<OuterContext>()); |
| 107 | 107 |
| 108 Node* start = t.graph()->NewNode(t.common()->Start(0)); | 108 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 109 t.graph()->SetStart(start); | 109 t.graph()->SetStart(start); |
| 110 | 110 |
| 111 // Make a context and initialize it a bit for this test. | 111 // Make a context and initialize it a bit for this test. |
| 112 Handle<Context> native = t.factory()->NewNativeContext(); | 112 Handle<Context> native = t.factory()->NewNativeContext(); |
| 113 Handle<Context> subcontext1 = t.factory()->NewNativeContext(); | 113 Handle<Context> subcontext1 = t.factory()->NewNativeContext(); |
| 114 Handle<Context> subcontext2 = t.factory()->NewNativeContext(); | 114 Handle<Context> subcontext2 = t.factory()->NewNativeContext(); |
| 115 subcontext2->set_previous(*subcontext1); | 115 subcontext2->set_previous(*subcontext1); |
| 116 subcontext1->set_previous(*native); | 116 subcontext1->set_previous(*native); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 CHECK(match.HasValue()); | 167 CHECK(match.HasValue()); |
| 168 CHECK_EQ(*expected, *match.Value()); | 168 CHECK_EQ(*expected, *match.Value()); |
| 169 } | 169 } |
| 170 } | 170 } |
| 171 | 171 |
| 172 TEST(ReduceJSLoadContext1) { | 172 TEST(ReduceJSLoadContext1) { |
| 173 // The graph's context chain ends in the incoming context parameter: | 173 // The graph's context chain ends in the incoming context parameter: |
| 174 // | 174 // |
| 175 // context2 <-- context1 <-- context0 (= Parameter(0)) | 175 // context2 <-- context1 <-- context0 (= Parameter(0)) |
| 176 | 176 |
| 177 ContextSpecializationTester t((MaybeHandle<Context>())); | 177 ContextSpecializationTester t(Nothing<OuterContext>()); |
| 178 | 178 |
| 179 Node* start = t.graph()->NewNode(t.common()->Start(0)); | 179 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 180 t.graph()->SetStart(start); | 180 t.graph()->SetStart(start); |
| 181 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); | 181 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 182 const i::compiler::Operator* create_function_context = | 182 const i::compiler::Operator* create_function_context = |
| 183 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); | 183 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 184 | 184 |
| 185 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); | 185 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); |
| 186 Node* context1 = t.graph()->NewNode(create_function_context, undefined, | 186 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 187 context0, start, start); | 187 context0, start, start); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 | 232 |
| 233 { | 233 { |
| 234 Node* load = t.graph()->NewNode( | 234 Node* load = t.graph()->NewNode( |
| 235 t.javascript()->LoadContext(3, slot_index, true), context2, start); | 235 t.javascript()->LoadContext(3, slot_index, true), context2, start); |
| 236 t.CheckContextInputAndDepthChanges(load, context0, 1); | 236 t.CheckContextInputAndDepthChanges(load, context0, 1); |
| 237 } | 237 } |
| 238 } | 238 } |
| 239 | 239 |
| 240 TEST(ReduceJSLoadContext2) { | 240 TEST(ReduceJSLoadContext2) { |
| 241 // The graph's context chain ends in a constant context (context_object1), | 241 // The graph's context chain ends in a constant context (context_object1), |
| 242 // which has has another outer context (context_object0). | 242 // which has another outer context (context_object0). |
| 243 // | 243 // |
| 244 // context2 <-- context1 <-- context0 (= HeapConstant(context_object1)) | 244 // context2 <-- context1 <-- context0 (= HeapConstant(context_object1)) |
| 245 // context_object1 <~~ context_object0 | 245 // context_object1 <~~ context_object0 |
| 246 | 246 |
| 247 ContextSpecializationTester t((MaybeHandle<Context>())); | 247 ContextSpecializationTester t(Nothing<OuterContext>()); |
| 248 | 248 |
| 249 Node* start = t.graph()->NewNode(t.common()->Start(0)); | 249 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 250 t.graph()->SetStart(start); | 250 t.graph()->SetStart(start); |
| 251 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); | 251 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 252 const i::compiler::Operator* create_function_context = | 252 const i::compiler::Operator* create_function_context = |
| 253 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); | 253 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 254 | 254 |
| 255 Handle<HeapObject> slot_value0 = t.factory()->InternalizeUtf8String("0"); | 255 Handle<HeapObject> slot_value0 = t.factory()->InternalizeUtf8String("0"); |
| 256 Handle<HeapObject> slot_value1 = t.factory()->InternalizeUtf8String("1"); | 256 Handle<HeapObject> slot_value1 = t.factory()->InternalizeUtf8String("1"); |
| 257 | 257 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 | 328 |
| 329 Handle<HeapObject> slot_value0 = factory->InternalizeUtf8String("0"); | 329 Handle<HeapObject> slot_value0 = factory->InternalizeUtf8String("0"); |
| 330 Handle<HeapObject> slot_value1 = factory->InternalizeUtf8String("1"); | 330 Handle<HeapObject> slot_value1 = factory->InternalizeUtf8String("1"); |
| 331 | 331 |
| 332 Handle<Context> context_object0 = factory->NewNativeContext(); | 332 Handle<Context> context_object0 = factory->NewNativeContext(); |
| 333 Handle<Context> context_object1 = factory->NewNativeContext(); | 333 Handle<Context> context_object1 = factory->NewNativeContext(); |
| 334 context_object1->set_previous(*context_object0); | 334 context_object1->set_previous(*context_object0); |
| 335 context_object0->set(slot_index, *slot_value0); | 335 context_object0->set(slot_index, *slot_value0); |
| 336 context_object1->set(slot_index, *slot_value1); | 336 context_object1->set(slot_index, *slot_value1); |
| 337 | 337 |
| 338 ContextSpecializationTester t(context_object1); | 338 ContextSpecializationTester t(Just(OuterContext(context_object1, 0))); |
| 339 | 339 |
| 340 Node* start = t.graph()->NewNode(t.common()->Start(2)); | 340 Node* start = t.graph()->NewNode(t.common()->Start(2)); |
| 341 t.graph()->SetStart(start); | 341 t.graph()->SetStart(start); |
| 342 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); | 342 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 343 const i::compiler::Operator* create_function_context = | 343 const i::compiler::Operator* create_function_context = |
| 344 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); | 344 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 345 | 345 |
| 346 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); | 346 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); |
| 347 Node* context1 = t.graph()->NewNode(create_function_context, undefined, | 347 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 348 context0, start, start); | 348 context0, start, start); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 } | 392 } |
| 393 | 393 |
| 394 { | 394 { |
| 395 Node* load = t.graph()->NewNode( | 395 Node* load = t.graph()->NewNode( |
| 396 t.javascript()->LoadContext(3, slot_index, true), context2, start); | 396 t.javascript()->LoadContext(3, slot_index, true), context2, start); |
| 397 t.CheckChangesToValue(load, slot_value0); | 397 t.CheckChangesToValue(load, slot_value0); |
| 398 } | 398 } |
| 399 } | 399 } |
| 400 | 400 |
| 401 TEST(ReduceJSStoreContext0) { | 401 TEST(ReduceJSStoreContext0) { |
| 402 ContextSpecializationTester t((MaybeHandle<Context>())); | 402 ContextSpecializationTester t(Nothing<OuterContext>()); |
| 403 | 403 |
| 404 Node* start = t.graph()->NewNode(t.common()->Start(0)); | 404 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 405 t.graph()->SetStart(start); | 405 t.graph()->SetStart(start); |
| 406 | 406 |
| 407 // Make a context and initialize it a bit for this test. | 407 // Make a context and initialize it a bit for this test. |
| 408 Handle<Context> native = t.factory()->NewNativeContext(); | 408 Handle<Context> native = t.factory()->NewNativeContext(); |
| 409 Handle<Context> subcontext1 = t.factory()->NewNativeContext(); | 409 Handle<Context> subcontext1 = t.factory()->NewNativeContext(); |
| 410 Handle<Context> subcontext2 = t.factory()->NewNativeContext(); | 410 Handle<Context> subcontext2 = t.factory()->NewNativeContext(); |
| 411 subcontext2->set_previous(*subcontext1); | 411 subcontext2->set_previous(*subcontext1); |
| 412 subcontext1->set_previous(*native); | 412 subcontext1->set_previous(*native); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 HeapObjectMatcher match(new_context_input); | 454 HeapObjectMatcher match(new_context_input); |
| 455 CHECK_EQ(*native, *match.Value()); | 455 CHECK_EQ(*native, *match.Value()); |
| 456 ContextAccess access = OpParameter<ContextAccess>(r.replacement()); | 456 ContextAccess access = OpParameter<ContextAccess>(r.replacement()); |
| 457 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); | 457 CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index())); |
| 458 CHECK_EQ(0, static_cast<int>(access.depth())); | 458 CHECK_EQ(0, static_cast<int>(access.depth())); |
| 459 CHECK_EQ(false, access.immutable()); | 459 CHECK_EQ(false, access.immutable()); |
| 460 } | 460 } |
| 461 } | 461 } |
| 462 | 462 |
| 463 TEST(ReduceJSStoreContext1) { | 463 TEST(ReduceJSStoreContext1) { |
| 464 ContextSpecializationTester t((MaybeHandle<Context>())); | 464 ContextSpecializationTester t(Nothing<OuterContext>()); |
| 465 | 465 |
| 466 Node* start = t.graph()->NewNode(t.common()->Start(0)); | 466 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 467 t.graph()->SetStart(start); | 467 t.graph()->SetStart(start); |
| 468 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); | 468 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 469 const i::compiler::Operator* create_function_context = | 469 const i::compiler::Operator* create_function_context = |
| 470 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); | 470 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 471 | 471 |
| 472 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); | 472 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); |
| 473 Node* context1 = t.graph()->NewNode(create_function_context, undefined, | 473 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 474 context0, start, start); | 474 context0, start, start); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 498 | 498 |
| 499 { | 499 { |
| 500 Node* store = | 500 Node* store = |
| 501 t.graph()->NewNode(t.javascript()->StoreContext(3, slot_index), | 501 t.graph()->NewNode(t.javascript()->StoreContext(3, slot_index), |
| 502 context2, context2, start, start); | 502 context2, context2, start, start); |
| 503 t.CheckContextInputAndDepthChanges(store, context0, 1); | 503 t.CheckContextInputAndDepthChanges(store, context0, 1); |
| 504 } | 504 } |
| 505 } | 505 } |
| 506 | 506 |
| 507 TEST(ReduceJSStoreContext2) { | 507 TEST(ReduceJSStoreContext2) { |
| 508 ContextSpecializationTester t((MaybeHandle<Context>())); | 508 ContextSpecializationTester t(Nothing<OuterContext>()); |
| 509 | 509 |
| 510 Node* start = t.graph()->NewNode(t.common()->Start(0)); | 510 Node* start = t.graph()->NewNode(t.common()->Start(0)); |
| 511 t.graph()->SetStart(start); | 511 t.graph()->SetStart(start); |
| 512 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); | 512 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 513 const i::compiler::Operator* create_function_context = | 513 const i::compiler::Operator* create_function_context = |
| 514 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); | 514 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 515 | 515 |
| 516 Handle<HeapObject> slot_value0 = t.factory()->InternalizeUtf8String("0"); | 516 Handle<HeapObject> slot_value0 = t.factory()->InternalizeUtf8String("0"); |
| 517 Handle<HeapObject> slot_value1 = t.factory()->InternalizeUtf8String("1"); | 517 Handle<HeapObject> slot_value1 = t.factory()->InternalizeUtf8String("1"); |
| 518 | 518 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 | 563 |
| 564 Handle<HeapObject> slot_value0 = factory->InternalizeUtf8String("0"); | 564 Handle<HeapObject> slot_value0 = factory->InternalizeUtf8String("0"); |
| 565 Handle<HeapObject> slot_value1 = factory->InternalizeUtf8String("1"); | 565 Handle<HeapObject> slot_value1 = factory->InternalizeUtf8String("1"); |
| 566 | 566 |
| 567 Handle<Context> context_object0 = factory->NewNativeContext(); | 567 Handle<Context> context_object0 = factory->NewNativeContext(); |
| 568 Handle<Context> context_object1 = factory->NewNativeContext(); | 568 Handle<Context> context_object1 = factory->NewNativeContext(); |
| 569 context_object1->set_previous(*context_object0); | 569 context_object1->set_previous(*context_object0); |
| 570 context_object0->set(slot_index, *slot_value0); | 570 context_object0->set(slot_index, *slot_value0); |
| 571 context_object1->set(slot_index, *slot_value1); | 571 context_object1->set(slot_index, *slot_value1); |
| 572 | 572 |
| 573 ContextSpecializationTester t(context_object1); | 573 ContextSpecializationTester t(Just(OuterContext(context_object1, 0))); |
| 574 | 574 |
| 575 Node* start = t.graph()->NewNode(t.common()->Start(2)); | 575 Node* start = t.graph()->NewNode(t.common()->Start(2)); |
| 576 t.graph()->SetStart(start); | 576 t.graph()->SetStart(start); |
| 577 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); | 577 Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); |
| 578 const i::compiler::Operator* create_function_context = | 578 const i::compiler::Operator* create_function_context = |
| 579 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); | 579 t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); |
| 580 | 580 |
| 581 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); | 581 Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); |
| 582 Node* context1 = t.graph()->NewNode(create_function_context, undefined, | 582 Node* context1 = t.graph()->NewNode(create_function_context, undefined, |
| 583 context0, start, start); | 583 context0, start, start); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 | 669 |
| 670 CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 670 CHECK(T.Call(T.Val(0.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
| 671 CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 671 CHECK(T.Call(T.Val(2.0), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
| 672 CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); | 672 CHECK(T.Call(T.Val(-2.1), T.Val(0.0)).ToHandleChecked()->IsNaN()); |
| 673 } | 673 } |
| 674 } | 674 } |
| 675 | 675 |
| 676 } // namespace compiler | 676 } // namespace compiler |
| 677 } // namespace internal | 677 } // namespace internal |
| 678 } // namespace v8 | 678 } // namespace v8 |
| OLD | NEW |