OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/flow_graph_type_propagator.h" | 5 #include "vm/flow_graph_type_propagator.h" |
6 | 6 |
7 #include "vm/cha.h" | 7 #include "vm/cha.h" |
8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
9 #include "vm/il_printer.h" | 9 #include "vm/il_printer.h" |
10 #include "vm/regexp_assembler.h" | 10 #include "vm/regexp_assembler.h" |
11 #include "vm/timeline.h" | 11 #include "vm/timeline.h" |
12 | 12 |
13 namespace dart { | 13 namespace dart { |
14 | 14 |
15 DEFINE_FLAG(bool, trace_type_propagation, false, | 15 DEFINE_FLAG(bool, |
| 16 trace_type_propagation, |
| 17 false, |
16 "Trace flow graph type propagation"); | 18 "Trace flow graph type propagation"); |
17 | 19 |
18 DECLARE_FLAG(bool, propagate_types); | 20 DECLARE_FLAG(bool, propagate_types); |
19 | 21 |
20 | 22 |
21 void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) { | 23 void FlowGraphTypePropagator::Propagate(FlowGraph* flow_graph) { |
22 #ifndef PRODUCT | 24 #ifndef PRODUCT |
23 Thread* thread = flow_graph->thread(); | 25 Thread* thread = flow_graph->thread(); |
24 TimelineStream* compiler_timeline = Timeline::GetCompilerStream(); | 26 TimelineStream* compiler_timeline = Timeline::GetCompilerStream(); |
25 TimelineDurationScope tds2(thread, | 27 TimelineDurationScope tds2(thread, compiler_timeline, |
26 compiler_timeline, | |
27 "FlowGraphTypePropagator"); | 28 "FlowGraphTypePropagator"); |
28 #endif // !PRODUCT | 29 #endif // !PRODUCT |
29 FlowGraphTypePropagator propagator(flow_graph); | 30 FlowGraphTypePropagator propagator(flow_graph); |
30 propagator.Propagate(); | 31 propagator.Propagate(); |
31 } | 32 } |
32 | 33 |
33 | 34 |
34 FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph) | 35 FlowGraphTypePropagator::FlowGraphTypePropagator(FlowGraph* flow_graph) |
35 : FlowGraphVisitor(flow_graph->reverse_postorder()), | 36 : FlowGraphVisitor(flow_graph->reverse_postorder()), |
36 flow_graph_(flow_graph), | 37 flow_graph_(flow_graph), |
37 visited_blocks_(new(flow_graph->zone()) BitVector( | 38 visited_blocks_(new (flow_graph->zone()) |
38 flow_graph->zone(), flow_graph->reverse_postorder().length())), | 39 BitVector(flow_graph->zone(), |
| 40 flow_graph->reverse_postorder().length())), |
39 types_(flow_graph->current_ssa_temp_index()), | 41 types_(flow_graph->current_ssa_temp_index()), |
40 in_worklist_(new(flow_graph->zone()) BitVector( | 42 in_worklist_(new (flow_graph->zone()) |
41 flow_graph->zone(), flow_graph->current_ssa_temp_index())), | 43 BitVector(flow_graph->zone(), |
| 44 flow_graph->current_ssa_temp_index())), |
42 asserts_(NULL), | 45 asserts_(NULL), |
43 collected_asserts_(NULL) { | 46 collected_asserts_(NULL) { |
44 for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { | 47 for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { |
45 types_.Add(NULL); | 48 types_.Add(NULL); |
46 } | 49 } |
47 | 50 |
48 if (Isolate::Current()->type_checks()) { | 51 if (Isolate::Current()->type_checks()) { |
49 asserts_ = new ZoneGrowableArray<AssertAssignableInstr*>( | 52 asserts_ = new ZoneGrowableArray<AssertAssignableInstr*>( |
50 flow_graph->current_ssa_temp_index()); | 53 flow_graph->current_ssa_temp_index()); |
51 for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { | 54 for (intptr_t i = 0; i < flow_graph->current_ssa_temp_index(); i++) { |
(...skipping 21 matching lines...) Expand all Loading... |
73 for (intptr_t i = 0; i < worklist_.length(); i++) { | 76 for (intptr_t i = 0; i < worklist_.length(); i++) { |
74 ASSERT(worklist_[i]->IsPhi()); | 77 ASSERT(worklist_[i]->IsPhi()); |
75 *worklist_[i]->Type() = CompileType::None(); | 78 *worklist_[i]->Type() = CompileType::None(); |
76 } | 79 } |
77 | 80 |
78 // Iterate until a fixed point is reached, updating the types of | 81 // Iterate until a fixed point is reached, updating the types of |
79 // definitions. | 82 // definitions. |
80 while (!worklist_.is_empty()) { | 83 while (!worklist_.is_empty()) { |
81 Definition* def = RemoveLastFromWorklist(); | 84 Definition* def = RemoveLastFromWorklist(); |
82 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { | 85 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { |
83 THR_Print("recomputing type of v%" Pd ": %s\n", | 86 THR_Print("recomputing type of v%" Pd ": %s\n", def->ssa_temp_index(), |
84 def->ssa_temp_index(), | |
85 def->Type()->ToCString()); | 87 def->Type()->ToCString()); |
86 } | 88 } |
87 if (def->RecomputeType()) { | 89 if (def->RecomputeType()) { |
88 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { | 90 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { |
89 THR_Print(" ... new type %s\n", def->Type()->ToCString()); | 91 THR_Print(" ... new type %s\n", def->Type()->ToCString()); |
90 } | 92 } |
91 for (Value::Iterator it(def->input_use_list()); | 93 for (Value::Iterator it(def->input_use_list()); !it.Done(); |
92 !it.Done(); | |
93 it.Advance()) { | 94 it.Advance()) { |
94 Instruction* instr = it.Current()->instruction(); | 95 Instruction* instr = it.Current()->instruction(); |
95 | 96 |
96 Definition* use_defn = instr->AsDefinition(); | 97 Definition* use_defn = instr->AsDefinition(); |
97 if (use_defn != NULL) { | 98 if (use_defn != NULL) { |
98 AddToWorklist(use_defn); | 99 AddToWorklist(use_defn); |
99 } | 100 } |
100 | 101 |
101 // If the value flow into a branch recompute type constrained by the | 102 // If the value flow into a branch recompute type constrained by the |
102 // branch (if any). This ensures that correct non-nullable type will | 103 // branch (if any). This ensures that correct non-nullable type will |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 } | 212 } |
212 | 213 |
213 | 214 |
214 void FlowGraphTypePropagator::VisitValue(Value* value) { | 215 void FlowGraphTypePropagator::VisitValue(Value* value) { |
215 CompileType* type = TypeOf(value->definition()); | 216 CompileType* type = TypeOf(value->definition()); |
216 value->SetReachingType(type); | 217 value->SetReachingType(type); |
217 | 218 |
218 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { | 219 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { |
219 THR_Print("reaching type to %s for v%" Pd " is %s\n", | 220 THR_Print("reaching type to %s for v%" Pd " is %s\n", |
220 value->instruction()->ToCString(), | 221 value->instruction()->ToCString(), |
221 value->definition()->ssa_temp_index(), | 222 value->definition()->ssa_temp_index(), type->ToCString()); |
222 type->ToCString()); | |
223 } | 223 } |
224 } | 224 } |
225 | 225 |
226 | 226 |
227 void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join) { | 227 void FlowGraphTypePropagator::VisitJoinEntry(JoinEntryInstr* join) { |
228 for (PhiIterator it(join); !it.Done(); it.Advance()) { | 228 for (PhiIterator it(join); !it.Done(); it.Advance()) { |
229 worklist_.Add(it.Current()); | 229 worklist_.Add(it.Current()); |
230 } | 230 } |
231 } | 231 } |
232 | 232 |
(...skipping 24 matching lines...) Expand all Loading... |
257 | 257 |
258 | 258 |
259 void FlowGraphTypePropagator::VisitCheckClassId(CheckClassIdInstr* check) { | 259 void FlowGraphTypePropagator::VisitCheckClassId(CheckClassIdInstr* check) { |
260 // Can't propagate the type/cid because it may cause illegal code motion and | 260 // Can't propagate the type/cid because it may cause illegal code motion and |
261 // we don't track dependencies in all places via redefinitions. | 261 // we don't track dependencies in all places via redefinitions. |
262 } | 262 } |
263 | 263 |
264 | 264 |
265 void FlowGraphTypePropagator::VisitInstanceCall(InstanceCallInstr* instr) { | 265 void FlowGraphTypePropagator::VisitInstanceCall(InstanceCallInstr* instr) { |
266 if (instr->has_unique_selector()) { | 266 if (instr->has_unique_selector()) { |
267 SetCid(instr->ArgumentAt(0), | 267 SetCid(instr->ArgumentAt(0), instr->ic_data()->GetReceiverClassIdAt(0)); |
268 instr->ic_data()->GetReceiverClassIdAt(0)); | |
269 } | 268 } |
270 } | 269 } |
271 | 270 |
272 | 271 |
273 void FlowGraphTypePropagator::VisitPolymorphicInstanceCall( | 272 void FlowGraphTypePropagator::VisitPolymorphicInstanceCall( |
274 PolymorphicInstanceCallInstr* instr) { | 273 PolymorphicInstanceCallInstr* instr) { |
275 if (instr->instance_call()->has_unique_selector()) { | 274 if (instr->instance_call()->has_unique_selector()) { |
276 SetCid(instr->ArgumentAt(0), | 275 SetCid(instr->ArgumentAt(0), instr->ic_data().GetReceiverClassIdAt(0)); |
277 instr->ic_data().GetReceiverClassIdAt(0)); | |
278 } | 276 } |
279 } | 277 } |
280 | 278 |
281 | 279 |
282 void FlowGraphTypePropagator::VisitGuardFieldClass( | 280 void FlowGraphTypePropagator::VisitGuardFieldClass( |
283 GuardFieldClassInstr* guard) { | 281 GuardFieldClassInstr* guard) { |
284 const intptr_t cid = guard->field().guarded_cid(); | 282 const intptr_t cid = guard->field().guarded_cid(); |
285 if ((cid == kIllegalCid) || | 283 if ((cid == kIllegalCid) || (cid == kDynamicCid) || |
286 (cid == kDynamicCid) || | |
287 Field::IsExternalizableCid(cid)) { | 284 Field::IsExternalizableCid(cid)) { |
288 return; | 285 return; |
289 } | 286 } |
290 | 287 |
291 Definition* def = guard->value()->definition(); | 288 Definition* def = guard->value()->definition(); |
292 CompileType* current = TypeOf(def); | 289 CompileType* current = TypeOf(def); |
293 if (current->IsNone() || | 290 if (current->IsNone() || (current->ToCid() != cid) || |
294 (current->ToCid() != cid) || | |
295 (current->is_nullable() && !guard->field().is_nullable())) { | 291 (current->is_nullable() && !guard->field().is_nullable())) { |
296 const bool is_nullable = | 292 const bool is_nullable = |
297 guard->field().is_nullable() && current->is_nullable(); | 293 guard->field().is_nullable() && current->is_nullable(); |
298 SetTypeOf(def, ZoneCompileType::Wrap(CompileType(is_nullable, cid, NULL))); | 294 SetTypeOf(def, ZoneCompileType::Wrap(CompileType(is_nullable, cid, NULL))); |
299 } | 295 } |
300 } | 296 } |
301 | 297 |
302 | 298 |
303 void FlowGraphTypePropagator::VisitAssertAssignable( | 299 void FlowGraphTypePropagator::VisitAssertAssignable( |
304 AssertAssignableInstr* instr) { | 300 AssertAssignableInstr* instr) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 AssertAssignableInstr* assert = (*asserts_)[defn->ssa_temp_index()]; | 366 AssertAssignableInstr* assert = (*asserts_)[defn->ssa_temp_index()]; |
371 if ((assert == NULL) || (assert == kStrengthenedAssertMarker)) { | 367 if ((assert == NULL) || (assert == kStrengthenedAssertMarker)) { |
372 return; | 368 return; |
373 } | 369 } |
374 ASSERT(assert->env() != NULL); | 370 ASSERT(assert->env() != NULL); |
375 | 371 |
376 Instruction* check_clone = NULL; | 372 Instruction* check_clone = NULL; |
377 if (check->IsCheckSmi()) { | 373 if (check->IsCheckSmi()) { |
378 check_clone = | 374 check_clone = |
379 new CheckSmiInstr(assert->value()->Copy(zone()), | 375 new CheckSmiInstr(assert->value()->Copy(zone()), |
380 assert->env()->deopt_id(), | 376 assert->env()->deopt_id(), check->token_pos()); |
381 check->token_pos()); | |
382 check_clone->AsCheckSmi()->set_licm_hoisted( | 377 check_clone->AsCheckSmi()->set_licm_hoisted( |
383 check->AsCheckSmi()->licm_hoisted()); | 378 check->AsCheckSmi()->licm_hoisted()); |
384 } else { | 379 } else { |
385 ASSERT(check->IsCheckClass()); | 380 ASSERT(check->IsCheckClass()); |
386 check_clone = | 381 check_clone = new CheckClassInstr( |
387 new CheckClassInstr(assert->value()->Copy(zone()), | 382 assert->value()->Copy(zone()), assert->env()->deopt_id(), |
388 assert->env()->deopt_id(), | 383 check->AsCheckClass()->unary_checks(), check->token_pos()); |
389 check->AsCheckClass()->unary_checks(), | |
390 check->token_pos()); | |
391 check_clone->AsCheckClass()->set_licm_hoisted( | 384 check_clone->AsCheckClass()->set_licm_hoisted( |
392 check->AsCheckClass()->licm_hoisted()); | 385 check->AsCheckClass()->licm_hoisted()); |
393 } | 386 } |
394 ASSERT(check_clone != NULL); | 387 ASSERT(check_clone != NULL); |
395 ASSERT(assert->deopt_id() == assert->env()->deopt_id()); | 388 ASSERT(assert->deopt_id() == assert->env()->deopt_id()); |
396 check_clone->InsertBefore(assert); | 389 check_clone->InsertBefore(assert); |
397 assert->env()->DeepCopyTo(zone(), check_clone); | 390 assert->env()->DeepCopyTo(zone(), check_clone); |
398 | 391 |
399 (*asserts_)[defn->ssa_temp_index()] = kStrengthenedAssertMarker; | 392 (*asserts_)[defn->ssa_temp_index()] = kStrengthenedAssertMarker; |
400 } | 393 } |
(...skipping 21 matching lines...) Expand all Loading... |
422 return; | 415 return; |
423 } | 416 } |
424 | 417 |
425 if (ToNullableCid() != other->ToNullableCid()) { | 418 if (ToNullableCid() != other->ToNullableCid()) { |
426 ASSERT(cid_ != kNullCid); | 419 ASSERT(cid_ != kNullCid); |
427 cid_ = kDynamicCid; | 420 cid_ = kDynamicCid; |
428 } | 421 } |
429 | 422 |
430 const AbstractType* compile_type = ToAbstractType(); | 423 const AbstractType* compile_type = ToAbstractType(); |
431 const AbstractType* other_compile_type = other->ToAbstractType(); | 424 const AbstractType* other_compile_type = other->ToAbstractType(); |
432 if (compile_type->IsMoreSpecificThan( | 425 if (compile_type->IsMoreSpecificThan(*other_compile_type, NULL, NULL, |
433 *other_compile_type, NULL, NULL, Heap::kOld)) { | 426 Heap::kOld)) { |
434 type_ = other_compile_type; | 427 type_ = other_compile_type; |
435 } else if (other_compile_type-> | 428 } else if (other_compile_type->IsMoreSpecificThan(*compile_type, NULL, NULL, |
436 IsMoreSpecificThan(*compile_type, NULL, NULL, Heap::kOld)) { | 429 Heap::kOld)) { |
437 // Nothing to do. | 430 // Nothing to do. |
438 } else { | 431 } else { |
439 // Can't unify. | 432 // Can't unify. |
440 type_ = &Object::dynamic_type(); | 433 type_ = &Object::dynamic_type(); |
441 } | 434 } |
442 } | 435 } |
443 | 436 |
444 | 437 |
445 static bool IsNullableCid(intptr_t cid) { | 438 static bool IsNullableCid(intptr_t cid) { |
446 ASSERT(cid != kIllegalCid); | 439 ASSERT(cid != kIllegalCid); |
447 return cid == kNullCid || cid == kDynamicCid; | 440 return cid == kNullCid || cid == kDynamicCid; |
448 } | 441 } |
449 | 442 |
450 | 443 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 // Don't infer a cid from an abstract type since there can be multiple | 514 // Don't infer a cid from an abstract type since there can be multiple |
522 // compatible classes with different cids. | 515 // compatible classes with different cids. |
523 if (!CHA::IsImplemented(type_class) && !CHA::HasSubclasses(type_class)) { | 516 if (!CHA::IsImplemented(type_class) && !CHA::HasSubclasses(type_class)) { |
524 if (type_class.IsPrivate()) { | 517 if (type_class.IsPrivate()) { |
525 // Type of a private class cannot change through later loaded libs. | 518 // Type of a private class cannot change through later loaded libs. |
526 cid_ = type_class.id(); | 519 cid_ = type_class.id(); |
527 } else if (FLAG_use_cha_deopt || | 520 } else if (FLAG_use_cha_deopt || |
528 thread->isolate()->all_classes_finalized()) { | 521 thread->isolate()->all_classes_finalized()) { |
529 if (FLAG_trace_cha) { | 522 if (FLAG_trace_cha) { |
530 THR_Print(" **(CHA) Compile type not subclassed: %s\n", | 523 THR_Print(" **(CHA) Compile type not subclassed: %s\n", |
531 type_class.ToCString()); | 524 type_class.ToCString()); |
532 } | 525 } |
533 if (FLAG_use_cha_deopt) { | 526 if (FLAG_use_cha_deopt) { |
534 cha->AddToGuardedClasses(type_class, /*subclass_count=*/0); | 527 cha->AddToGuardedClasses(type_class, /*subclass_count=*/0); |
535 } | 528 } |
536 cid_ = type_class.id(); | 529 cid_ = type_class.id(); |
537 } else { | 530 } else { |
538 cid_ = kDynamicCid; | 531 cid_ = kDynamicCid; |
539 } | 532 } |
540 } else { | 533 } else { |
541 cid_ = kDynamicCid; | 534 cid_ = kDynamicCid; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 | 610 |
618 if (compile_type.IsMalformedOrMalbounded()) { | 611 if (compile_type.IsMalformedOrMalbounded()) { |
619 return false; | 612 return false; |
620 } | 613 } |
621 | 614 |
622 // The Null type is only a subtype of Object and of dynamic. | 615 // The Null type is only a subtype of Object and of dynamic. |
623 // Functions that do not explicitly return a value, implicitly return null, | 616 // Functions that do not explicitly return a value, implicitly return null, |
624 // except generative constructors, which return the object being constructed. | 617 // except generative constructors, which return the object being constructed. |
625 // It is therefore acceptable for void functions to return null. | 618 // It is therefore acceptable for void functions to return null. |
626 if (compile_type.IsNullType()) { | 619 if (compile_type.IsNullType()) { |
627 *is_instance = is_nullable || | 620 *is_instance = is_nullable || type.IsObjectType() || type.IsDynamicType() || |
628 type.IsObjectType() || type.IsDynamicType() || type.IsVoidType(); | 621 type.IsVoidType(); |
629 return true; | 622 return true; |
630 } | 623 } |
631 | 624 |
632 // A non-null value is not an instance of void. | 625 // A non-null value is not an instance of void. |
633 if (type.IsVoidType()) { | 626 if (type.IsVoidType()) { |
634 *is_instance = IsNull(); | 627 *is_instance = IsNull(); |
635 return HasDecidableNullability(); | 628 return HasDecidableNullability(); |
636 } | 629 } |
637 | 630 |
638 // If the value can be null then we can't eliminate the | 631 // If the value can be null then we can't eliminate the |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 // for the first time. | 666 // for the first time. |
674 return CompileType::None(); | 667 return CompileType::None(); |
675 } | 668 } |
676 | 669 |
677 | 670 |
678 bool PhiInstr::RecomputeType() { | 671 bool PhiInstr::RecomputeType() { |
679 CompileType result = CompileType::None(); | 672 CompileType result = CompileType::None(); |
680 for (intptr_t i = 0; i < InputCount(); i++) { | 673 for (intptr_t i = 0; i < InputCount(); i++) { |
681 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { | 674 if (FLAG_support_il_printer && FLAG_trace_type_propagation) { |
682 THR_Print(" phi %" Pd " input %" Pd ": v%" Pd " has reaching type %s\n", | 675 THR_Print(" phi %" Pd " input %" Pd ": v%" Pd " has reaching type %s\n", |
683 ssa_temp_index(), | 676 ssa_temp_index(), i, InputAt(i)->definition()->ssa_temp_index(), |
684 i, | |
685 InputAt(i)->definition()->ssa_temp_index(), | |
686 InputAt(i)->Type()->ToCString()); | 677 InputAt(i)->Type()->ToCString()); |
687 } | 678 } |
688 result.Union(InputAt(i)->Type()); | 679 result.Union(InputAt(i)->Type()); |
689 } | 680 } |
690 | 681 |
691 if (result.IsNone()) { | 682 if (result.IsNone()) { |
692 ASSERT(Type()->IsNone()); | 683 ASSERT(Type()->IsNone()); |
693 return false; | 684 return false; |
694 } | 685 } |
695 | 686 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 // In irregexp functions, types of input parameters are known and immutable. | 728 // In irregexp functions, types of input parameters are known and immutable. |
738 // Set parameter types here in order to prevent unnecessary CheckClassInstr | 729 // Set parameter types here in order to prevent unnecessary CheckClassInstr |
739 // from being generated. | 730 // from being generated. |
740 switch (index()) { | 731 switch (index()) { |
741 case RegExpMacroAssembler::kParamRegExpIndex: | 732 case RegExpMacroAssembler::kParamRegExpIndex: |
742 return CompileType::FromCid(kRegExpCid); | 733 return CompileType::FromCid(kRegExpCid); |
743 case RegExpMacroAssembler::kParamStringIndex: | 734 case RegExpMacroAssembler::kParamStringIndex: |
744 return CompileType::FromCid(function.string_specialization_cid()); | 735 return CompileType::FromCid(function.string_specialization_cid()); |
745 case RegExpMacroAssembler::kParamStartOffsetIndex: | 736 case RegExpMacroAssembler::kParamStartOffsetIndex: |
746 return CompileType::FromCid(kSmiCid); | 737 return CompileType::FromCid(kSmiCid); |
747 default: UNREACHABLE(); | 738 default: |
| 739 UNREACHABLE(); |
748 } | 740 } |
749 UNREACHABLE(); | 741 UNREACHABLE(); |
750 return CompileType::Dynamic(); | 742 return CompileType::Dynamic(); |
751 } | 743 } |
752 | 744 |
753 // Parameter is the receiver. | 745 // Parameter is the receiver. |
754 if ((index() == 0) && | 746 if ((index() == 0) && |
755 (function.IsDynamicFunction() || function.IsGenerativeConstructor())) { | 747 (function.IsDynamicFunction() || function.IsGenerativeConstructor())) { |
756 LocalScope* scope = graph_entry->parsed_function().node_sequence()->scope(); | 748 LocalScope* scope = graph_entry->parsed_function().node_sequence()->scope(); |
757 const AbstractType& type = scope->VariableAt(index())->type(); | 749 const AbstractType& type = scope->VariableAt(index())->type(); |
758 if (type.IsObjectType() || type.IsNullType()) { | 750 if (type.IsObjectType() || type.IsNullType()) { |
759 // Receiver can be null. | 751 // Receiver can be null. |
760 return CompileType::FromAbstractType(type, CompileType::kNullable); | 752 return CompileType::FromAbstractType(type, CompileType::kNullable); |
761 } | 753 } |
762 | 754 |
763 // Receiver can't be null but can be an instance of a subclass. | 755 // Receiver can't be null but can be an instance of a subclass. |
764 intptr_t cid = kDynamicCid; | 756 intptr_t cid = kDynamicCid; |
765 | 757 |
766 if (type.HasResolvedTypeClass()) { | 758 if (type.HasResolvedTypeClass()) { |
767 Thread* thread = Thread::Current(); | 759 Thread* thread = Thread::Current(); |
768 const Class& type_class = Class::Handle(type.type_class()); | 760 const Class& type_class = Class::Handle(type.type_class()); |
769 if (!CHA::HasSubclasses(type_class)) { | 761 if (!CHA::HasSubclasses(type_class)) { |
770 if (type_class.IsPrivate()) { | 762 if (type_class.IsPrivate()) { |
771 // Private classes can never be subclassed by later loaded libs. | 763 // Private classes can never be subclassed by later loaded libs. |
772 cid = type_class.id(); | 764 cid = type_class.id(); |
773 } else { | 765 } else { |
774 if (FLAG_use_cha_deopt || | 766 if (FLAG_use_cha_deopt || |
775 thread->isolate()->all_classes_finalized()) { | 767 thread->isolate()->all_classes_finalized()) { |
776 if (FLAG_trace_cha) { | 768 if (FLAG_trace_cha) { |
777 THR_Print(" **(CHA) Computing exact type of receiver, " | 769 THR_Print( |
| 770 " **(CHA) Computing exact type of receiver, " |
778 "no subclasses: %s\n", | 771 "no subclasses: %s\n", |
779 type_class.ToCString()); | 772 type_class.ToCString()); |
780 } | 773 } |
781 if (FLAG_use_cha_deopt) { | 774 if (FLAG_use_cha_deopt) { |
782 thread->cha()->AddToGuardedClasses( | 775 thread->cha()->AddToGuardedClasses(type_class, |
783 type_class, /*subclass_count=*/0); | 776 /*subclass_count=*/0); |
784 } | 777 } |
785 cid = type_class.id(); | 778 cid = type_class.id(); |
786 } | 779 } |
787 } | 780 } |
788 } | 781 } |
789 } | 782 } |
790 | 783 |
791 return CompileType(CompileType::kNonNullable, cid, &type); | 784 return CompileType(CompileType::kNonNullable, cid, &type); |
792 } | 785 } |
793 | 786 |
(...skipping 10 matching lines...) Expand all Loading... |
804 if (value().IsNull()) { | 797 if (value().IsNull()) { |
805 return CompileType::Null(); | 798 return CompileType::Null(); |
806 } | 799 } |
807 | 800 |
808 intptr_t cid = value().GetClassId(); | 801 intptr_t cid = value().GetClassId(); |
809 if (Field::IsExternalizableCid(cid)) { | 802 if (Field::IsExternalizableCid(cid)) { |
810 cid = kDynamicCid; | 803 cid = kDynamicCid; |
811 } | 804 } |
812 | 805 |
813 if (value().IsInstance()) { | 806 if (value().IsInstance()) { |
814 return CompileType::Create(cid, | 807 return CompileType::Create( |
815 AbstractType::ZoneHandle(Instance::Cast(value()).GetType())); | 808 cid, AbstractType::ZoneHandle(Instance::Cast(value()).GetType())); |
816 } else { | 809 } else { |
817 // Type info for non-instance objects. | 810 // Type info for non-instance objects. |
818 return CompileType::FromCid(cid); | 811 return CompileType::FromCid(cid); |
819 } | 812 } |
820 } | 813 } |
821 | 814 |
822 | 815 |
823 CompileType AssertAssignableInstr::ComputeType() const { | 816 CompileType AssertAssignableInstr::ComputeType() const { |
824 CompileType* value_type = value()->Type(); | 817 CompileType* value_type = value()->Type(); |
825 | 818 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 } | 870 } |
878 | 871 |
879 | 872 |
880 CompileType RelationalOpInstr::ComputeType() const { | 873 CompileType RelationalOpInstr::ComputeType() const { |
881 // Used for numeric comparisons only. | 874 // Used for numeric comparisons only. |
882 return CompileType::Bool(); | 875 return CompileType::Bool(); |
883 } | 876 } |
884 | 877 |
885 | 878 |
886 CompileType CurrentContextInstr::ComputeType() const { | 879 CompileType CurrentContextInstr::ComputeType() const { |
887 return CompileType(CompileType::kNonNullable, | 880 return CompileType(CompileType::kNonNullable, kContextCid, |
888 kContextCid, | |
889 &Object::dynamic_type()); | 881 &Object::dynamic_type()); |
890 } | 882 } |
891 | 883 |
892 | 884 |
893 CompileType CloneContextInstr::ComputeType() const { | 885 CompileType CloneContextInstr::ComputeType() const { |
894 return CompileType(CompileType::kNonNullable, | 886 return CompileType(CompileType::kNonNullable, kContextCid, |
895 kContextCid, | |
896 &Object::dynamic_type()); | 887 &Object::dynamic_type()); |
897 } | 888 } |
898 | 889 |
899 | 890 |
900 CompileType AllocateContextInstr::ComputeType() const { | 891 CompileType AllocateContextInstr::ComputeType() const { |
901 return CompileType(CompileType::kNonNullable, | 892 return CompileType(CompileType::kNonNullable, kContextCid, |
902 kContextCid, | |
903 &Object::dynamic_type()); | 893 &Object::dynamic_type()); |
904 } | 894 } |
905 | 895 |
906 | 896 |
907 CompileType AllocateUninitializedContextInstr::ComputeType() const { | 897 CompileType AllocateUninitializedContextInstr::ComputeType() const { |
908 return CompileType(CompileType::kNonNullable, | 898 return CompileType(CompileType::kNonNullable, kContextCid, |
909 kContextCid, | |
910 &Object::dynamic_type()); | 899 &Object::dynamic_type()); |
911 } | 900 } |
912 | 901 |
913 | 902 |
914 CompileType PolymorphicInstanceCallInstr::ComputeType() const { | 903 CompileType PolymorphicInstanceCallInstr::ComputeType() const { |
915 if (!HasSingleRecognizedTarget()) return CompileType::Dynamic(); | 904 if (!HasSingleRecognizedTarget()) return CompileType::Dynamic(); |
916 const Function& target = Function::Handle(ic_data().GetTargetAt(0)); | 905 const Function& target = Function::Handle(ic_data().GetTargetAt(0)); |
917 return (target.recognized_kind() != MethodRecognizer::kUnknown) | 906 return (target.recognized_kind() != MethodRecognizer::kUnknown) |
918 ? CompileType::FromCid(MethodRecognizer::ResultCid(target)) | 907 ? CompileType::FromCid(MethodRecognizer::ResultCid(target)) |
919 : CompileType::Dynamic(); | 908 : CompileType::Dynamic(); |
920 } | 909 } |
921 | 910 |
922 | 911 |
923 CompileType StaticCallInstr::ComputeType() const { | 912 CompileType StaticCallInstr::ComputeType() const { |
924 if (result_cid_ != kDynamicCid) { | 913 if (result_cid_ != kDynamicCid) { |
925 return CompileType::FromCid(result_cid_); | 914 return CompileType::FromCid(result_cid_); |
926 } | 915 } |
927 | 916 |
928 if (Isolate::Current()->type_checks()) { | 917 if (Isolate::Current()->type_checks()) { |
929 // Void functions are known to return null, which is checked at the return | 918 // Void functions are known to return null, which is checked at the return |
930 // from the function. | 919 // from the function. |
931 const AbstractType& result_type = | 920 const AbstractType& result_type = |
932 AbstractType::ZoneHandle(function().result_type()); | 921 AbstractType::ZoneHandle(function().result_type()); |
933 return CompileType::FromAbstractType(result_type.IsVoidType() | 922 return CompileType::FromAbstractType( |
934 ? AbstractType::ZoneHandle(Type::NullType()) | 923 result_type.IsVoidType() ? AbstractType::ZoneHandle(Type::NullType()) |
935 : result_type); | 924 : result_type); |
936 } | 925 } |
937 | 926 |
938 return CompileType::Dynamic(); | 927 return CompileType::Dynamic(); |
939 } | 928 } |
940 | 929 |
941 | 930 |
942 CompileType LoadLocalInstr::ComputeType() const { | 931 CompileType LoadLocalInstr::ComputeType() const { |
943 if (Isolate::Current()->type_checks()) { | 932 if (Isolate::Current()->type_checks()) { |
944 return CompileType::FromAbstractType(local().type()); | 933 return CompileType::FromAbstractType(local().type()); |
945 } | 934 } |
(...skipping 11 matching lines...) Expand all Loading... |
957 return *value()->Type(); | 946 return *value()->Type(); |
958 } | 947 } |
959 | 948 |
960 | 949 |
961 CompileType OneByteStringFromCharCodeInstr::ComputeType() const { | 950 CompileType OneByteStringFromCharCodeInstr::ComputeType() const { |
962 return CompileType::FromCid(kOneByteStringCid); | 951 return CompileType::FromCid(kOneByteStringCid); |
963 } | 952 } |
964 | 953 |
965 | 954 |
966 CompileType StringToCharCodeInstr::ComputeType() const { | 955 CompileType StringToCharCodeInstr::ComputeType() const { |
967 return CompileType::FromCid(kSmiCid); | 956 return CompileType::FromCid(kSmiCid); |
968 } | 957 } |
969 | 958 |
970 | 959 |
971 CompileType StringInterpolateInstr::ComputeType() const { | 960 CompileType StringInterpolateInstr::ComputeType() const { |
972 // TODO(srdjan): Do better and determine if it is a one or two byte string. | 961 // TODO(srdjan): Do better and determine if it is a one or two byte string. |
973 return CompileType::String(); | 962 return CompileType::String(); |
974 } | 963 } |
975 | 964 |
976 | 965 |
977 CompileType LoadStaticFieldInstr::ComputeType() const { | 966 CompileType LoadStaticFieldInstr::ComputeType() const { |
978 bool is_nullable = CompileType::kNullable; | 967 bool is_nullable = CompileType::kNullable; |
979 intptr_t cid = kDynamicCid; | 968 intptr_t cid = kDynamicCid; |
980 AbstractType* abstract_type = NULL; | 969 AbstractType* abstract_type = NULL; |
981 const Field& field = this->StaticField(); | 970 const Field& field = this->StaticField(); |
982 if (Isolate::Current()->type_checks()) { | 971 if (Isolate::Current()->type_checks()) { |
983 cid = kIllegalCid; | 972 cid = kIllegalCid; |
984 abstract_type = &AbstractType::ZoneHandle(field.type()); | 973 abstract_type = &AbstractType::ZoneHandle(field.type()); |
985 } | 974 } |
986 ASSERT(field.is_static()); | 975 ASSERT(field.is_static()); |
987 if (field.is_final()) { | 976 if (field.is_final()) { |
988 if (!FLAG_fields_may_be_reset) { | 977 if (!FLAG_fields_may_be_reset) { |
989 const Instance& obj = Instance::Handle(field.StaticValue()); | 978 const Instance& obj = Instance::Handle(field.StaticValue()); |
990 if ((obj.raw() != Object::sentinel().raw()) && | 979 if ((obj.raw() != Object::sentinel().raw()) && |
991 (obj.raw() != Object::transition_sentinel().raw()) && | 980 (obj.raw() != Object::transition_sentinel().raw()) && !obj.IsNull()) { |
992 !obj.IsNull()) { | |
993 is_nullable = CompileType::kNonNullable; | 981 is_nullable = CompileType::kNonNullable; |
994 cid = obj.GetClassId(); | 982 cid = obj.GetClassId(); |
995 } | 983 } |
996 } else if (field.guarded_cid() != kIllegalCid) { | 984 } else if (field.guarded_cid() != kIllegalCid) { |
997 cid = field.guarded_cid(); | 985 cid = field.guarded_cid(); |
998 if (!IsNullableCid(cid)) is_nullable = CompileType::kNonNullable; | 986 if (!IsNullableCid(cid)) is_nullable = CompileType::kNonNullable; |
999 } | 987 } |
1000 } | 988 } |
1001 if (Field::IsExternalizableCid(cid)) { | 989 if (Field::IsExternalizableCid(cid)) { |
1002 cid = kDynamicCid; | 990 cid = kDynamicCid; |
1003 } | 991 } |
1004 return CompileType(is_nullable, cid, abstract_type); | 992 return CompileType(is_nullable, cid, abstract_type); |
1005 } | 993 } |
1006 | 994 |
1007 | 995 |
1008 CompileType CreateArrayInstr::ComputeType() const { | 996 CompileType CreateArrayInstr::ComputeType() const { |
1009 // TODO(fschneider): Add abstract type and type arguments to the compile type. | 997 // TODO(fschneider): Add abstract type and type arguments to the compile type. |
1010 return CompileType::FromCid(kArrayCid); | 998 return CompileType::FromCid(kArrayCid); |
1011 } | 999 } |
1012 | 1000 |
1013 | 1001 |
1014 CompileType AllocateObjectInstr::ComputeType() const { | 1002 CompileType AllocateObjectInstr::ComputeType() const { |
1015 if (!closure_function().IsNull()) { | 1003 if (!closure_function().IsNull()) { |
1016 ASSERT(cls().id() == kClosureCid); | 1004 ASSERT(cls().id() == kClosureCid); |
1017 return CompileType(CompileType::kNonNullable, | 1005 return CompileType(CompileType::kNonNullable, kClosureCid, |
1018 kClosureCid, | |
1019 &Type::ZoneHandle(closure_function().SignatureType())); | 1006 &Type::ZoneHandle(closure_function().SignatureType())); |
1020 } | 1007 } |
1021 // TODO(vegorov): Incorporate type arguments into the returned type. | 1008 // TODO(vegorov): Incorporate type arguments into the returned type. |
1022 return CompileType::FromCid(cls().id()); | 1009 return CompileType::FromCid(cls().id()); |
1023 } | 1010 } |
1024 | 1011 |
1025 | 1012 |
1026 CompileType LoadUntaggedInstr::ComputeType() const { | 1013 CompileType LoadUntaggedInstr::ComputeType() const { |
1027 return CompileType::Dynamic(); | 1014 return CompileType::Dynamic(); |
1028 } | 1015 } |
1029 | 1016 |
1030 | 1017 |
1031 CompileType LoadClassIdInstr::ComputeType() const { | 1018 CompileType LoadClassIdInstr::ComputeType() const { |
1032 return CompileType::FromCid(kSmiCid); | 1019 return CompileType::FromCid(kSmiCid); |
1033 } | 1020 } |
1034 | 1021 |
1035 | 1022 |
1036 CompileType LoadFieldInstr::ComputeType() const { | 1023 CompileType LoadFieldInstr::ComputeType() const { |
1037 // Type may be null if the field is a VM field, e.g. context parent. | 1024 // Type may be null if the field is a VM field, e.g. context parent. |
1038 // Keep it as null for debug purposes and do not return dynamic in production | 1025 // Keep it as null for debug purposes and do not return dynamic in production |
1039 // mode, since misuse of the type would remain undetected. | 1026 // mode, since misuse of the type would remain undetected. |
1040 if (type().IsNull()) { | 1027 if (type().IsNull()) { |
1041 return CompileType::Dynamic(); | 1028 return CompileType::Dynamic(); |
1042 } | 1029 } |
1043 | 1030 |
1044 const AbstractType* abstract_type = NULL; | 1031 const AbstractType* abstract_type = NULL; |
1045 if (Isolate::Current()->type_checks() && | 1032 if (Isolate::Current()->type_checks() && |
1046 (type().IsFunctionType() || | 1033 (type().IsFunctionType() || |
1047 (type().HasResolvedTypeClass() && | 1034 (type().HasResolvedTypeClass() && |
1048 !Field::IsExternalizableCid(Class::Handle(type().type_class()).id())))) { | 1035 !Field::IsExternalizableCid( |
| 1036 Class::Handle(type().type_class()).id())))) { |
1049 abstract_type = &type(); | 1037 abstract_type = &type(); |
1050 } | 1038 } |
1051 | 1039 |
1052 if ((field_ != NULL) && (field_->guarded_cid() != kIllegalCid)) { | 1040 if ((field_ != NULL) && (field_->guarded_cid() != kIllegalCid)) { |
1053 bool is_nullable = field_->is_nullable(); | 1041 bool is_nullable = field_->is_nullable(); |
1054 intptr_t field_cid = field_->guarded_cid(); | 1042 intptr_t field_cid = field_->guarded_cid(); |
1055 if (Field::IsExternalizableCid(field_cid)) { | 1043 if (Field::IsExternalizableCid(field_cid)) { |
1056 // We cannot assume that the type of the value in the field has not | 1044 // We cannot assume that the type of the value in the field has not |
1057 // changed on the fly. | 1045 // changed on the fly. |
1058 field_cid = kDynamicCid; | 1046 field_cid = kDynamicCid; |
1059 } | 1047 } |
1060 return CompileType(is_nullable, field_cid, abstract_type); | 1048 return CompileType(is_nullable, field_cid, abstract_type); |
1061 } | 1049 } |
1062 | 1050 |
1063 ASSERT(!Field::IsExternalizableCid(result_cid_)); | 1051 ASSERT(!Field::IsExternalizableCid(result_cid_)); |
1064 return CompileType::Create(result_cid_, *abstract_type); | 1052 return CompileType::Create(result_cid_, *abstract_type); |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1433 CompileType MergedMathInstr::ComputeType() const { | 1421 CompileType MergedMathInstr::ComputeType() const { |
1434 return CompileType::Dynamic(); | 1422 return CompileType::Dynamic(); |
1435 } | 1423 } |
1436 | 1424 |
1437 | 1425 |
1438 CompileType ExtractNthOutputInstr::ComputeType() const { | 1426 CompileType ExtractNthOutputInstr::ComputeType() const { |
1439 return CompileType::FromCid(definition_cid_); | 1427 return CompileType::FromCid(definition_cid_); |
1440 } | 1428 } |
1441 | 1429 |
1442 } // namespace dart | 1430 } // namespace dart |
OLD | NEW |