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/object_store.h" | 10 #include "vm/object_store.h" |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 if (load_cid != NULL && comparison->InputAt(1)->BindsToConstant()) { | 343 if (load_cid != NULL && comparison->InputAt(1)->BindsToConstant()) { |
344 intptr_t cid = Smi::Cast(comparison->InputAt(1)->BoundConstant()).Value(); | 344 intptr_t cid = Smi::Cast(comparison->InputAt(1)->BoundConstant()).Value(); |
345 BlockEntryInstr* true_successor = | 345 BlockEntryInstr* true_successor = |
346 negated ? instr->false_successor() : instr->true_successor(); | 346 negated ? instr->false_successor() : instr->true_successor(); |
347 redef = flow_graph_->EnsureRedefinition(true_successor, | 347 redef = flow_graph_->EnsureRedefinition(true_successor, |
348 load_cid->object()->definition(), | 348 load_cid->object()->definition(), |
349 CompileType::FromCid(cid)); | 349 CompileType::FromCid(cid)); |
350 } else if ((call != NULL) && | 350 } else if ((call != NULL) && |
351 call->MatchesCoreName(Symbols::_simpleInstanceOf()) && | 351 call->MatchesCoreName(Symbols::_simpleInstanceOf()) && |
352 comparison->InputAt(1)->BindsToConstant() && | 352 comparison->InputAt(1)->BindsToConstant() && |
353 comparison->InputAt(1)->BoundConstant().IsBool()) { | 353 (comparison->InputAt(1)->BoundConstant().IsBool())) { |
354 ASSERT(call->ArgumentAt(1)->IsConstant()); | 354 ASSERT(call->ArgumentAt(1)->IsConstant()); |
355 if (comparison->InputAt(1)->BoundConstant().raw() == Bool::False().raw()) { | 355 if (comparison->InputAt(1)->BoundConstant().raw() == Bool::False().raw()) { |
356 negated = !negated; | 356 negated = !negated; |
357 } | 357 } |
358 BlockEntryInstr* true_successor = | 358 BlockEntryInstr* true_successor = |
359 negated ? instr->false_successor() : instr->true_successor(); | 359 negated ? instr->false_successor() : instr->true_successor(); |
360 const Object& type = call->ArgumentAt(1)->AsConstant()->value(); | 360 const Object& type = call->ArgumentAt(1)->AsConstant()->value(); |
361 if (type.IsType() && !Type::Cast(type).IsDynamicType() && | 361 if (type.IsType() && !Type::Cast(type).IsDynamicType() && |
362 !Type::Cast(type).IsObjectType()) { | 362 !Type::Cast(type).IsObjectType()) { |
363 const bool is_nullable = Type::Cast(type).IsNullType() | 363 const bool is_nullable = Type::Cast(type).IsNullType() |
364 ? CompileType::kNullable | 364 ? CompileType::kNullable |
365 : CompileType::kNonNullable; | 365 : CompileType::kNonNullable; |
366 redef = flow_graph_->EnsureRedefinition( | 366 redef = flow_graph_->EnsureRedefinition( |
367 true_successor, call->ArgumentAt(0), | 367 true_successor, call->ArgumentAt(0), |
368 CompileType::FromAbstractType(Type::Cast(type), is_nullable)); | 368 CompileType::FromAbstractType(Type::Cast(type), is_nullable)); |
369 } | 369 } |
370 } else if (comparison->InputAt(0)->BindsToConstant() && | |
371 comparison->InputAt(0)->BoundConstant().IsNull()) { | |
372 // Handle for expr != null. | |
373 BlockEntryInstr* true_successor = | |
374 negated ? instr->true_successor() : instr->false_successor(); | |
375 redef = flow_graph_->EnsureRedefinition( | |
376 true_successor, comparison->InputAt(1)->definition(), | |
377 comparison->InputAt(1)->Type()->CopyNonNullable()); | |
378 | |
379 } else if (comparison->InputAt(1)->BindsToConstant() && | |
380 comparison->InputAt(1)->BoundConstant().IsNull()) { | |
381 // Handle for null != expr. | |
382 BlockEntryInstr* true_successor = | |
383 negated ? instr->true_successor() : instr->false_successor(); | |
384 redef = flow_graph_->EnsureRedefinition( | |
385 true_successor, comparison->InputAt(0)->definition(), | |
386 comparison->InputAt(0)->Type()->CopyNonNullable()); | |
387 } | 370 } |
| 371 // TODO(fschneider): Add propagation for null-comparisons. |
388 // TODO(fschneider): Add propagation for generic is-tests. | 372 // TODO(fschneider): Add propagation for generic is-tests. |
389 | 373 |
390 // Grow types array if a new redefinition was inserted. | 374 // Grow types array if a new redefinition was inserted. |
391 if (redef != NULL) { | 375 if (redef != NULL) { |
392 for (intptr_t i = types_.length(); i <= redef->ssa_temp_index() + 1; ++i) { | 376 for (intptr_t i = types_.length(); i <= redef->ssa_temp_index() + 1; ++i) { |
393 types_.Add(NULL); | 377 types_.Add(NULL); |
394 } | 378 } |
395 } | 379 } |
396 } | 380 } |
397 | 381 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 return Create(kNullCid, Type::ZoneHandle(Type::NullType())); | 543 return Create(kNullCid, Type::ZoneHandle(Type::NullType())); |
560 } | 544 } |
561 | 545 |
562 | 546 |
563 CompileType CompileType::Bool() { | 547 CompileType CompileType::Bool() { |
564 return Create(kBoolCid, Type::ZoneHandle(Type::BoolType())); | 548 return Create(kBoolCid, Type::ZoneHandle(Type::BoolType())); |
565 } | 549 } |
566 | 550 |
567 | 551 |
568 CompileType CompileType::Int() { | 552 CompileType CompileType::Int() { |
569 return FromAbstractType(Type::ZoneHandle(Type::Int64Type()), kNonNullable); | 553 return FromAbstractType(Type::ZoneHandle(Type::IntType()), kNonNullable); |
570 } | 554 } |
571 | 555 |
572 | 556 |
573 CompileType CompileType::Smi() { | 557 CompileType CompileType::Smi() { |
574 return Create(kSmiCid, Type::ZoneHandle(Type::SmiType())); | 558 return Create(kSmiCid, Type::ZoneHandle(Type::SmiType())); |
575 } | 559 } |
576 | 560 |
577 | 561 |
578 CompileType CompileType::String() { | 562 CompileType CompileType::String() { |
579 return FromAbstractType(Type::ZoneHandle(Type::StringType()), kNonNullable); | 563 return FromAbstractType(Type::ZoneHandle(Type::StringType()), kNonNullable); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
780 return UpdateType(result); | 764 return UpdateType(result); |
781 } | 765 } |
782 | 766 |
783 | 767 |
784 CompileType RedefinitionInstr::ComputeType() const { | 768 CompileType RedefinitionInstr::ComputeType() const { |
785 if (constrained_type_ != NULL) { | 769 if (constrained_type_ != NULL) { |
786 // Check if the type associated with this redefinition is more specific | 770 // Check if the type associated with this redefinition is more specific |
787 // than the type of its input. If yes, return it. Otherwise, fall back | 771 // than the type of its input. If yes, return it. Otherwise, fall back |
788 // to the input's type. | 772 // to the input's type. |
789 | 773 |
| 774 // If either type has a concrete cid, stick with it. |
| 775 if (value()->Type()->ToCid() != kDynamicCid) { |
| 776 return *value()->Type(); |
| 777 } |
| 778 if (constrained_type_->ToCid() != kDynamicCid) { |
| 779 return *constrained_type_; |
| 780 } |
790 // If either type is non-nullable, the resulting type is non-nullable. | 781 // If either type is non-nullable, the resulting type is non-nullable. |
791 const bool is_nullable = | 782 const bool is_nullable = |
792 value()->Type()->is_nullable() && constrained_type_->is_nullable(); | 783 value()->Type()->is_nullable() && constrained_type_->is_nullable(); |
793 | |
794 // If either type has a concrete cid, stick with it. | |
795 if (value()->Type()->ToNullableCid() != kDynamicCid) { | |
796 return CompileType::CreateNullable(is_nullable, value()->Type()->ToCid()); | |
797 } | |
798 if (constrained_type_->ToNullableCid() != kDynamicCid) { | |
799 return CompileType::CreateNullable(is_nullable, | |
800 constrained_type_->ToCid()); | |
801 } | |
802 if (value()->Type()->IsMoreSpecificThan( | 784 if (value()->Type()->IsMoreSpecificThan( |
803 *constrained_type_->ToAbstractType())) { | 785 *constrained_type_->ToAbstractType())) { |
804 return is_nullable ? *value()->Type() | 786 return is_nullable ? *value()->Type() |
805 : value()->Type()->CopyNonNullable(); | 787 : value()->Type()->CopyNonNullable(); |
806 } else { | 788 } else { |
807 return is_nullable ? *constrained_type_ | 789 return is_nullable ? *constrained_type_ |
808 : constrained_type_->CopyNonNullable(); | 790 : constrained_type_->CopyNonNullable(); |
809 } | 791 } |
810 } | 792 } |
811 return *value()->Type(); | 793 return *value()->Type(); |
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1543 CompileType MergedMathInstr::ComputeType() const { | 1525 CompileType MergedMathInstr::ComputeType() const { |
1544 return CompileType::Dynamic(); | 1526 return CompileType::Dynamic(); |
1545 } | 1527 } |
1546 | 1528 |
1547 | 1529 |
1548 CompileType ExtractNthOutputInstr::ComputeType() const { | 1530 CompileType ExtractNthOutputInstr::ComputeType() const { |
1549 return CompileType::FromCid(definition_cid_); | 1531 return CompileType::FromCid(definition_cid_); |
1550 } | 1532 } |
1551 | 1533 |
1552 } // namespace dart | 1534 } // namespace dart |
OLD | NEW |