| 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 |