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()); |
370 } | 387 } |
371 // TODO(fschneider): Add propagation for null-comparisons. | |
372 // TODO(fschneider): Add propagation for generic is-tests. | 388 // TODO(fschneider): Add propagation for generic is-tests. |
373 | 389 |
374 // Grow types array if a new redefinition was inserted. | 390 // Grow types array if a new redefinition was inserted. |
375 if (redef != NULL) { | 391 if (redef != NULL) { |
376 for (intptr_t i = types_.length(); i <= redef->ssa_temp_index() + 1; ++i) { | 392 for (intptr_t i = types_.length(); i <= redef->ssa_temp_index() + 1; ++i) { |
377 types_.Add(NULL); | 393 types_.Add(NULL); |
378 } | 394 } |
379 } | 395 } |
380 } | 396 } |
381 | 397 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
543 return Create(kNullCid, Type::ZoneHandle(Type::NullType())); | 559 return Create(kNullCid, Type::ZoneHandle(Type::NullType())); |
544 } | 560 } |
545 | 561 |
546 | 562 |
547 CompileType CompileType::Bool() { | 563 CompileType CompileType::Bool() { |
548 return Create(kBoolCid, Type::ZoneHandle(Type::BoolType())); | 564 return Create(kBoolCid, Type::ZoneHandle(Type::BoolType())); |
549 } | 565 } |
550 | 566 |
551 | 567 |
552 CompileType CompileType::Int() { | 568 CompileType CompileType::Int() { |
553 return FromAbstractType(Type::ZoneHandle(Type::IntType()), kNonNullable); | 569 return FromAbstractType(Type::ZoneHandle(Type::Int64Type()), kNonNullable); |
554 } | 570 } |
555 | 571 |
556 | 572 |
557 CompileType CompileType::Smi() { | 573 CompileType CompileType::Smi() { |
558 return Create(kSmiCid, Type::ZoneHandle(Type::SmiType())); | 574 return Create(kSmiCid, Type::ZoneHandle(Type::SmiType())); |
559 } | 575 } |
560 | 576 |
561 | 577 |
562 CompileType CompileType::String() { | 578 CompileType CompileType::String() { |
563 return FromAbstractType(Type::ZoneHandle(Type::StringType()), kNonNullable); | 579 return FromAbstractType(Type::ZoneHandle(Type::StringType()), kNonNullable); |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 return UpdateType(result); | 780 return UpdateType(result); |
765 } | 781 } |
766 | 782 |
767 | 783 |
768 CompileType RedefinitionInstr::ComputeType() const { | 784 CompileType RedefinitionInstr::ComputeType() const { |
769 if (constrained_type_ != NULL) { | 785 if (constrained_type_ != NULL) { |
770 // Check if the type associated with this redefinition is more specific | 786 // Check if the type associated with this redefinition is more specific |
771 // than the type of its input. If yes, return it. Otherwise, fall back | 787 // than the type of its input. If yes, return it. Otherwise, fall back |
772 // to the input's type. | 788 // to the input's type. |
773 | 789 |
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 } | |
781 // If either type is non-nullable, the resulting type is non-nullable. | 790 // If either type is non-nullable, the resulting type is non-nullable. |
782 const bool is_nullable = | 791 const bool is_nullable = |
783 value()->Type()->is_nullable() && constrained_type_->is_nullable(); | 792 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, |
| 797 value()->Type()->ToNullableCid()); |
| 798 } |
| 799 if (constrained_type_->ToNullableCid() != kDynamicCid) { |
| 800 return CompileType::CreateNullable(is_nullable, |
| 801 constrained_type_->ToNullableCid()); |
| 802 } |
784 if (value()->Type()->IsMoreSpecificThan( | 803 if (value()->Type()->IsMoreSpecificThan( |
785 *constrained_type_->ToAbstractType())) { | 804 *constrained_type_->ToAbstractType())) { |
786 return is_nullable ? *value()->Type() | 805 return is_nullable ? *value()->Type() |
787 : value()->Type()->CopyNonNullable(); | 806 : value()->Type()->CopyNonNullable(); |
788 } else { | 807 } else { |
789 return is_nullable ? *constrained_type_ | 808 return is_nullable ? *constrained_type_ |
790 : constrained_type_->CopyNonNullable(); | 809 : constrained_type_->CopyNonNullable(); |
791 } | 810 } |
792 } | 811 } |
793 return *value()->Type(); | 812 return *value()->Type(); |
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1525 CompileType MergedMathInstr::ComputeType() const { | 1544 CompileType MergedMathInstr::ComputeType() const { |
1526 return CompileType::Dynamic(); | 1545 return CompileType::Dynamic(); |
1527 } | 1546 } |
1528 | 1547 |
1529 | 1548 |
1530 CompileType ExtractNthOutputInstr::ComputeType() const { | 1549 CompileType ExtractNthOutputInstr::ComputeType() const { |
1531 return CompileType::FromCid(definition_cid_); | 1550 return CompileType::FromCid(definition_cid_); |
1532 } | 1551 } |
1533 | 1552 |
1534 } // namespace dart | 1553 } // namespace dart |
OLD | NEW |