| 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" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/locations.h" | 12 #include "vm/locations.h" |
| 13 #include "vm/object.h" | 13 #include "vm/object.h" |
| 14 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 15 #include "vm/os.h" | 15 #include "vm/os.h" |
| 16 #include "vm/scopes.h" | 16 #include "vm/scopes.h" |
| 17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 18 #include "vm/symbols.h" | 18 #include "vm/symbols.h" |
| 19 | 19 |
| 20 namespace dart { | 20 namespace dart { |
| 21 | 21 |
| 22 DECLARE_FLAG(bool, enable_type_checks); | 22 DECLARE_FLAG(bool, enable_type_checks); |
| 23 | 23 |
| 24 | 24 |
| 25 intptr_t Computation::Hashcode() const { | 25 intptr_t Computation::Hashcode() const { |
| 26 intptr_t result = computation_kind(); | 26 intptr_t result = computation_kind(); |
| 27 for (intptr_t i = 0; i < InputCount(); ++i) { | 27 for (intptr_t i = 0; i < InputCount(); ++i) { |
| 28 UseVal* val = InputAt(i)->AsUse(); | 28 Value* value = InputAt(i); |
| 29 intptr_t j = val != NULL | 29 intptr_t j = value->definition()->ssa_temp_index(); |
| 30 ? val->definition()->ssa_temp_index() | |
| 31 : -1; | |
| 32 result = result * 31 + j; | 30 result = result * 31 + j; |
| 33 } | 31 } |
| 34 return result; | 32 return result; |
| 35 } | 33 } |
| 36 | 34 |
| 37 | 35 |
| 38 bool Computation::Equals(Computation* other) const { | 36 bool Computation::Equals(Computation* other) const { |
| 39 if (computation_kind() != other->computation_kind()) return false; | 37 if (computation_kind() != other->computation_kind()) return false; |
| 40 for (intptr_t i = 0; i < InputCount(); ++i) { | 38 for (intptr_t i = 0; i < InputCount(); ++i) { |
| 41 if (!InputAt(i)->Equals(other->InputAt(i))) return false; | 39 if (!InputAt(i)->Equals(other->InputAt(i))) return false; |
| 42 } | 40 } |
| 43 return AttributesEqual(other); | 41 return AttributesEqual(other); |
| 44 } | 42 } |
| 45 | 43 |
| 46 | 44 |
| 47 bool UseVal::Equals(Value* other) const { | 45 bool Value::Equals(Value* other) const { |
| 48 return other->IsUse() | 46 return definition() == other->definition(); |
| 49 && definition() == other->AsUse()->definition(); | |
| 50 } | 47 } |
| 51 | 48 |
| 52 | 49 |
| 53 bool CheckClassComp::AttributesEqual(Computation* other) const { | 50 bool CheckClassComp::AttributesEqual(Computation* other) const { |
| 54 CheckClassComp* other_check = other->AsCheckClass(); | 51 CheckClassComp* other_check = other->AsCheckClass(); |
| 55 if (other_check == NULL) return false; | 52 if (other_check == NULL) return false; |
| 56 if (ic_data()->NumberOfChecks() != other->ic_data()->NumberOfChecks()) { | 53 if (ic_data()->NumberOfChecks() != other->ic_data()->NumberOfChecks()) { |
| 57 return false; | 54 return false; |
| 58 } | 55 } |
| 59 for (intptr_t i = 0; i < ic_data()->NumberOfChecks(); ++i) { | 56 for (intptr_t i = 0; i < ic_data()->NumberOfChecks(); ++i) { |
| 60 // TODO(fschneider): Make sure ic_data are sorted to hit more cases. | 57 // TODO(fschneider): Make sure ic_data are sorted to hit more cases. |
| 61 if (ic_data()->GetReceiverClassIdAt(i) != | 58 if (ic_data()->GetReceiverClassIdAt(i) != |
| 62 other->ic_data()->GetReceiverClassIdAt(i)) { | 59 other->ic_data()->GetReceiverClassIdAt(i)) { |
| 63 return false; | 60 return false; |
| 64 } | 61 } |
| 65 } | 62 } |
| 66 return true; | 63 return true; |
| 67 } | 64 } |
| 68 | 65 |
| 69 | 66 |
| 70 bool CheckArrayBoundComp::AttributesEqual(Computation* other) const { | 67 bool CheckArrayBoundComp::AttributesEqual(Computation* other) const { |
| 71 CheckArrayBoundComp* other_check = other->AsCheckArrayBound(); | 68 CheckArrayBoundComp* other_check = other->AsCheckArrayBound(); |
| 72 if (other_check == NULL) return false; | 69 if (other_check == NULL) return false; |
| 73 return array_type() == other_check->array_type(); | 70 return array_type() == other_check->array_type(); |
| 74 } | 71 } |
| 75 | 72 |
| 76 | 73 |
| 77 // Returns true if the value represents a constant. | 74 // Returns true if the value represents a constant. |
| 78 bool UseVal::BindsToConstant() const { | 75 bool Value::BindsToConstant() const { |
| 79 BindInstr* bind = definition()->AsBind(); | 76 BindInstr* bind = definition()->AsBind(); |
| 80 return (bind != NULL) && (bind->computation()->AsConstant() != NULL); | 77 return (bind != NULL) && (bind->computation()->AsConstant() != NULL); |
| 81 } | 78 } |
| 82 | 79 |
| 83 | 80 |
| 84 // Returns true if the value represents constant null. | 81 // Returns true if the value represents constant null. |
| 85 bool UseVal::BindsToConstantNull() const { | 82 bool Value::BindsToConstantNull() const { |
| 86 BindInstr* bind = definition()->AsBind(); | 83 BindInstr* bind = definition()->AsBind(); |
| 87 if (bind == NULL) { | 84 if (bind == NULL) { |
| 88 return false; | 85 return false; |
| 89 } | 86 } |
| 90 ConstantComp* constant = bind->computation()->AsConstant(); | 87 ConstantComp* constant = bind->computation()->AsConstant(); |
| 91 return (constant != NULL) && constant->value().IsNull(); | 88 return (constant != NULL) && constant->value().IsNull(); |
| 92 } | 89 } |
| 93 | 90 |
| 94 | 91 |
| 95 const Object& UseVal::BoundConstant() const { | 92 const Object& Value::BoundConstant() const { |
| 96 ASSERT(BindsToConstant()); | 93 ASSERT(BindsToConstant()); |
| 97 BindInstr* bind = definition()->AsBind(); | 94 BindInstr* bind = definition()->AsBind(); |
| 98 ASSERT(bind != NULL); | 95 ASSERT(bind != NULL); |
| 99 ConstantComp* constant = bind->computation()->AsConstant(); | 96 ConstantComp* constant = bind->computation()->AsConstant(); |
| 100 ASSERT(constant != NULL); | 97 ASSERT(constant != NULL); |
| 101 return constant->value(); | 98 return constant->value(); |
| 102 } | 99 } |
| 103 | 100 |
| 104 | 101 |
| 105 bool ConstantComp::AttributesEqual(Computation* other) const { | 102 bool ConstantComp::AttributesEqual(Computation* other) const { |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 } | 384 } |
| 388 } | 385 } |
| 389 | 386 |
| 390 | 387 |
| 391 void Instruction::RecordAssignedVars(BitVector* assigned_vars, | 388 void Instruction::RecordAssignedVars(BitVector* assigned_vars, |
| 392 intptr_t fixed_parameter_count) { | 389 intptr_t fixed_parameter_count) { |
| 393 // Nothing to do for the base class. | 390 // Nothing to do for the base class. |
| 394 } | 391 } |
| 395 | 392 |
| 396 | 393 |
| 397 void UseVal::AddToInputUseList() { | 394 void Value::AddToInputUseList() { |
| 398 set_next_use(definition()->input_use_list()); | 395 set_next_use(definition()->input_use_list()); |
| 399 definition()->set_input_use_list(this); | 396 definition()->set_input_use_list(this); |
| 400 } | 397 } |
| 401 | 398 |
| 402 | 399 |
| 403 void UseVal::AddToEnvUseList() { | 400 void Value::AddToEnvUseList() { |
| 404 set_next_use(definition()->env_use_list()); | 401 set_next_use(definition()->env_use_list()); |
| 405 definition()->set_env_use_list(this); | 402 definition()->set_env_use_list(this); |
| 406 } | 403 } |
| 407 | 404 |
| 408 | 405 |
| 409 void Definition::ReplaceUsesWith(Definition* other) { | 406 void Definition::ReplaceUsesWith(Definition* other) { |
| 410 ASSERT(other != NULL); | 407 ASSERT(other != NULL); |
| 411 ASSERT(this != other); | 408 ASSERT(this != other); |
| 412 while (input_use_list_ != NULL) { | 409 while (input_use_list_ != NULL) { |
| 413 UseVal* current = input_use_list_; | 410 Value* current = input_use_list_; |
| 414 input_use_list_ = input_use_list_->next_use(); | 411 input_use_list_ = input_use_list_->next_use(); |
| 415 current->set_definition(other); | 412 current->set_definition(other); |
| 416 current->AddToInputUseList(); | 413 current->AddToInputUseList(); |
| 417 } | 414 } |
| 418 while (env_use_list_ != NULL) { | 415 while (env_use_list_ != NULL) { |
| 419 UseVal* current = env_use_list_; | 416 Value* current = env_use_list_; |
| 420 env_use_list_ = env_use_list_->next_use(); | 417 env_use_list_ = env_use_list_->next_use(); |
| 421 current->set_definition(other); | 418 current->set_definition(other); |
| 422 current->AddToEnvUseList(); | 419 current->AddToEnvUseList(); |
| 423 } | 420 } |
| 424 } | 421 } |
| 425 | 422 |
| 426 | 423 |
| 427 bool Definition::SetPropagatedCid(intptr_t cid) { | 424 bool Definition::SetPropagatedCid(intptr_t cid) { |
| 428 if (cid == kIllegalCid) { | 425 if (cid == kIllegalCid) { |
| 429 return false; | 426 return false; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 ASSERT(index == 0); | 670 ASSERT(index == 0); |
| 674 return successor(); | 671 return successor(); |
| 675 } | 672 } |
| 676 | 673 |
| 677 | 674 |
| 678 void Instruction::Goto(JoinEntryInstr* entry) { | 675 void Instruction::Goto(JoinEntryInstr* entry) { |
| 679 set_next(new GotoInstr(entry)); | 676 set_next(new GotoInstr(entry)); |
| 680 } | 677 } |
| 681 | 678 |
| 682 | 679 |
| 683 RawAbstractType* UseVal::CompileType() const { | 680 RawAbstractType* Value::CompileType() const { |
| 684 if (definition()->HasPropagatedType()) { | 681 if (definition()->HasPropagatedType()) { |
| 685 return definition()->PropagatedType(); | 682 return definition()->PropagatedType(); |
| 686 } | 683 } |
| 687 // The compile type may be requested when building the flow graph, i.e. before | 684 // The compile type may be requested when building the flow graph, i.e. before |
| 688 // type propagation has occurred. To avoid repeatedly computing the compile | 685 // type propagation has occurred. To avoid repeatedly computing the compile |
| 689 // type of the definition, we store it as initial propagated type. | 686 // type of the definition, we store it as initial propagated type. |
| 690 AbstractType& type = AbstractType::Handle(definition()->CompileType()); | 687 AbstractType& type = AbstractType::Handle(definition()->CompileType()); |
| 691 definition()->SetPropagatedType(type); | 688 definition()->SetPropagatedType(type); |
| 692 return type.raw(); | 689 return type.raw(); |
| 693 } | 690 } |
| 694 | 691 |
| 695 | 692 |
| 696 intptr_t UseVal::ResultCid() const { | 693 intptr_t Value::ResultCid() const { |
| 697 return definition()->GetPropagatedCid(); | 694 return definition()->GetPropagatedCid(); |
| 698 } | 695 } |
| 699 | 696 |
| 700 | 697 |
| 701 | 698 |
| 702 RawAbstractType* ConstantComp::CompileType() const { | 699 RawAbstractType* ConstantComp::CompileType() const { |
| 703 if (value().IsNull()) { | 700 if (value().IsNull()) { |
| 704 return Type::NullType(); | 701 return Type::NullType(); |
| 705 } | 702 } |
| 706 if (value().IsInstance()) { | 703 if (value().IsInstance()) { |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 } | 1079 } |
| 1083 | 1080 |
| 1084 | 1081 |
| 1085 // Optimizations that eliminate or simplify individual computations. | 1082 // Optimizations that eliminate or simplify individual computations. |
| 1086 Definition* Computation::TryReplace(BindInstr* instr) const { | 1083 Definition* Computation::TryReplace(BindInstr* instr) const { |
| 1087 return instr; | 1084 return instr; |
| 1088 } | 1085 } |
| 1089 | 1086 |
| 1090 | 1087 |
| 1091 Definition* StrictCompareComp::TryReplace(BindInstr* instr) const { | 1088 Definition* StrictCompareComp::TryReplace(BindInstr* instr) const { |
| 1092 UseVal* left_use = left()->AsUse(); | 1089 if (!right()->BindsToConstant()) return instr; |
| 1093 UseVal* right_use = right()->AsUse(); | 1090 const Object& right_constant = right()->BoundConstant(); |
| 1094 if ((right_use == NULL) || (left_use == NULL)) return instr; | 1091 Definition* left_defn = left()->definition(); |
| 1095 if (!right_use->BindsToConstant()) return instr; | |
| 1096 const Object& right_constant = right_use->BoundConstant(); | |
| 1097 Definition* left = left_use->definition(); | |
| 1098 // TODO(fschneider): Handle other cases: e === false and e !== true/false. | 1092 // TODO(fschneider): Handle other cases: e === false and e !== true/false. |
| 1099 // Handles e === true. | 1093 // Handles e === true. |
| 1100 if ((kind() == Token::kEQ_STRICT) && | 1094 if ((kind() == Token::kEQ_STRICT) && |
| 1101 (right_constant.raw() == Bool::True()) && | 1095 (right_constant.raw() == Bool::True()) && |
| 1102 (left_use->ResultCid() == kBoolCid)) { | 1096 (left()->ResultCid() == kBoolCid)) { |
| 1103 // Remove the constant from the graph. | 1097 // Remove the constant from the graph. |
| 1104 BindInstr* right = right_use->definition()->AsBind(); | 1098 BindInstr* right_defn = right()->definition()->AsBind(); |
| 1105 if (right != NULL) { | 1099 if (right_defn != NULL) { |
| 1106 right->RemoveFromGraph(); | 1100 right_defn->RemoveFromGraph(); |
| 1107 } | 1101 } |
| 1108 // Return left subexpression as the replacement for this instruction. | 1102 // Return left subexpression as the replacement for this instruction. |
| 1109 return left; | 1103 return left_defn; |
| 1110 } | 1104 } |
| 1111 return instr; | 1105 return instr; |
| 1112 } | 1106 } |
| 1113 | 1107 |
| 1114 | 1108 |
| 1115 Definition* CheckClassComp::TryReplace(BindInstr* instr) const { | 1109 Definition* CheckClassComp::TryReplace(BindInstr* instr) const { |
| 1116 const intptr_t v_cid = value()->ResultCid(); | 1110 const intptr_t v_cid = value()->ResultCid(); |
| 1117 const intptr_t num_checks = ic_data()->NumberOfChecks(); | 1111 const intptr_t num_checks = ic_data()->NumberOfChecks(); |
| 1118 if ((num_checks == 1) && | 1112 if ((num_checks == 1) && |
| 1119 (v_cid == ic_data()->GetReceiverClassIdAt(0))) { | 1113 (v_cid == ic_data()->GetReceiverClassIdAt(0))) { |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1512 } | 1506 } |
| 1513 } | 1507 } |
| 1514 | 1508 |
| 1515 | 1509 |
| 1516 Environment::Environment(const GrowableArray<Definition*>& definitions, | 1510 Environment::Environment(const GrowableArray<Definition*>& definitions, |
| 1517 intptr_t fixed_parameter_count) | 1511 intptr_t fixed_parameter_count) |
| 1518 : values_(definitions.length()), | 1512 : values_(definitions.length()), |
| 1519 locations_(NULL), | 1513 locations_(NULL), |
| 1520 fixed_parameter_count_(fixed_parameter_count) { | 1514 fixed_parameter_count_(fixed_parameter_count) { |
| 1521 for (intptr_t i = 0; i < definitions.length(); ++i) { | 1515 for (intptr_t i = 0; i < definitions.length(); ++i) { |
| 1522 values_.Add(new UseVal(definitions[i])); | 1516 values_.Add(new Value(definitions[i])); |
| 1523 } | 1517 } |
| 1524 } | 1518 } |
| 1525 | 1519 |
| 1526 | 1520 |
| 1527 // Copies the environment and updates the environment use lists. | 1521 // Copies the environment and updates the environment use lists. |
| 1528 void Environment::CopyTo(Instruction* instr) const { | 1522 void Environment::CopyTo(Instruction* instr) const { |
| 1529 Environment* copy = new Environment(values().length(), | 1523 Environment* copy = new Environment(values().length(), |
| 1530 fixed_parameter_count()); | 1524 fixed_parameter_count()); |
| 1531 GrowableArray<Value*>* values_copy = copy->values_ptr(); | 1525 GrowableArray<Value*>* values_copy = copy->values_ptr(); |
| 1532 for (intptr_t i = 0; i < values().length(); ++i) { | 1526 for (intptr_t i = 0; i < values().length(); ++i) { |
| 1533 Value* value = values()[i]->CopyValue(); | 1527 Value* value = values()[i]->Copy(); |
| 1534 values_copy->Add(value); | 1528 values_copy->Add(value); |
| 1535 UseVal* use = value->AsUse(); | 1529 value->set_instruction(instr); |
| 1536 if (use != NULL) { | 1530 value->set_use_index(i); |
| 1537 use->set_instruction(instr); | 1531 value->AddToEnvUseList(); |
| 1538 use->set_use_index(i); | |
| 1539 use->AddToEnvUseList(); | |
| 1540 } | |
| 1541 } | 1532 } |
| 1542 instr->set_env(copy); | 1533 instr->set_env(copy); |
| 1543 } | 1534 } |
| 1544 | 1535 |
| 1545 | 1536 |
| 1546 #undef __ | 1537 #undef __ |
| 1547 | 1538 |
| 1548 } // namespace dart | 1539 } // namespace dart |
| OLD | NEW |