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 |