Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1214)

Side by Side Diff: runtime/vm/flow_graph_type_propagator.cc

Issue 2481873005: clang-format runtime/vm (Closed)
Patch Set: Merge Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/flow_graph_type_propagator.h ('k') | runtime/vm/freelist.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_type_propagator.h ('k') | runtime/vm/freelist.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698