Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 return AttributesEqual(other); | 43 return AttributesEqual(other); |
| 44 } | 44 } |
| 45 | 45 |
| 46 | 46 |
| 47 bool UseVal::Equals(Value* other) const { | 47 bool UseVal::Equals(Value* other) const { |
| 48 return other->IsUse() | 48 return other->IsUse() |
| 49 && definition() == other->AsUse()->definition(); | 49 && definition() == other->AsUse()->definition(); |
| 50 } | 50 } |
| 51 | 51 |
| 52 | 52 |
| 53 bool ConstantVal::Equals(Value* other) const { | |
| 54 return other->IsConstant() | |
| 55 && value().raw() == other->AsConstant()->value().raw(); | |
| 56 } | |
| 57 | |
| 58 | |
| 59 bool CheckClassComp::AttributesEqual(Computation* other) const { | |
| 60 CheckClassComp* other_check = other->AsCheckClass(); | |
| 61 if (other_check == NULL) return false; | |
| 62 if (ic_data()->NumberOfChecks() != other->ic_data()->NumberOfChecks()) { | |
| 63 return false; | |
| 64 } | |
| 65 for (intptr_t i = 0; i < ic_data()->NumberOfChecks(); ++i) { | |
| 66 // TODO(fschneider): Make sure ic_data are sorted to hit more cases. | |
| 67 if (ic_data()->GetReceiverClassIdAt(i) != | |
| 68 other->ic_data()->GetReceiverClassIdAt(i)) { | |
| 69 return false; | |
| 70 } | |
| 71 } | |
| 72 return true; | |
| 73 } | |
| 74 | |
| 75 | |
| 76 // Returns true if the value represents a constant. | 53 // Returns true if the value represents a constant. |
| 77 bool UseVal::BindsToConstant() const { | 54 bool UseVal::BindsToConstant() const { |
| 78 BindInstr* bind = definition()->AsBind(); | 55 BindInstr* bind = definition()->AsBind(); |
| 79 if (bind == NULL) { | 56 return (bind != NULL) && (bind->computation()->AsConstant() != NULL); |
| 80 return false; | |
| 81 } | |
| 82 return bind->computation()->AsMaterialize() != NULL; | |
| 83 } | 57 } |
| 84 | 58 |
| 85 | 59 |
| 86 // Returns true if the value represents constant null. | 60 // Returns true if the value represents constant null. |
| 87 bool UseVal::BindsToConstantNull() const { | 61 bool UseVal::BindsToConstantNull() const { |
| 88 BindInstr* bind = definition()->AsBind(); | 62 BindInstr* bind = definition()->AsBind(); |
| 89 if (bind == NULL) { | 63 if (bind == NULL) { |
| 90 return false; | 64 return false; |
| 91 } | 65 } |
| 92 MaterializeComp* constant = bind->computation()->AsMaterialize(); | 66 ConstantComp* constant = bind->computation()->AsConstant(); |
| 93 if (constant != NULL) { | 67 return (constant != NULL) && constant->value().IsNull(); |
| 94 return constant->constant_val()->value().IsNull(); | |
| 95 } | |
| 96 return false; | |
| 97 } | 68 } |
| 98 | 69 |
| 99 | 70 |
| 100 const Object& UseVal::BoundConstant() const { | 71 const Object& UseVal::BoundConstant() const { |
| 101 ASSERT(BindsToConstant()); | 72 ASSERT(BindsToConstant()); |
| 102 BindInstr* bind = definition()->AsBind(); | 73 BindInstr* bind = definition()->AsBind(); |
| 103 ASSERT(bind != NULL); | 74 ASSERT(bind != NULL); |
| 104 MaterializeComp* constant = bind->computation()->AsMaterialize(); | 75 ConstantComp* constant = bind->computation()->AsConstant(); |
| 105 ASSERT(constant != NULL); | 76 ASSERT(constant != NULL); |
| 106 return constant->constant_val()->value(); | 77 return constant->value(); |
| 107 } | 78 } |
| 108 | 79 |
| 109 | 80 |
| 81 bool ConstantComp::AttributesEqual(Computation* other) const { | |
| 82 ConstantComp* other_constant = other->AsConstant(); | |
| 83 return (other_constant != NULL) && | |
| 84 (value().raw() == other_constant->value().raw()); | |
| 85 } | |
| 86 | |
| 87 | |
| 88 bool CheckClassComp::AttributesEqual(Computation* other) const { | |
| 89 CheckClassComp* other_check = other->AsCheckClass(); | |
| 90 if (other_check == NULL) return false; | |
| 91 if (ic_data()->NumberOfChecks() != other->ic_data()->NumberOfChecks()) { | |
| 92 return false; | |
| 93 } | |
| 94 for (intptr_t i = 0; i < ic_data()->NumberOfChecks(); ++i) { | |
| 95 // TODO(fschneider): Make sure ic_data are sorted to hit more cases. | |
| 96 if (ic_data()->GetReceiverClassIdAt(i) != | |
| 97 other->ic_data()->GetReceiverClassIdAt(i)) { | |
| 98 return false; | |
| 99 } | |
| 100 } | |
| 101 return true; | |
| 102 } | |
| 103 | |
| 104 | |
| 105 GraphEntryInstr::GraphEntryInstr(TargetEntryInstr* normal_entry) | |
| 106 : BlockEntryInstr(), | |
| 107 normal_entry_(normal_entry), | |
| 108 catch_entries_(), | |
| 109 start_env_(NULL), | |
| 110 constant_null_(new BindInstr(BindInstr::kUsed, | |
|
Florian Schneider
2012/08/29 11:07:48
Maybe break after the first '(' here helps?
| |
| 111 new ConstantComp(Object::ZoneHandle()))), | |
| 112 spill_slot_count_(0) { | |
| 113 } | |
| 114 | |
| 115 | |
| 110 MethodRecognizer::Kind MethodRecognizer::RecognizeKind( | 116 MethodRecognizer::Kind MethodRecognizer::RecognizeKind( |
| 111 const Function& function) { | 117 const Function& function) { |
| 112 // Only core and math library methods can be recognized. | 118 // Only core and math library methods can be recognized. |
| 113 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 119 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 114 const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary()); | 120 const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary()); |
| 115 const Library& math_lib = Library::Handle(Library::MathLibrary()); | 121 const Library& math_lib = Library::Handle(Library::MathLibrary()); |
| 116 const Class& function_class = Class::Handle(function.Owner()); | 122 const Class& function_class = Class::Handle(function.Owner()); |
| 117 if ((function_class.library() != core_lib.raw()) && | 123 if ((function_class.library() != core_lib.raw()) && |
| 118 (function_class.library() != core_impl_lib.raw()) && | 124 (function_class.library() != core_impl_lib.raw()) && |
| 119 (function_class.library() != math_lib.raw())) { | 125 (function_class.library() != math_lib.raw())) { |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 UseVal* current = env_use_list_; | 412 UseVal* current = env_use_list_; |
| 407 env_use_list_ = env_use_list_->next_use(); | 413 env_use_list_ = env_use_list_->next_use(); |
| 408 current->set_definition(other); | 414 current->set_definition(other); |
| 409 current->AddToEnvUseList(); | 415 current->AddToEnvUseList(); |
| 410 } | 416 } |
| 411 } | 417 } |
| 412 | 418 |
| 413 | 419 |
| 414 void Definition::ReplaceUsesWith(Value* value) { | 420 void Definition::ReplaceUsesWith(Value* value) { |
| 415 ASSERT(value != NULL); | 421 ASSERT(value != NULL); |
| 416 if (value->IsUse()) { | 422 ASSERT(value->IsUse()); |
| 417 ReplaceUsesWith(value->AsUse()->definition()); | 423 ReplaceUsesWith(value->AsUse()->definition()); |
| 418 return; | 424 return; |
|
Florian Schneider
2012/08/29 11:07:48
No need for a return here.
Kevin Millikin (Google)
2012/08/29 12:43:44
Actually, this whole function seems kind of pointl
| |
| 419 } | |
| 420 ASSERT(value->IsConstant()); | |
| 421 while (input_use_list_ != NULL) { | |
| 422 Instruction* instr = input_use_list_->instruction(); | |
| 423 instr->SetInputAt(input_use_list_->use_index(), value); | |
| 424 input_use_list_ = input_use_list_->next_use(); | |
| 425 } | |
| 426 while (env_use_list_ != NULL) { | |
| 427 Environment* env = env_use_list_->instruction()->env(); | |
| 428 ASSERT(env != NULL); | |
| 429 env->values()[env_use_list_->use_index()] = value; | |
| 430 env_use_list_ = env_use_list_->next_use(); | |
| 431 } | |
| 432 } | 425 } |
| 433 | 426 |
| 434 | 427 |
| 435 bool Definition::SetPropagatedCid(intptr_t cid) { | 428 bool Definition::SetPropagatedCid(intptr_t cid) { |
| 436 if (cid == kIllegalCid) { | 429 if (cid == kIllegalCid) { |
| 437 return false; | 430 return false; |
| 438 } | 431 } |
| 439 if (propagated_cid_ == kIllegalCid) { | 432 if (propagated_cid_ == kIllegalCid) { |
| 440 // First setting, nothing has changed. | 433 // First setting, nothing has changed. |
| 441 propagated_cid_ = cid; | 434 propagated_cid_ = cid; |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 681 ASSERT(index == 0); | 674 ASSERT(index == 0); |
| 682 return successor(); | 675 return successor(); |
| 683 } | 676 } |
| 684 | 677 |
| 685 | 678 |
| 686 void Instruction::Goto(JoinEntryInstr* entry) { | 679 void Instruction::Goto(JoinEntryInstr* entry) { |
| 687 set_next(new GotoInstr(entry)); | 680 set_next(new GotoInstr(entry)); |
| 688 } | 681 } |
| 689 | 682 |
| 690 | 683 |
| 691 RawAbstractType* ConstantVal::CompileType() const { | |
| 692 if (value().IsNull()) { | |
| 693 return Type::NullType(); | |
| 694 } | |
| 695 if (value().IsInstance()) { | |
| 696 return Instance::Cast(value()).GetType(); | |
| 697 } else { | |
| 698 ASSERT(value().IsAbstractTypeArguments()); | |
| 699 return AbstractType::null(); | |
| 700 } | |
| 701 } | |
| 702 | |
| 703 | |
| 704 intptr_t ConstantVal::ResultCid() const { | |
| 705 if (value().IsNull()) { | |
| 706 return kNullCid; | |
| 707 } | |
| 708 if (value().IsInstance()) { | |
| 709 return Class::Handle(value().clazz()).id(); | |
| 710 } else { | |
| 711 ASSERT(value().IsAbstractTypeArguments()); | |
| 712 return kDynamicCid; | |
| 713 } | |
| 714 } | |
| 715 | |
| 716 | |
| 717 RawAbstractType* UseVal::CompileType() const { | 684 RawAbstractType* UseVal::CompileType() const { |
| 718 if (definition()->HasPropagatedType()) { | 685 if (definition()->HasPropagatedType()) { |
| 719 return definition()->PropagatedType(); | 686 return definition()->PropagatedType(); |
| 720 } | 687 } |
| 721 // The compile type may be requested when building the flow graph, i.e. before | 688 // The compile type may be requested when building the flow graph, i.e. before |
| 722 // type propagation has occurred. To avoid repeatedly computing the compile | 689 // type propagation has occurred. To avoid repeatedly computing the compile |
| 723 // type of the definition, we store it as initial propagated type. | 690 // type of the definition, we store it as initial propagated type. |
| 724 AbstractType& type = AbstractType::Handle(definition()->CompileType()); | 691 AbstractType& type = AbstractType::Handle(definition()->CompileType()); |
| 725 definition()->SetPropagatedType(type); | 692 definition()->SetPropagatedType(type); |
| 726 return type.raw(); | 693 return type.raw(); |
| 727 } | 694 } |
| 728 | 695 |
| 729 | 696 |
| 730 intptr_t UseVal::ResultCid() const { | 697 intptr_t UseVal::ResultCid() const { |
| 731 return definition()->GetPropagatedCid(); | 698 return definition()->GetPropagatedCid(); |
| 732 } | 699 } |
| 733 | 700 |
| 734 | 701 |
| 735 | 702 |
| 736 RawAbstractType* MaterializeComp::CompileType() const { | 703 RawAbstractType* ConstantComp::CompileType() const { |
| 737 return constant_val()->CompileType(); | 704 if (value().IsNull()) { |
| 705 return Type::NullType(); | |
| 706 } | |
| 707 if (value().IsInstance()) { | |
| 708 return Instance::Cast(value()).GetType(); | |
| 709 } else { | |
| 710 ASSERT(value().IsAbstractTypeArguments()); | |
| 711 return AbstractType::null(); | |
| 712 } | |
| 738 } | 713 } |
| 739 | 714 |
| 740 | 715 |
| 741 intptr_t MaterializeComp::ResultCid() const { | 716 intptr_t ConstantComp::ResultCid() const { |
| 742 return constant_val()->ResultCid(); | 717 if (value().IsNull()) { |
| 718 return kNullCid; | |
| 719 } | |
| 720 if (value().IsInstance()) { | |
| 721 return Class::Handle(value().clazz()).id(); | |
| 722 } else { | |
| 723 ASSERT(value().IsAbstractTypeArguments()); | |
| 724 return kDynamicCid; | |
| 725 } | |
| 743 } | 726 } |
| 744 | 727 |
| 745 | 728 |
| 746 RawAbstractType* AssertAssignableComp::CompileType() const { | 729 RawAbstractType* AssertAssignableComp::CompileType() const { |
| 747 const AbstractType& value_compile_type = | 730 const AbstractType& value_compile_type = |
| 748 AbstractType::Handle(value()->CompileType()); | 731 AbstractType::Handle(value()->CompileType()); |
| 749 if (!value_compile_type.IsNull() && | 732 if (!value_compile_type.IsNull() && |
| 750 value_compile_type.IsMoreSpecificThan(dst_type(), NULL)) { | 733 value_compile_type.IsMoreSpecificThan(dst_type(), NULL)) { |
| 751 return value_compile_type.raw(); | 734 return value_compile_type.raw(); |
| 752 } | 735 } |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1502 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 1485 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 1503 // where PushArgument is handled by BindInstr::EmitNativeCode. | 1486 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 1504 // TODO(fschneider): Avoid special-casing for SSA mode here. | 1487 // TODO(fschneider): Avoid special-casing for SSA mode here. |
| 1505 if (compiler->is_optimizing()) { | 1488 if (compiler->is_optimizing()) { |
| 1506 ASSERT(locs()->in(0).IsRegister()); | 1489 ASSERT(locs()->in(0).IsRegister()); |
| 1507 __ PushRegister(locs()->in(0).reg()); | 1490 __ PushRegister(locs()->in(0).reg()); |
| 1508 } | 1491 } |
| 1509 } | 1492 } |
| 1510 | 1493 |
| 1511 | 1494 |
| 1512 // Helper to either use the constant value of a definition or the definition. | |
| 1513 static Value* UseDefinition(Definition* defn) { | |
| 1514 if (defn->IsBind() && defn->AsBind()->computation()->IsMaterialize()) { | |
| 1515 return defn->AsBind()->computation()->AsMaterialize()->constant_val(); | |
| 1516 } else { | |
| 1517 return new UseVal(defn); | |
| 1518 } | |
| 1519 } | |
| 1520 | |
| 1521 | |
| 1522 Environment::Environment(const GrowableArray<Definition*>& definitions, | 1495 Environment::Environment(const GrowableArray<Definition*>& definitions, |
| 1523 intptr_t fixed_parameter_count) | 1496 intptr_t fixed_parameter_count) |
| 1524 : values_(definitions.length()), | 1497 : values_(definitions.length()), |
| 1525 locations_(NULL), | 1498 locations_(NULL), |
| 1526 fixed_parameter_count_(fixed_parameter_count) { | 1499 fixed_parameter_count_(fixed_parameter_count) { |
| 1527 for (intptr_t i = 0; i < definitions.length(); ++i) { | 1500 for (intptr_t i = 0; i < definitions.length(); ++i) { |
| 1528 values_.Add(UseDefinition(definitions[i])); | 1501 values_.Add(new UseVal(definitions[i])); |
| 1529 } | 1502 } |
| 1530 } | 1503 } |
| 1531 | 1504 |
| 1532 | 1505 |
| 1533 Environment* Environment::Copy() const { | 1506 Environment* Environment::Copy() const { |
| 1534 Environment* copy = new Environment(values().length(), | 1507 Environment* copy = new Environment(values().length(), |
| 1535 fixed_parameter_count()); | 1508 fixed_parameter_count()); |
| 1536 GrowableArray<Value*>* values_copy = copy->values_ptr(); | 1509 GrowableArray<Value*>* values_copy = copy->values_ptr(); |
| 1537 for (intptr_t i = 0; i < values().length(); ++i) { | 1510 for (intptr_t i = 0; i < values().length(); ++i) { |
| 1538 values_copy->Add(values()[i]->CopyValue()); | 1511 values_copy->Add(values()[i]->CopyValue()); |
| 1539 } | 1512 } |
| 1540 return copy; | 1513 return copy; |
| 1541 } | 1514 } |
| 1542 | 1515 |
| 1543 | 1516 |
| 1544 #undef __ | 1517 #undef __ |
| 1545 | 1518 |
| 1546 } // namespace dart | 1519 } // namespace dart |
| OLD | NEW |