| 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 Definition::Hashcode() const { |
| 26 intptr_t result = computation_kind(); | 26 intptr_t result = tag(); |
| 27 for (intptr_t i = 0; i < InputCount(); ++i) { | 27 for (intptr_t i = 0; i < InputCount(); ++i) { |
| 28 Value* value = InputAt(i); | 28 Value* value = InputAt(i); |
| 29 intptr_t j = value->definition()->ssa_temp_index(); | 29 intptr_t j = value->definition()->ssa_temp_index(); |
| 30 result = result * 31 + j; | 30 result = result * 31 + j; |
| 31 } | 31 } |
| 32 return result; | 32 return result; |
| 33 } | 33 } |
| 34 | 34 |
| 35 | 35 |
| 36 bool Computation::Equals(Computation* other) const { | 36 bool Definition::Equals(Definition* other) const { |
| 37 if (computation_kind() != other->computation_kind()) return false; | 37 if (tag() != other->tag()) return false; |
| 38 for (intptr_t i = 0; i < InputCount(); ++i) { | 38 for (intptr_t i = 0; i < InputCount(); ++i) { |
| 39 if (!InputAt(i)->Equals(other->InputAt(i))) return false; | 39 if (!InputAt(i)->Equals(other->InputAt(i))) return false; |
| 40 } | 40 } |
| 41 return AttributesEqual(other); | 41 return AttributesEqual(other); |
| 42 } | 42 } |
| 43 | 43 |
| 44 | 44 |
| 45 bool Value::Equals(Value* other) const { | 45 bool Value::Equals(Value* other) const { |
| 46 return definition() == other->definition(); | 46 return definition() == other->definition(); |
| 47 } | 47 } |
| 48 | 48 |
| 49 | 49 |
| 50 bool CheckClassComp::AttributesEqual(Computation* other) const { | 50 bool CheckClassInstr::AttributesEqual(Definition* other) const { |
| 51 CheckClassComp* other_check = other->AsCheckClass(); | 51 CheckClassInstr* other_check = other->AsCheckClass(); |
| 52 if (other_check == NULL) return false; | 52 ASSERT(other_check != NULL); |
| 53 if (unary_checks().NumberOfChecks() != | 53 if (unary_checks().NumberOfChecks() != |
| 54 other_check->unary_checks().NumberOfChecks()) { | 54 other_check->unary_checks().NumberOfChecks()) { |
| 55 return false; | 55 return false; |
| 56 } | 56 } |
| 57 for (intptr_t i = 0; i < unary_checks().NumberOfChecks(); ++i) { | 57 for (intptr_t i = 0; i < unary_checks().NumberOfChecks(); ++i) { |
| 58 // TODO(fschneider): Make sure ic_data are sorted to hit more cases. | 58 // TODO(fschneider): Make sure ic_data are sorted to hit more cases. |
| 59 if (unary_checks().GetReceiverClassIdAt(i) != | 59 if (unary_checks().GetReceiverClassIdAt(i) != |
| 60 other_check->unary_checks().GetReceiverClassIdAt(i)) { | 60 other_check->unary_checks().GetReceiverClassIdAt(i)) { |
| 61 return false; | 61 return false; |
| 62 } | 62 } |
| 63 } | 63 } |
| 64 return true; | 64 return true; |
| 65 } | 65 } |
| 66 | 66 |
| 67 | 67 |
| 68 bool CheckArrayBoundComp::AttributesEqual(Computation* other) const { | 68 bool CheckArrayBoundInstr::AttributesEqual(Definition* other) const { |
| 69 CheckArrayBoundComp* other_check = other->AsCheckArrayBound(); | 69 CheckArrayBoundInstr* other_check = other->AsCheckArrayBound(); |
| 70 if (other_check == NULL) return false; | 70 ASSERT(other_check != NULL); |
| 71 return array_type() == other_check->array_type(); | 71 return array_type() == other_check->array_type(); |
| 72 } | 72 } |
| 73 | 73 |
| 74 | 74 |
| 75 // Returns true if the value represents a constant. | 75 // Returns true if the value represents a constant. |
| 76 bool Value::BindsToConstant() const { | 76 bool Value::BindsToConstant() const { |
| 77 BindInstr* bind = definition()->AsBind(); | 77 return definition()->IsConstant(); |
| 78 return (bind != NULL) && (bind->computation()->AsConstant() != NULL); | |
| 79 } | 78 } |
| 80 | 79 |
| 81 | 80 |
| 82 // Returns true if the value represents constant null. | 81 // Returns true if the value represents constant null. |
| 83 bool Value::BindsToConstantNull() const { | 82 bool Value::BindsToConstantNull() const { |
| 84 BindInstr* bind = definition()->AsBind(); | 83 ConstantInstr* constant = definition()->AsConstant(); |
| 85 if (bind == NULL) { | |
| 86 return false; | |
| 87 } | |
| 88 ConstantComp* constant = bind->computation()->AsConstant(); | |
| 89 return (constant != NULL) && constant->value().IsNull(); | 84 return (constant != NULL) && constant->value().IsNull(); |
| 90 } | 85 } |
| 91 | 86 |
| 92 | 87 |
| 93 const Object& Value::BoundConstant() const { | 88 const Object& Value::BoundConstant() const { |
| 94 ASSERT(BindsToConstant()); | 89 ASSERT(BindsToConstant()); |
| 95 BindInstr* bind = definition()->AsBind(); | 90 ConstantInstr* constant = definition()->AsConstant(); |
| 96 ASSERT(bind != NULL); | |
| 97 ConstantComp* constant = bind->computation()->AsConstant(); | |
| 98 ASSERT(constant != NULL); | 91 ASSERT(constant != NULL); |
| 99 return constant->value(); | 92 return constant->value(); |
| 100 } | 93 } |
| 101 | 94 |
| 102 | 95 |
| 103 bool ConstantComp::AttributesEqual(Computation* other) const { | 96 bool ConstantInstr::AttributesEqual(Definition* other) const { |
| 104 ConstantComp* other_constant = other->AsConstant(); | 97 ConstantInstr* other_constant = other->AsConstant(); |
| 105 return (other_constant != NULL) && | 98 ASSERT(other_constant != NULL); |
| 106 (value().raw() == other_constant->value().raw()); | 99 return (value().raw() == other_constant->value().raw()); |
| 107 } | 100 } |
| 108 | 101 |
| 109 | 102 |
| 110 GraphEntryInstr::GraphEntryInstr(TargetEntryInstr* normal_entry) | 103 GraphEntryInstr::GraphEntryInstr(TargetEntryInstr* normal_entry) |
| 111 : BlockEntryInstr(CatchClauseNode::kInvalidTryIndex), | 104 : BlockEntryInstr(CatchClauseNode::kInvalidTryIndex), |
| 112 normal_entry_(normal_entry), | 105 normal_entry_(normal_entry), |
| 113 catch_entries_(), | 106 catch_entries_(), |
| 114 start_env_(NULL), | 107 start_env_(NULL), |
| 115 constant_null_(new BindInstr(Definition::kValue, | 108 constant_null_(new ConstantInstr(Object::ZoneHandle())), |
| 116 new ConstantComp(Object::ZoneHandle()))), | |
| 117 spill_slot_count_(0) { | 109 spill_slot_count_(0) { |
| 118 } | 110 } |
| 119 | 111 |
| 120 | 112 |
| 121 MethodRecognizer::Kind MethodRecognizer::RecognizeKind( | 113 MethodRecognizer::Kind MethodRecognizer::RecognizeKind( |
| 122 const Function& function) { | 114 const Function& function) { |
| 123 // Only core and math library methods can be recognized. | 115 // Only core and math library methods can be recognized. |
| 124 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 116 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 125 const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary()); | 117 const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary()); |
| 126 const Library& math_lib = Library::Handle(Library::MathLibrary()); | 118 const Library& math_lib = Library::Handle(Library::MathLibrary()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 150 const char* MethodRecognizer::KindToCString(Kind kind) { | 142 const char* MethodRecognizer::KindToCString(Kind kind) { |
| 151 #define KIND_TO_STRING(class_name, function_name, enum_name) \ | 143 #define KIND_TO_STRING(class_name, function_name, enum_name) \ |
| 152 if (kind == k##enum_name) return #enum_name; | 144 if (kind == k##enum_name) return #enum_name; |
| 153 RECOGNIZED_LIST(KIND_TO_STRING) | 145 RECOGNIZED_LIST(KIND_TO_STRING) |
| 154 #undef KIND_TO_STRING | 146 #undef KIND_TO_STRING |
| 155 return "?"; | 147 return "?"; |
| 156 } | 148 } |
| 157 | 149 |
| 158 | 150 |
| 159 // ==== Support for visiting flow graphs. | 151 // ==== Support for visiting flow graphs. |
| 160 #define DEFINE_ACCEPT(ShortName, ClassName) \ | |
| 161 void ClassName::Accept(FlowGraphVisitor* visitor, BindInstr* instr) { \ | |
| 162 visitor->Visit##ShortName(this, instr); \ | |
| 163 } | |
| 164 | |
| 165 FOR_EACH_COMPUTATION(DEFINE_ACCEPT) | |
| 166 | |
| 167 #undef DEFINE_ACCEPT | |
| 168 | |
| 169 | |
| 170 #define DEFINE_ACCEPT(ShortName) \ | 152 #define DEFINE_ACCEPT(ShortName) \ |
| 171 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ | 153 void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ |
| 172 visitor->Visit##ShortName(this); \ | 154 visitor->Visit##ShortName(this); \ |
| 173 } | 155 } |
| 174 | 156 |
| 175 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT) | 157 FOR_EACH_INSTRUCTION(DEFINE_ACCEPT) |
| 176 | 158 |
| 177 #undef DEFINE_ACCEPT | 159 #undef DEFINE_ACCEPT |
| 178 | 160 |
| 179 | 161 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 void Definition::InsertAfter(Instruction* prev) { | 194 void Definition::InsertAfter(Instruction* prev) { |
| 213 ASSERT(previous_ == NULL); | 195 ASSERT(previous_ == NULL); |
| 214 ASSERT(next_ == NULL); | 196 ASSERT(next_ == NULL); |
| 215 previous_ = prev; | 197 previous_ = prev; |
| 216 next_ = prev->next_; | 198 next_ = prev->next_; |
| 217 next_->previous_ = this; | 199 next_->previous_ = this; |
| 218 previous_->next_ = this; | 200 previous_->next_ = this; |
| 219 } | 201 } |
| 220 | 202 |
| 221 | 203 |
| 222 ConstantComp* Definition::AsConstant() { | |
| 223 BindInstr* bind = AsBind(); | |
| 224 return (bind != NULL) ? bind->computation()->AsConstant() : NULL; | |
| 225 } | |
| 226 | |
| 227 | |
| 228 void ForwardInstructionIterator::RemoveCurrentFromGraph() { | 204 void ForwardInstructionIterator::RemoveCurrentFromGraph() { |
| 229 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. | 205 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. |
| 230 } | 206 } |
| 231 | 207 |
| 232 | 208 |
| 209 void ForwardInstructionIterator::ReplaceCurrentWith(Definition* other) { |
| 210 Definition* defn = current_->AsDefinition(); |
| 211 ASSERT(defn != NULL); |
| 212 defn->ReplaceUsesWith(other); |
| 213 ASSERT(other->env() == NULL); |
| 214 other->set_env(defn->env()); |
| 215 defn->set_env(NULL); |
| 216 ASSERT(!other->HasSSATemp()); |
| 217 if (defn->HasSSATemp()) other->set_ssa_temp_index(defn->ssa_temp_index()); |
| 218 |
| 219 other->InsertBefore(current_); // So other will be current. |
| 220 RemoveCurrentFromGraph(); |
| 221 } |
| 222 |
| 223 |
| 233 // Default implementation of visiting basic blocks. Can be overridden. | 224 // Default implementation of visiting basic blocks. Can be overridden. |
| 234 void FlowGraphVisitor::VisitBlocks() { | 225 void FlowGraphVisitor::VisitBlocks() { |
| 235 ASSERT(current_iterator_ == NULL); | 226 ASSERT(current_iterator_ == NULL); |
| 236 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 227 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 237 BlockEntryInstr* entry = block_order_[i]; | 228 BlockEntryInstr* entry = block_order_[i]; |
| 238 entry->Accept(this); | 229 entry->Accept(this); |
| 239 ForwardInstructionIterator it(entry); | 230 ForwardInstructionIterator it(entry); |
| 240 current_iterator_ = ⁢ | 231 current_iterator_ = ⁢ |
| 241 for (; !it.Done(); it.Advance()) { | 232 for (; !it.Done(); it.Advance()) { |
| 242 it.Current()->Accept(this); | 233 it.Current()->Accept(this); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 | 362 |
| 372 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { | 363 intptr_t JoinEntryInstr::IndexOfPredecessor(BlockEntryInstr* pred) const { |
| 373 for (intptr_t i = 0; i < predecessors_.length(); ++i) { | 364 for (intptr_t i = 0; i < predecessors_.length(); ++i) { |
| 374 if (predecessors_[i] == pred) return i; | 365 if (predecessors_[i] == pred) return i; |
| 375 } | 366 } |
| 376 return -1; | 367 return -1; |
| 377 } | 368 } |
| 378 | 369 |
| 379 | 370 |
| 380 // ==== Recording assigned variables. | 371 // ==== Recording assigned variables. |
| 381 void Computation::RecordAssignedVars(BitVector* assigned_vars, | 372 void Definition::RecordAssignedVars(BitVector* assigned_vars, |
| 382 intptr_t fixed_parameter_count) { | 373 intptr_t fixed_parameter_count) { |
| 383 // Nothing to do for the base class. | 374 // Nothing to do for the base class. |
| 384 } | 375 } |
| 385 | 376 |
| 386 | 377 |
| 387 void StoreLocalComp::RecordAssignedVars(BitVector* assigned_vars, | 378 void StoreLocalInstr::RecordAssignedVars(BitVector* assigned_vars, |
| 388 intptr_t fixed_parameter_count) { | 379 intptr_t fixed_parameter_count) { |
| 389 if (!local().is_captured()) { | 380 if (!local().is_captured()) { |
| 390 assigned_vars->Add(local().BitIndexIn(fixed_parameter_count)); | 381 assigned_vars->Add(local().BitIndexIn(fixed_parameter_count)); |
| 391 } | 382 } |
| 392 } | 383 } |
| 393 | 384 |
| 394 | 385 |
| 395 void Instruction::RecordAssignedVars(BitVector* assigned_vars, | 386 void Instruction::RecordAssignedVars(BitVector* assigned_vars, |
| 396 intptr_t fixed_parameter_count) { | 387 intptr_t fixed_parameter_count) { |
| 397 // Nothing to do for the base class. | 388 // Nothing to do for the base class. |
| 398 } | 389 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 421 } | 412 } |
| 422 while (env_use_list_ != NULL) { | 413 while (env_use_list_ != NULL) { |
| 423 Value* current = env_use_list_; | 414 Value* current = env_use_list_; |
| 424 env_use_list_ = env_use_list_->next_use(); | 415 env_use_list_ = env_use_list_->next_use(); |
| 425 current->set_definition(other); | 416 current->set_definition(other); |
| 426 current->AddToEnvUseList(); | 417 current->AddToEnvUseList(); |
| 427 } | 418 } |
| 428 } | 419 } |
| 429 | 420 |
| 430 | 421 |
| 422 void Definition::ReplaceWith(Definition* other, |
| 423 ForwardInstructionIterator* iterator) { |
| 424 if ((iterator != NULL) && (other == iterator->Current())) { |
| 425 iterator->ReplaceCurrentWith(other); |
| 426 } else { |
| 427 ReplaceUsesWith(other); |
| 428 ASSERT(other->env() == NULL); |
| 429 other->set_env(env()); |
| 430 set_env(NULL); |
| 431 ASSERT(!other->HasSSATemp()); |
| 432 if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index()); |
| 433 |
| 434 other->set_previous(previous()); |
| 435 previous()->set_next(other); |
| 436 set_previous(NULL); |
| 437 |
| 438 other->set_next(next()); |
| 439 next()->set_previous(other); |
| 440 set_next(NULL); |
| 441 } |
| 442 } |
| 443 |
| 444 |
| 431 bool Definition::SetPropagatedCid(intptr_t cid) { | 445 bool Definition::SetPropagatedCid(intptr_t cid) { |
| 432 if (cid == kIllegalCid) { | 446 if (cid == kIllegalCid) { |
| 433 return false; | 447 return false; |
| 434 } | 448 } |
| 435 if (propagated_cid_ == kIllegalCid) { | 449 if (propagated_cid_ == kIllegalCid) { |
| 436 // First setting, nothing has changed. | 450 // First setting, nothing has changed. |
| 437 propagated_cid_ = cid; | 451 propagated_cid_ = cid; |
| 438 return false; | 452 return false; |
| 439 } | 453 } |
| 440 bool has_changed = (propagated_cid_ != cid); | 454 bool has_changed = (propagated_cid_ != cid); |
| 441 propagated_cid_ = cid; | 455 propagated_cid_ = cid; |
| 442 return has_changed; | 456 return has_changed; |
| 443 } | 457 } |
| 444 | 458 |
| 445 RawAbstractType* BindInstr::CompileType() const { | |
| 446 ASSERT(!HasPropagatedType()); | |
| 447 // The compile type may be requested when building the flow graph, i.e. before | |
| 448 // type propagation has occurred. | |
| 449 return computation()->CompileType(); | |
| 450 } | |
| 451 | 459 |
| 452 | 460 intptr_t Definition::GetPropagatedCid() { |
| 453 intptr_t BindInstr::GetPropagatedCid() { | |
| 454 if (has_propagated_cid()) return propagated_cid(); | 461 if (has_propagated_cid()) return propagated_cid(); |
| 455 intptr_t cid = computation()->ResultCid(); | 462 intptr_t cid = ResultCid(); |
| 456 ASSERT(cid != kIllegalCid); | 463 ASSERT(cid != kIllegalCid); |
| 457 SetPropagatedCid(cid); | 464 SetPropagatedCid(cid); |
| 458 return cid; | 465 return cid; |
| 459 } | 466 } |
| 460 | 467 |
| 461 void BindInstr::RecordAssignedVars(BitVector* assigned_vars, | 468 |
| 462 intptr_t fixed_parameter_count) { | 469 intptr_t PhiInstr::GetPropagatedCid() { |
| 463 computation()->RecordAssignedVars(assigned_vars, fixed_parameter_count); | 470 return propagated_cid(); |
| 464 } | 471 } |
| 465 | 472 |
| 466 | 473 |
| 474 intptr_t ParameterInstr::GetPropagatedCid() { |
| 475 return propagated_cid(); |
| 476 } |
| 477 |
| 478 |
| 467 // ==== Postorder graph traversal. | 479 // ==== Postorder graph traversal. |
| 468 void GraphEntryInstr::DiscoverBlocks( | 480 void GraphEntryInstr::DiscoverBlocks( |
| 469 BlockEntryInstr* current_block, | 481 BlockEntryInstr* current_block, |
| 470 GrowableArray<BlockEntryInstr*>* preorder, | 482 GrowableArray<BlockEntryInstr*>* preorder, |
| 471 GrowableArray<BlockEntryInstr*>* postorder, | 483 GrowableArray<BlockEntryInstr*>* postorder, |
| 472 GrowableArray<intptr_t>* parent, | 484 GrowableArray<intptr_t>* parent, |
| 473 GrowableArray<BitVector*>* assigned_vars, | 485 GrowableArray<BitVector*>* assigned_vars, |
| 474 intptr_t variable_count, | 486 intptr_t variable_count, |
| 475 intptr_t fixed_parameter_count) { | 487 intptr_t fixed_parameter_count) { |
| 476 // We only visit this block once, first of all blocks. | 488 // We only visit this block once, first of all blocks. |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 return type.raw(); | 708 return type.raw(); |
| 697 } | 709 } |
| 698 | 710 |
| 699 | 711 |
| 700 intptr_t Value::ResultCid() const { | 712 intptr_t Value::ResultCid() const { |
| 701 return definition()->GetPropagatedCid(); | 713 return definition()->GetPropagatedCid(); |
| 702 } | 714 } |
| 703 | 715 |
| 704 | 716 |
| 705 | 717 |
| 706 RawAbstractType* ConstantComp::CompileType() const { | 718 RawAbstractType* ConstantInstr::CompileType() const { |
| 707 if (value().IsNull()) { | 719 if (value().IsNull()) { |
| 708 return Type::NullType(); | 720 return Type::NullType(); |
| 709 } | 721 } |
| 710 if (value().IsInstance()) { | 722 if (value().IsInstance()) { |
| 711 return Instance::Cast(value()).GetType(); | 723 return Instance::Cast(value()).GetType(); |
| 712 } else { | 724 } else { |
| 713 ASSERT(value().IsAbstractTypeArguments()); | 725 ASSERT(value().IsAbstractTypeArguments()); |
| 714 return AbstractType::null(); | 726 return AbstractType::null(); |
| 715 } | 727 } |
| 716 } | 728 } |
| 717 | 729 |
| 718 | 730 |
| 719 intptr_t ConstantComp::ResultCid() const { | 731 intptr_t ConstantInstr::ResultCid() const { |
| 720 if (value().IsNull()) { | 732 if (value().IsNull()) { |
| 721 return kNullCid; | 733 return kNullCid; |
| 722 } | 734 } |
| 723 if (value().IsInstance()) { | 735 if (value().IsInstance()) { |
| 724 return Class::Handle(value().clazz()).id(); | 736 return Class::Handle(value().clazz()).id(); |
| 725 } else { | 737 } else { |
| 726 ASSERT(value().IsAbstractTypeArguments()); | 738 ASSERT(value().IsAbstractTypeArguments()); |
| 727 return kDynamicCid; | 739 return kDynamicCid; |
| 728 } | 740 } |
| 729 } | 741 } |
| 730 | 742 |
| 731 | 743 |
| 732 RawAbstractType* AssertAssignableComp::CompileType() const { | 744 RawAbstractType* AssertAssignableInstr::CompileType() const { |
| 733 const AbstractType& value_compile_type = | 745 const AbstractType& value_compile_type = |
| 734 AbstractType::Handle(value()->CompileType()); | 746 AbstractType::Handle(value()->CompileType()); |
| 735 if (!value_compile_type.IsNull() && | 747 if (!value_compile_type.IsNull() && |
| 736 value_compile_type.IsMoreSpecificThan(dst_type(), NULL)) { | 748 value_compile_type.IsMoreSpecificThan(dst_type(), NULL)) { |
| 737 return value_compile_type.raw(); | 749 return value_compile_type.raw(); |
| 738 } | 750 } |
| 739 return dst_type().raw(); | 751 return dst_type().raw(); |
| 740 } | 752 } |
| 741 | 753 |
| 742 | 754 |
| 743 RawAbstractType* AssertBooleanComp::CompileType() const { | 755 RawAbstractType* AssertBooleanInstr::CompileType() const { |
| 744 return Type::BoolType(); | 756 return Type::BoolType(); |
| 745 } | 757 } |
| 746 | 758 |
| 747 | 759 |
| 748 RawAbstractType* ArgumentDefinitionTestComp::CompileType() const { | 760 RawAbstractType* ArgumentDefinitionTestInstr::CompileType() const { |
| 749 return Type::BoolType(); | 761 return Type::BoolType(); |
| 750 } | 762 } |
| 751 | 763 |
| 752 | 764 |
| 753 RawAbstractType* CurrentContextComp::CompileType() const { | 765 RawAbstractType* CurrentContextInstr::CompileType() const { |
| 754 return AbstractType::null(); | 766 return AbstractType::null(); |
| 755 } | 767 } |
| 756 | 768 |
| 757 | 769 |
| 758 RawAbstractType* StoreContextComp::CompileType() const { | 770 RawAbstractType* StoreContextInstr::CompileType() const { |
| 759 return AbstractType::null(); | 771 return AbstractType::null(); |
| 760 } | 772 } |
| 761 | 773 |
| 762 | 774 |
| 763 RawAbstractType* ClosureCallComp::CompileType() const { | 775 RawAbstractType* ClosureCallInstr::CompileType() const { |
| 764 // Because of function subtyping rules, the declared return type of a closure | 776 // Because of function subtyping rules, the declared return type of a closure |
| 765 // call cannot be relied upon for compile type analysis. For example, a | 777 // call cannot be relied upon for compile type analysis. For example, a |
| 766 // function returning Dynamic can be assigned to a closure variable declared | 778 // function returning Dynamic can be assigned to a closure variable declared |
| 767 // to return int and may actually return a double at run-time. | 779 // to return int and may actually return a double at run-time. |
| 768 return Type::DynamicType(); | 780 return Type::DynamicType(); |
| 769 } | 781 } |
| 770 | 782 |
| 771 | 783 |
| 772 RawAbstractType* InstanceCallComp::CompileType() const { | 784 RawAbstractType* InstanceCallInstr::CompileType() const { |
| 773 // TODO(regis): Return a more specific type than Dynamic for recognized | 785 // TODO(regis): Return a more specific type than Dynamic for recognized |
| 774 // combinations of receiver type and method name. | 786 // combinations of receiver type and method name. |
| 775 return Type::DynamicType(); | 787 return Type::DynamicType(); |
| 776 } | 788 } |
| 777 | 789 |
| 778 | 790 |
| 779 RawAbstractType* PolymorphicInstanceCallComp::CompileType() const { | 791 RawAbstractType* PolymorphicInstanceCallInstr::CompileType() const { |
| 780 return Type::DynamicType(); | 792 return Type::DynamicType(); |
| 781 } | 793 } |
| 782 | 794 |
| 783 | 795 |
| 784 RawAbstractType* StaticCallComp::CompileType() const { | 796 RawAbstractType* StaticCallInstr::CompileType() const { |
| 785 if (FLAG_enable_type_checks) { | 797 if (FLAG_enable_type_checks) { |
| 786 return function().result_type(); | 798 return function().result_type(); |
| 787 } | 799 } |
| 788 return Type::DynamicType(); | 800 return Type::DynamicType(); |
| 789 } | 801 } |
| 790 | 802 |
| 791 | 803 |
| 792 RawAbstractType* LoadLocalComp::CompileType() const { | 804 RawAbstractType* LoadLocalInstr::CompileType() const { |
| 793 if (FLAG_enable_type_checks) { | 805 if (FLAG_enable_type_checks) { |
| 794 return local().type().raw(); | 806 return local().type().raw(); |
| 795 } | 807 } |
| 796 return Type::DynamicType(); | 808 return Type::DynamicType(); |
| 797 } | 809 } |
| 798 | 810 |
| 799 | 811 |
| 800 RawAbstractType* StoreLocalComp::CompileType() const { | 812 RawAbstractType* StoreLocalInstr::CompileType() const { |
| 801 return value()->CompileType(); | 813 return value()->CompileType(); |
| 802 } | 814 } |
| 803 | 815 |
| 804 | 816 |
| 805 RawAbstractType* StrictCompareComp::CompileType() const { | 817 RawAbstractType* StrictCompareInstr::CompileType() const { |
| 806 return Type::BoolType(); | 818 return Type::BoolType(); |
| 807 } | 819 } |
| 808 | 820 |
| 809 | 821 |
| 810 // Only known == targets return a Boolean. | 822 // Only known == targets return a Boolean. |
| 811 RawAbstractType* EqualityCompareComp::CompileType() const { | 823 RawAbstractType* EqualityCompareInstr::CompileType() const { |
| 812 if ((receiver_class_id() == kSmiCid) || | 824 if ((receiver_class_id() == kSmiCid) || |
| 813 (receiver_class_id() == kDoubleCid) || | 825 (receiver_class_id() == kDoubleCid) || |
| 814 (receiver_class_id() == kNumberCid)) { | 826 (receiver_class_id() == kNumberCid)) { |
| 815 return Type::BoolType(); | 827 return Type::BoolType(); |
| 816 } | 828 } |
| 817 return Type::DynamicType(); | 829 return Type::DynamicType(); |
| 818 } | 830 } |
| 819 | 831 |
| 820 | 832 |
| 821 intptr_t EqualityCompareComp::ResultCid() const { | 833 intptr_t EqualityCompareInstr::ResultCid() const { |
| 822 if ((receiver_class_id() == kSmiCid) || | 834 if ((receiver_class_id() == kSmiCid) || |
| 823 (receiver_class_id() == kDoubleCid) || | 835 (receiver_class_id() == kDoubleCid) || |
| 824 (receiver_class_id() == kNumberCid)) { | 836 (receiver_class_id() == kNumberCid)) { |
| 825 // Known/library equalities that are guaranteed to return Boolean. | 837 // Known/library equalities that are guaranteed to return Boolean. |
| 826 return kBoolCid; | 838 return kBoolCid; |
| 827 } | 839 } |
| 828 return kDynamicCid; | 840 return kDynamicCid; |
| 829 } | 841 } |
| 830 | 842 |
| 831 | 843 |
| 832 RawAbstractType* RelationalOpComp::CompileType() const { | 844 RawAbstractType* RelationalOpInstr::CompileType() const { |
| 833 if ((operands_class_id() == kSmiCid) || | 845 if ((operands_class_id() == kSmiCid) || |
| 834 (operands_class_id() == kDoubleCid) || | 846 (operands_class_id() == kDoubleCid) || |
| 835 (operands_class_id() == kNumberCid)) { | 847 (operands_class_id() == kNumberCid)) { |
| 836 // Known/library relational ops that are guaranteed to return Boolean. | 848 // Known/library relational ops that are guaranteed to return Boolean. |
| 837 return Type::BoolType(); | 849 return Type::BoolType(); |
| 838 } | 850 } |
| 839 return Type::DynamicType(); | 851 return Type::DynamicType(); |
| 840 } | 852 } |
| 841 | 853 |
| 842 | 854 |
| 843 intptr_t RelationalOpComp::ResultCid() const { | 855 intptr_t RelationalOpInstr::ResultCid() const { |
| 844 if ((operands_class_id() == kSmiCid) || | 856 if ((operands_class_id() == kSmiCid) || |
| 845 (operands_class_id() == kDoubleCid) || | 857 (operands_class_id() == kDoubleCid) || |
| 846 (operands_class_id() == kNumberCid)) { | 858 (operands_class_id() == kNumberCid)) { |
| 847 // Known/library relational ops that are guaranteed to return Boolean. | 859 // Known/library relational ops that are guaranteed to return Boolean. |
| 848 return kBoolCid; | 860 return kBoolCid; |
| 849 } | 861 } |
| 850 return kDynamicCid; | 862 return kDynamicCid; |
| 851 } | 863 } |
| 852 | 864 |
| 853 | 865 |
| 854 RawAbstractType* NativeCallComp::CompileType() const { | 866 RawAbstractType* NativeCallInstr::CompileType() const { |
| 855 // The result type of the native function is identical to the result type of | 867 // The result type of the native function is identical to the result type of |
| 856 // the enclosing native Dart function. However, we prefer to check the type | 868 // the enclosing native Dart function. However, we prefer to check the type |
| 857 // of the value returned from the native call. | 869 // of the value returned from the native call. |
| 858 return Type::DynamicType(); | 870 return Type::DynamicType(); |
| 859 } | 871 } |
| 860 | 872 |
| 861 | 873 |
| 862 RawAbstractType* LoadIndexedComp::CompileType() const { | 874 RawAbstractType* LoadIndexedInstr::CompileType() const { |
| 863 return Type::DynamicType(); | 875 return Type::DynamicType(); |
| 864 } | 876 } |
| 865 | 877 |
| 866 | 878 |
| 867 RawAbstractType* StoreIndexedComp::CompileType() const { | 879 RawAbstractType* StoreIndexedInstr::CompileType() const { |
| 868 return AbstractType::null(); | 880 return AbstractType::null(); |
| 869 } | 881 } |
| 870 | 882 |
| 871 | 883 |
| 872 RawAbstractType* LoadInstanceFieldComp::CompileType() const { | 884 RawAbstractType* LoadInstanceFieldInstr::CompileType() const { |
| 873 if (FLAG_enable_type_checks) { | 885 if (FLAG_enable_type_checks) { |
| 874 return field().type(); | 886 return field().type(); |
| 875 } | 887 } |
| 876 return Type::DynamicType(); | 888 return Type::DynamicType(); |
| 877 } | 889 } |
| 878 | 890 |
| 879 | 891 |
| 880 RawAbstractType* StoreInstanceFieldComp::CompileType() const { | 892 RawAbstractType* StoreInstanceFieldInstr::CompileType() const { |
| 881 return value()->CompileType(); | 893 return value()->CompileType(); |
| 882 } | 894 } |
| 883 | 895 |
| 884 | 896 |
| 885 RawAbstractType* LoadStaticFieldComp::CompileType() const { | 897 RawAbstractType* LoadStaticFieldInstr::CompileType() const { |
| 886 if (FLAG_enable_type_checks) { | 898 if (FLAG_enable_type_checks) { |
| 887 return field().type(); | 899 return field().type(); |
| 888 } | 900 } |
| 889 return Type::DynamicType(); | 901 return Type::DynamicType(); |
| 890 } | 902 } |
| 891 | 903 |
| 892 | 904 |
| 893 RawAbstractType* StoreStaticFieldComp::CompileType() const { | 905 RawAbstractType* StoreStaticFieldInstr::CompileType() const { |
| 894 return value()->CompileType(); | 906 return value()->CompileType(); |
| 895 } | 907 } |
| 896 | 908 |
| 897 | 909 |
| 898 RawAbstractType* BooleanNegateComp::CompileType() const { | 910 RawAbstractType* BooleanNegateInstr::CompileType() const { |
| 899 return Type::BoolType(); | 911 return Type::BoolType(); |
| 900 } | 912 } |
| 901 | 913 |
| 902 | 914 |
| 903 RawAbstractType* InstanceOfComp::CompileType() const { | 915 RawAbstractType* InstanceOfInstr::CompileType() const { |
| 904 return Type::BoolType(); | 916 return Type::BoolType(); |
| 905 } | 917 } |
| 906 | 918 |
| 907 | 919 |
| 908 RawAbstractType* CreateArrayComp::CompileType() const { | 920 RawAbstractType* CreateArrayInstr::CompileType() const { |
| 909 return type().raw(); | 921 return type().raw(); |
| 910 } | 922 } |
| 911 | 923 |
| 912 | 924 |
| 913 RawAbstractType* CreateClosureComp::CompileType() const { | 925 RawAbstractType* CreateClosureInstr::CompileType() const { |
| 914 const Function& fun = function(); | 926 const Function& fun = function(); |
| 915 const Class& signature_class = Class::Handle(fun.signature_class()); | 927 const Class& signature_class = Class::Handle(fun.signature_class()); |
| 916 return signature_class.SignatureType(); | 928 return signature_class.SignatureType(); |
| 917 } | 929 } |
| 918 | 930 |
| 919 | 931 |
| 920 RawAbstractType* AllocateObjectComp::CompileType() const { | 932 RawAbstractType* AllocateObjectInstr::CompileType() const { |
| 921 // TODO(regis): Be more specific. | 933 // TODO(regis): Be more specific. |
| 922 return Type::DynamicType(); | 934 return Type::DynamicType(); |
| 923 } | 935 } |
| 924 | 936 |
| 925 | 937 |
| 926 RawAbstractType* AllocateObjectWithBoundsCheckComp::CompileType() const { | 938 RawAbstractType* AllocateObjectWithBoundsCheckInstr::CompileType() const { |
| 927 // TODO(regis): Be more specific. | 939 // TODO(regis): Be more specific. |
| 928 return Type::DynamicType(); | 940 return Type::DynamicType(); |
| 929 } | 941 } |
| 930 | 942 |
| 931 | 943 |
| 932 RawAbstractType* LoadVMFieldComp::CompileType() const { | 944 RawAbstractType* LoadVMFieldInstr::CompileType() const { |
| 933 // Type may be null if the field is a VM field, e.g. context parent. | 945 // Type may be null if the field is a VM field, e.g. context parent. |
| 934 // Keep it as null for debug purposes and do not return Dynamic in production | 946 // Keep it as null for debug purposes and do not return Dynamic in production |
| 935 // mode, since misuse of the type would remain undetected. | 947 // mode, since misuse of the type would remain undetected. |
| 936 if (type().IsNull()) { | 948 if (type().IsNull()) { |
| 937 return AbstractType::null(); | 949 return AbstractType::null(); |
| 938 } | 950 } |
| 939 if (FLAG_enable_type_checks) { | 951 if (FLAG_enable_type_checks) { |
| 940 return type().raw(); | 952 return type().raw(); |
| 941 } | 953 } |
| 942 return Type::DynamicType(); | 954 return Type::DynamicType(); |
| 943 } | 955 } |
| 944 | 956 |
| 945 | 957 |
| 946 RawAbstractType* StoreVMFieldComp::CompileType() const { | 958 RawAbstractType* StoreVMFieldInstr::CompileType() const { |
| 947 return value()->CompileType(); | 959 return value()->CompileType(); |
| 948 } | 960 } |
| 949 | 961 |
| 950 | 962 |
| 951 RawAbstractType* InstantiateTypeArgumentsComp::CompileType() const { | 963 RawAbstractType* InstantiateTypeArgumentsInstr::CompileType() const { |
| 952 return AbstractType::null(); | 964 return AbstractType::null(); |
| 953 } | 965 } |
| 954 | 966 |
| 955 | 967 |
| 956 RawAbstractType* ExtractConstructorTypeArgumentsComp::CompileType() const { | 968 RawAbstractType* ExtractConstructorTypeArgumentsInstr::CompileType() const { |
| 957 return AbstractType::null(); | 969 return AbstractType::null(); |
| 958 } | 970 } |
| 959 | 971 |
| 960 | 972 |
| 961 RawAbstractType* ExtractConstructorInstantiatorComp::CompileType() const { | 973 RawAbstractType* ExtractConstructorInstantiatorInstr::CompileType() const { |
| 962 return AbstractType::null(); | 974 return AbstractType::null(); |
| 963 } | 975 } |
| 964 | 976 |
| 965 | 977 |
| 966 RawAbstractType* AllocateContextComp::CompileType() const { | 978 RawAbstractType* AllocateContextInstr::CompileType() const { |
| 967 return AbstractType::null(); | 979 return AbstractType::null(); |
| 968 } | 980 } |
| 969 | 981 |
| 970 | 982 |
| 971 RawAbstractType* ChainContextComp::CompileType() const { | 983 RawAbstractType* ChainContextInstr::CompileType() const { |
| 972 return AbstractType::null(); | 984 return AbstractType::null(); |
| 973 } | 985 } |
| 974 | 986 |
| 975 | 987 |
| 976 RawAbstractType* CloneContextComp::CompileType() const { | 988 RawAbstractType* CloneContextInstr::CompileType() const { |
| 977 return AbstractType::null(); | 989 return AbstractType::null(); |
| 978 } | 990 } |
| 979 | 991 |
| 980 | 992 |
| 981 RawAbstractType* CatchEntryComp::CompileType() const { | 993 RawAbstractType* CatchEntryInstr::CompileType() const { |
| 982 return AbstractType::null(); | 994 return AbstractType::null(); |
| 983 } | 995 } |
| 984 | 996 |
| 985 | 997 |
| 986 RawAbstractType* CheckStackOverflowComp::CompileType() const { | 998 RawAbstractType* CheckStackOverflowInstr::CompileType() const { |
| 987 return AbstractType::null(); | 999 return AbstractType::null(); |
| 988 } | 1000 } |
| 989 | 1001 |
| 990 | 1002 |
| 991 RawAbstractType* BinarySmiOpComp::CompileType() const { | 1003 RawAbstractType* BinarySmiOpInstr::CompileType() const { |
| 992 return (op_kind() == Token::kSHL) ? Type::IntInterface() : Type::SmiType(); | 1004 return (op_kind() == Token::kSHL) ? Type::IntInterface() : Type::SmiType(); |
| 993 } | 1005 } |
| 994 | 1006 |
| 995 | 1007 |
| 996 intptr_t BinarySmiOpComp::ResultCid() const { | 1008 intptr_t BinarySmiOpInstr::ResultCid() const { |
| 997 return (op_kind() == Token::kSHL) ? kDynamicCid : kSmiCid; | 1009 return (op_kind() == Token::kSHL) ? kDynamicCid : kSmiCid; |
| 998 } | 1010 } |
| 999 | 1011 |
| 1000 | 1012 |
| 1001 bool BinarySmiOpComp::CanDeoptimize() const { | 1013 bool BinarySmiOpInstr::CanDeoptimize() const { |
| 1002 switch (op_kind()) { | 1014 switch (op_kind()) { |
| 1003 case Token::kBIT_AND: | 1015 case Token::kBIT_AND: |
| 1004 case Token::kBIT_OR: | 1016 case Token::kBIT_OR: |
| 1005 case Token::kBIT_XOR: | 1017 case Token::kBIT_XOR: |
| 1006 return false; | 1018 return false; |
| 1007 default: | 1019 default: |
| 1008 return true; | 1020 return true; |
| 1009 } | 1021 } |
| 1010 } | 1022 } |
| 1011 | 1023 |
| 1012 | 1024 |
| 1013 RawAbstractType* BinaryMintOpComp::CompileType() const { | 1025 RawAbstractType* BinaryMintOpInstr::CompileType() const { |
| 1014 return Type::MintType(); | 1026 return Type::MintType(); |
| 1015 } | 1027 } |
| 1016 | 1028 |
| 1017 | 1029 |
| 1018 intptr_t BinaryMintOpComp::ResultCid() const { | 1030 intptr_t BinaryMintOpInstr::ResultCid() const { |
| 1019 return kMintCid; | 1031 return kMintCid; |
| 1020 } | 1032 } |
| 1021 | 1033 |
| 1022 | 1034 |
| 1023 RawAbstractType* UnboxedDoubleBinaryOpComp::CompileType() const { | 1035 RawAbstractType* UnboxedDoubleBinaryOpInstr::CompileType() const { |
| 1024 return Type::Double(); | 1036 return Type::Double(); |
| 1025 } | 1037 } |
| 1026 | 1038 |
| 1027 | 1039 |
| 1028 RawAbstractType* UnboxDoubleComp::CompileType() const { | 1040 RawAbstractType* UnboxDoubleInstr::CompileType() const { |
| 1029 return Type::null(); | 1041 return Type::null(); |
| 1030 } | 1042 } |
| 1031 | 1043 |
| 1032 | 1044 |
| 1033 intptr_t BoxDoubleComp::ResultCid() const { | 1045 intptr_t BoxDoubleInstr::ResultCid() const { |
| 1034 return kDoubleCid; | 1046 return kDoubleCid; |
| 1035 } | 1047 } |
| 1036 | 1048 |
| 1037 | 1049 |
| 1038 RawAbstractType* BoxDoubleComp::CompileType() const { | 1050 RawAbstractType* BoxDoubleInstr::CompileType() const { |
| 1039 return Type::Double(); | 1051 return Type::Double(); |
| 1040 } | 1052 } |
| 1041 | 1053 |
| 1042 | 1054 |
| 1043 RawAbstractType* UnarySmiOpComp::CompileType() const { | 1055 RawAbstractType* UnarySmiOpInstr::CompileType() const { |
| 1044 return Type::SmiType(); | 1056 return Type::SmiType(); |
| 1045 } | 1057 } |
| 1046 | 1058 |
| 1047 | 1059 |
| 1048 RawAbstractType* NumberNegateComp::CompileType() const { | 1060 RawAbstractType* NumberNegateInstr::CompileType() const { |
| 1049 // Implemented only for doubles. | 1061 // Implemented only for doubles. |
| 1050 return Type::Double(); | 1062 return Type::Double(); |
| 1051 } | 1063 } |
| 1052 | 1064 |
| 1053 | 1065 |
| 1054 RawAbstractType* DoubleToDoubleComp::CompileType() const { | 1066 RawAbstractType* DoubleToDoubleInstr::CompileType() const { |
| 1055 return Type::Double(); | 1067 return Type::Double(); |
| 1056 } | 1068 } |
| 1057 | 1069 |
| 1058 | 1070 |
| 1059 RawAbstractType* SmiToDoubleComp::CompileType() const { | 1071 RawAbstractType* SmiToDoubleInstr::CompileType() const { |
| 1060 return Type::Double(); | 1072 return Type::Double(); |
| 1061 } | 1073 } |
| 1062 | 1074 |
| 1063 | 1075 |
| 1064 RawAbstractType* CheckClassComp::CompileType() const { | 1076 RawAbstractType* CheckClassInstr::CompileType() const { |
| 1065 return AbstractType::null(); | 1077 return AbstractType::null(); |
| 1066 } | 1078 } |
| 1067 | 1079 |
| 1068 | 1080 |
| 1069 RawAbstractType* CheckSmiComp::CompileType() const { | 1081 RawAbstractType* CheckSmiInstr::CompileType() const { |
| 1070 return AbstractType::null(); | 1082 return AbstractType::null(); |
| 1071 } | 1083 } |
| 1072 | 1084 |
| 1073 | 1085 |
| 1074 RawAbstractType* CheckArrayBoundComp::CompileType() const { | 1086 RawAbstractType* CheckArrayBoundInstr::CompileType() const { |
| 1075 return AbstractType::null(); | 1087 return AbstractType::null(); |
| 1076 } | 1088 } |
| 1077 | 1089 |
| 1078 | 1090 |
| 1079 RawAbstractType* CheckEitherNonSmiComp::CompileType() const { | 1091 RawAbstractType* CheckEitherNonSmiInstr::CompileType() const { |
| 1080 return AbstractType::null(); | 1092 return AbstractType::null(); |
| 1081 } | 1093 } |
| 1082 | 1094 |
| 1083 | 1095 |
| 1084 // Optimizations that eliminate or simplify individual computations. | 1096 // Optimizations that eliminate or simplify individual computations. |
| 1085 Definition* Computation::TryReplace(BindInstr* instr) const { | 1097 Definition* Definition::Canonicalize() { |
| 1086 return instr; | 1098 return this; |
| 1087 } | 1099 } |
| 1088 | 1100 |
| 1089 | 1101 |
| 1090 Definition* StrictCompareComp::TryReplace(BindInstr* instr) const { | 1102 Definition* StrictCompareInstr::Canonicalize() { |
| 1091 if (!right()->BindsToConstant()) return instr; | 1103 if (!right()->BindsToConstant()) return this; |
| 1092 const Object& right_constant = right()->BoundConstant(); | 1104 const Object& right_constant = right()->BoundConstant(); |
| 1093 Definition* left_defn = left()->definition(); | 1105 Definition* left_defn = left()->definition(); |
| 1094 // TODO(fschneider): Handle other cases: e === false and e !== true/false. | 1106 // TODO(fschneider): Handle other cases: e === false and e !== true/false. |
| 1095 // Handles e === true. | 1107 // Handles e === true. |
| 1096 if ((kind() == Token::kEQ_STRICT) && | 1108 if ((kind() == Token::kEQ_STRICT) && |
| 1097 (right_constant.raw() == Bool::True()) && | 1109 (right_constant.raw() == Bool::True()) && |
| 1098 (left()->ResultCid() == kBoolCid)) { | 1110 (left()->ResultCid() == kBoolCid)) { |
| 1099 // Remove the constant from the graph. | 1111 // Remove the constant from the graph. |
| 1100 BindInstr* right_defn = right()->definition()->AsBind(); | 1112 Definition* right_defn = right()->definition(); |
| 1101 if (right_defn != NULL) { | 1113 right_defn->RemoveFromGraph(); |
| 1102 right_defn->RemoveFromGraph(); | |
| 1103 } | |
| 1104 // Return left subexpression as the replacement for this instruction. | 1114 // Return left subexpression as the replacement for this instruction. |
| 1105 return left_defn; | 1115 return left_defn; |
| 1106 } | 1116 } |
| 1107 return instr; | 1117 return this; |
| 1108 } | 1118 } |
| 1109 | 1119 |
| 1110 | 1120 |
| 1111 Definition* CheckClassComp::TryReplace(BindInstr* instr) const { | 1121 Definition* CheckClassInstr::Canonicalize() { |
| 1112 const intptr_t v_cid = value()->ResultCid(); | 1122 const intptr_t v_cid = value()->ResultCid(); |
| 1113 const intptr_t num_checks = unary_checks().NumberOfChecks(); | 1123 const intptr_t num_checks = unary_checks().NumberOfChecks(); |
| 1114 if ((num_checks == 1) && | 1124 if ((num_checks == 1) && |
| 1115 (v_cid == unary_checks().GetReceiverClassIdAt(0))) { | 1125 (v_cid == unary_checks().GetReceiverClassIdAt(0))) { |
| 1116 // No checks needed. | 1126 // No checks needed. |
| 1117 return NULL; | 1127 return NULL; |
| 1118 } | 1128 } |
| 1119 return instr; | 1129 return this; |
| 1120 } | 1130 } |
| 1121 | 1131 |
| 1122 | 1132 |
| 1123 Definition* CheckSmiComp::TryReplace(BindInstr* instr) const { | 1133 Definition* CheckSmiInstr::Canonicalize() { |
| 1124 return (value()->ResultCid() == kSmiCid) ? NULL : instr; | 1134 return (value()->ResultCid() == kSmiCid) ? NULL : this; |
| 1125 } | 1135 } |
| 1126 | 1136 |
| 1127 | 1137 |
| 1128 Definition* CheckEitherNonSmiComp::TryReplace(BindInstr* instr) const { | 1138 Definition* CheckEitherNonSmiInstr::Canonicalize() { |
| 1129 if ((left()->ResultCid() == kDoubleCid) || | 1139 if ((left()->ResultCid() == kDoubleCid) || |
| 1130 (right()->ResultCid() == kDoubleCid)) { | 1140 (right()->ResultCid() == kDoubleCid)) { |
| 1131 return NULL; // Remove from the graph. | 1141 return NULL; // Remove from the graph. |
| 1132 } | 1142 } |
| 1133 return instr; | 1143 return this; |
| 1134 } | 1144 } |
| 1135 | 1145 |
| 1136 | 1146 |
| 1137 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and | 1147 // Shared code generation methods (EmitNativeCode, MakeLocationSummary, and |
| 1138 // PrepareEntry). Only assembly code that can be shared across all architectures | 1148 // PrepareEntry). Only assembly code that can be shared across all architectures |
| 1139 // can be used. Machine specific register allocation and code generation | 1149 // can be used. Machine specific register allocation and code generation |
| 1140 // is located in intermediate_language_<arch>.cc | 1150 // is located in intermediate_language_<arch>.cc |
| 1141 | 1151 |
| 1142 #define __ compiler->assembler()-> | 1152 #define __ compiler->assembler()-> |
| 1143 | 1153 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1159 if (IsCatchEntry()) { | 1169 if (IsCatchEntry()) { |
| 1160 compiler->AddExceptionHandler(catch_try_index(), | 1170 compiler->AddExceptionHandler(catch_try_index(), |
| 1161 compiler->assembler()->CodeSize()); | 1171 compiler->assembler()->CodeSize()); |
| 1162 } | 1172 } |
| 1163 if (HasParallelMove()) { | 1173 if (HasParallelMove()) { |
| 1164 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 1174 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 1165 } | 1175 } |
| 1166 } | 1176 } |
| 1167 | 1177 |
| 1168 | 1178 |
| 1179 LocationSummary* GraphEntryInstr::MakeLocationSummary() const { |
| 1180 UNREACHABLE(); |
| 1181 return NULL; |
| 1182 } |
| 1183 |
| 1184 |
| 1185 void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1186 UNREACHABLE(); |
| 1187 } |
| 1188 |
| 1189 |
| 1190 LocationSummary* JoinEntryInstr::MakeLocationSummary() const { |
| 1191 UNREACHABLE(); |
| 1192 return NULL; |
| 1193 } |
| 1194 |
| 1195 |
| 1196 void JoinEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1197 UNREACHABLE(); |
| 1198 } |
| 1199 |
| 1200 |
| 1201 LocationSummary* TargetEntryInstr::MakeLocationSummary() const { |
| 1202 UNREACHABLE(); |
| 1203 return NULL; |
| 1204 } |
| 1205 |
| 1206 |
| 1207 void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1208 UNREACHABLE(); |
| 1209 } |
| 1210 |
| 1211 |
| 1212 LocationSummary* PhiInstr::MakeLocationSummary() const { |
| 1213 UNREACHABLE(); |
| 1214 return NULL; |
| 1215 } |
| 1216 |
| 1217 |
| 1218 void PhiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1219 UNREACHABLE(); |
| 1220 } |
| 1221 |
| 1222 |
| 1223 LocationSummary* ParameterInstr::MakeLocationSummary() const { |
| 1224 UNREACHABLE(); |
| 1225 return NULL; |
| 1226 } |
| 1227 |
| 1228 |
| 1229 void ParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1230 UNREACHABLE(); |
| 1231 } |
| 1232 |
| 1233 |
| 1234 LocationSummary* ParallelMoveInstr::MakeLocationSummary() const { |
| 1235 return NULL; |
| 1236 } |
| 1237 |
| 1238 |
| 1239 void ParallelMoveInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1240 UNREACHABLE(); |
| 1241 } |
| 1242 |
| 1243 |
| 1169 LocationSummary* ThrowInstr::MakeLocationSummary() const { | 1244 LocationSummary* ThrowInstr::MakeLocationSummary() const { |
| 1170 return new LocationSummary(0, 0, LocationSummary::kCall); | 1245 return new LocationSummary(0, 0, LocationSummary::kCall); |
| 1171 } | 1246 } |
| 1172 | 1247 |
| 1173 | 1248 |
| 1174 | 1249 |
| 1175 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1250 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1176 compiler->GenerateCallRuntime(token_pos(), | 1251 compiler->GenerateCallRuntime(token_pos(), |
| 1177 kThrowRuntimeEntry, | 1252 kThrowRuntimeEntry, |
| 1178 locs()); | 1253 locs()); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 } else { | 1314 } else { |
| 1240 // If the next block is the true successor we negate comparison and fall | 1315 // If the next block is the true successor we negate comparison and fall |
| 1241 // through to it. | 1316 // through to it. |
| 1242 ASSERT(compiler->IsNextBlock(true_successor())); | 1317 ASSERT(compiler->IsNextBlock(true_successor())); |
| 1243 Condition false_condition = NegateCondition(true_condition); | 1318 Condition false_condition = NegateCondition(true_condition); |
| 1244 __ j(false_condition, compiler->GetBlockLabel(false_successor())); | 1319 __ j(false_condition, compiler->GetBlockLabel(false_successor())); |
| 1245 } | 1320 } |
| 1246 } | 1321 } |
| 1247 | 1322 |
| 1248 | 1323 |
| 1249 LocationSummary* CurrentContextComp::MakeLocationSummary() const { | 1324 LocationSummary* CurrentContextInstr::MakeLocationSummary() const { |
| 1250 return LocationSummary::Make(0, | 1325 return LocationSummary::Make(0, |
| 1251 Location::RequiresRegister(), | 1326 Location::RequiresRegister(), |
| 1252 LocationSummary::kNoCall); | 1327 LocationSummary::kNoCall); |
| 1253 } | 1328 } |
| 1254 | 1329 |
| 1255 | 1330 |
| 1256 void CurrentContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1331 void CurrentContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1257 __ MoveRegister(locs()->out().reg(), CTX); | 1332 __ MoveRegister(locs()->out().reg(), CTX); |
| 1258 } | 1333 } |
| 1259 | 1334 |
| 1260 | 1335 |
| 1261 LocationSummary* StoreContextComp::MakeLocationSummary() const { | 1336 LocationSummary* StoreContextInstr::MakeLocationSummary() const { |
| 1262 const intptr_t kNumInputs = 1; | 1337 const intptr_t kNumInputs = 1; |
| 1263 const intptr_t kNumTemps = 0; | 1338 const intptr_t kNumTemps = 0; |
| 1264 LocationSummary* summary = | 1339 LocationSummary* summary = |
| 1265 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1340 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1266 summary->set_in(0, Location::RegisterLocation(CTX)); | 1341 summary->set_in(0, Location::RegisterLocation(CTX)); |
| 1267 return summary; | 1342 return summary; |
| 1268 } | 1343 } |
| 1269 | 1344 |
| 1270 | 1345 |
| 1271 void StoreContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1346 void StoreContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1272 // Nothing to do. Context register were loaded by register allocator. | 1347 // Nothing to do. Context register were loaded by register allocator. |
| 1273 ASSERT(locs()->in(0).reg() == CTX); | 1348 ASSERT(locs()->in(0).reg() == CTX); |
| 1274 } | 1349 } |
| 1275 | 1350 |
| 1276 | 1351 |
| 1277 LocationSummary* StrictCompareComp::MakeLocationSummary() const { | 1352 LocationSummary* StrictCompareInstr::MakeLocationSummary() const { |
| 1278 return LocationSummary::Make(2, | 1353 return LocationSummary::Make(2, |
| 1279 Location::SameAsFirstInput(), | 1354 Location::SameAsFirstInput(), |
| 1280 LocationSummary::kNoCall); | 1355 LocationSummary::kNoCall); |
| 1281 } | 1356 } |
| 1282 | 1357 |
| 1283 | 1358 |
| 1284 void StrictCompareComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1359 void StrictCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1285 Register left = locs()->in(0).reg(); | 1360 Register left = locs()->in(0).reg(); |
| 1286 Register right = locs()->in(1).reg(); | 1361 Register right = locs()->in(1).reg(); |
| 1287 | 1362 |
| 1288 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 1363 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 1289 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 1364 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 1290 __ CompareRegisters(left, right); | 1365 __ CompareRegisters(left, right); |
| 1291 | 1366 |
| 1292 Register result = locs()->out().reg(); | 1367 Register result = locs()->out().reg(); |
| 1293 Label load_true, done; | 1368 Label load_true, done; |
| 1294 __ j(true_condition, &load_true, Assembler::kNearJump); | 1369 __ j(true_condition, &load_true, Assembler::kNearJump); |
| 1295 __ LoadObject(result, compiler->bool_false()); | 1370 __ LoadObject(result, compiler->bool_false()); |
| 1296 __ jmp(&done, Assembler::kNearJump); | 1371 __ jmp(&done, Assembler::kNearJump); |
| 1297 __ Bind(&load_true); | 1372 __ Bind(&load_true); |
| 1298 __ LoadObject(result, compiler->bool_true()); | 1373 __ LoadObject(result, compiler->bool_true()); |
| 1299 __ Bind(&done); | 1374 __ Bind(&done); |
| 1300 } | 1375 } |
| 1301 | 1376 |
| 1302 | 1377 |
| 1303 void StrictCompareComp::EmitBranchCode(FlowGraphCompiler* compiler, | 1378 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 1304 BranchInstr* branch) { | 1379 BranchInstr* branch) { |
| 1305 Register left = locs()->in(0).reg(); | 1380 Register left = locs()->in(0).reg(); |
| 1306 Register right = locs()->in(1).reg(); | 1381 Register right = locs()->in(1).reg(); |
| 1307 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 1382 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 1308 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; | 1383 Condition true_condition = (kind() == Token::kEQ_STRICT) ? EQUAL : NOT_EQUAL; |
| 1309 __ CompareRegisters(left, right); | 1384 __ CompareRegisters(left, right); |
| 1310 branch->EmitBranchOnCondition(compiler, true_condition); | 1385 branch->EmitBranchOnCondition(compiler, true_condition); |
| 1311 } | 1386 } |
| 1312 | 1387 |
| 1313 | 1388 |
| 1314 void ClosureCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1389 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1315 // The arguments to the stub include the closure. The arguments | 1390 // The arguments to the stub include the closure. The arguments |
| 1316 // descriptor describes the closure's arguments (and so does not include | 1391 // descriptor describes the closure's arguments (and so does not include |
| 1317 // the closure). | 1392 // the closure). |
| 1318 Register temp_reg = locs()->temp(0).reg(); | 1393 Register temp_reg = locs()->temp(0).reg(); |
| 1319 int argument_count = ArgumentCount(); | 1394 int argument_count = ArgumentCount(); |
| 1320 const Array& arguments_descriptor = | 1395 const Array& arguments_descriptor = |
| 1321 DartEntry::ArgumentsDescriptor(argument_count - 1, | 1396 DartEntry::ArgumentsDescriptor(argument_count - 1, |
| 1322 argument_names()); | 1397 argument_names()); |
| 1323 __ LoadObject(temp_reg, arguments_descriptor); | 1398 __ LoadObject(temp_reg, arguments_descriptor); |
| 1324 compiler->GenerateDartCall(deopt_id(), | 1399 compiler->GenerateDartCall(deopt_id(), |
| 1325 token_pos(), | 1400 token_pos(), |
| 1326 &StubCode::CallClosureFunctionLabel(), | 1401 &StubCode::CallClosureFunctionLabel(), |
| 1327 PcDescriptors::kOther, | 1402 PcDescriptors::kOther, |
| 1328 locs()); | 1403 locs()); |
| 1329 __ Drop(argument_count); | 1404 __ Drop(argument_count); |
| 1330 } | 1405 } |
| 1331 | 1406 |
| 1332 | 1407 |
| 1333 LocationSummary* InstanceCallComp::MakeLocationSummary() const { | 1408 LocationSummary* InstanceCallInstr::MakeLocationSummary() const { |
| 1334 return MakeCallSummary(); | 1409 return MakeCallSummary(); |
| 1335 } | 1410 } |
| 1336 | 1411 |
| 1337 | 1412 |
| 1338 void InstanceCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1413 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1339 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, | 1414 compiler->AddCurrentDescriptor(PcDescriptors::kDeoptBefore, |
| 1340 deopt_id(), | 1415 deopt_id(), |
| 1341 token_pos()); | 1416 token_pos()); |
| 1342 compiler->GenerateInstanceCall(deopt_id(), | 1417 compiler->GenerateInstanceCall(deopt_id(), |
| 1343 token_pos(), | 1418 token_pos(), |
| 1344 function_name(), | 1419 function_name(), |
| 1345 ArgumentCount(), | 1420 ArgumentCount(), |
| 1346 argument_names(), | 1421 argument_names(), |
| 1347 checked_argument_count(), | 1422 checked_argument_count(), |
| 1348 locs()); | 1423 locs()); |
| 1349 } | 1424 } |
| 1350 | 1425 |
| 1351 | 1426 |
| 1352 LocationSummary* StaticCallComp::MakeLocationSummary() const { | 1427 LocationSummary* StaticCallInstr::MakeLocationSummary() const { |
| 1353 return MakeCallSummary(); | 1428 return MakeCallSummary(); |
| 1354 } | 1429 } |
| 1355 | 1430 |
| 1356 | 1431 |
| 1357 void StaticCallComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1432 void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1358 Label done; | 1433 Label done; |
| 1359 if (recognized() == MethodRecognizer::kMathSqrt) { | 1434 if (recognized() == MethodRecognizer::kMathSqrt) { |
| 1360 compiler->GenerateInlinedMathSqrt(&done); | 1435 compiler->GenerateInlinedMathSqrt(&done); |
| 1361 // Falls through to static call when operand type is not double or smi. | 1436 // Falls through to static call when operand type is not double or smi. |
| 1362 } | 1437 } |
| 1363 compiler->GenerateStaticCall(deopt_id(), | 1438 compiler->GenerateStaticCall(deopt_id(), |
| 1364 token_pos(), | 1439 token_pos(), |
| 1365 function(), | 1440 function(), |
| 1366 ArgumentCount(), | 1441 ArgumentCount(), |
| 1367 argument_names(), | 1442 argument_names(), |
| 1368 locs()); | 1443 locs()); |
| 1369 __ Bind(&done); | 1444 __ Bind(&done); |
| 1370 } | 1445 } |
| 1371 | 1446 |
| 1372 | 1447 |
| 1373 void AssertAssignableComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1448 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1374 if (!is_eliminated()) { | 1449 if (!is_eliminated()) { |
| 1375 compiler->GenerateAssertAssignable(token_pos(), | 1450 compiler->GenerateAssertAssignable(token_pos(), |
| 1376 dst_type(), | 1451 dst_type(), |
| 1377 dst_name(), | 1452 dst_name(), |
| 1378 locs()); | 1453 locs()); |
| 1379 } | 1454 } |
| 1380 ASSERT(locs()->in(0).reg() == locs()->out().reg()); | 1455 ASSERT(locs()->in(0).reg() == locs()->out().reg()); |
| 1381 } | 1456 } |
| 1382 | 1457 |
| 1383 | 1458 |
| 1384 LocationSummary* BooleanNegateComp::MakeLocationSummary() const { | 1459 LocationSummary* BooleanNegateInstr::MakeLocationSummary() const { |
| 1385 return LocationSummary::Make(1, | 1460 return LocationSummary::Make(1, |
| 1386 Location::RequiresRegister(), | 1461 Location::RequiresRegister(), |
| 1387 LocationSummary::kNoCall); | 1462 LocationSummary::kNoCall); |
| 1388 } | 1463 } |
| 1389 | 1464 |
| 1390 | 1465 |
| 1391 void BooleanNegateComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1466 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1392 Register value = locs()->in(0).reg(); | 1467 Register value = locs()->in(0).reg(); |
| 1393 Register result = locs()->out().reg(); | 1468 Register result = locs()->out().reg(); |
| 1394 | 1469 |
| 1395 Label done; | 1470 Label done; |
| 1396 __ LoadObject(result, compiler->bool_true()); | 1471 __ LoadObject(result, compiler->bool_true()); |
| 1397 __ CompareRegisters(result, value); | 1472 __ CompareRegisters(result, value); |
| 1398 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1473 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1399 __ LoadObject(result, compiler->bool_false()); | 1474 __ LoadObject(result, compiler->bool_false()); |
| 1400 __ Bind(&done); | 1475 __ Bind(&done); |
| 1401 } | 1476 } |
| 1402 | 1477 |
| 1403 | 1478 |
| 1404 LocationSummary* ChainContextComp::MakeLocationSummary() const { | 1479 LocationSummary* ChainContextInstr::MakeLocationSummary() const { |
| 1405 return LocationSummary::Make(1, | 1480 return LocationSummary::Make(1, |
| 1406 Location::NoLocation(), | 1481 Location::NoLocation(), |
| 1407 LocationSummary::kNoCall); | 1482 LocationSummary::kNoCall); |
| 1408 } | 1483 } |
| 1409 | 1484 |
| 1410 | 1485 |
| 1411 void ChainContextComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1486 void ChainContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1412 Register context_value = locs()->in(0).reg(); | 1487 Register context_value = locs()->in(0).reg(); |
| 1413 | 1488 |
| 1414 // Chain the new context in context_value to its parent in CTX. | 1489 // Chain the new context in context_value to its parent in CTX. |
| 1415 __ StoreIntoObject(context_value, | 1490 __ StoreIntoObject(context_value, |
| 1416 FieldAddress(context_value, Context::parent_offset()), | 1491 FieldAddress(context_value, Context::parent_offset()), |
| 1417 CTX); | 1492 CTX); |
| 1418 // Set new context as current context. | 1493 // Set new context as current context. |
| 1419 __ MoveRegister(CTX, context_value); | 1494 __ MoveRegister(CTX, context_value); |
| 1420 } | 1495 } |
| 1421 | 1496 |
| 1422 | 1497 |
| 1423 LocationSummary* StoreVMFieldComp::MakeLocationSummary() const { | 1498 LocationSummary* StoreVMFieldInstr::MakeLocationSummary() const { |
| 1424 return LocationSummary::Make(2, | 1499 return LocationSummary::Make(2, |
| 1425 Location::SameAsFirstInput(), | 1500 Location::SameAsFirstInput(), |
| 1426 LocationSummary::kNoCall); | 1501 LocationSummary::kNoCall); |
| 1427 } | 1502 } |
| 1428 | 1503 |
| 1429 | 1504 |
| 1430 void StoreVMFieldComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1505 void StoreVMFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1431 Register value_reg = locs()->in(0).reg(); | 1506 Register value_reg = locs()->in(0).reg(); |
| 1432 Register dest_reg = locs()->in(1).reg(); | 1507 Register dest_reg = locs()->in(1).reg(); |
| 1433 ASSERT(value_reg == locs()->out().reg()); | 1508 ASSERT(value_reg == locs()->out().reg()); |
| 1434 | 1509 |
| 1435 if (value()->NeedsStoreBuffer()) { | 1510 if (value()->NeedsStoreBuffer()) { |
| 1436 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), | 1511 __ StoreIntoObject(dest_reg, FieldAddress(dest_reg, offset_in_bytes()), |
| 1437 value_reg); | 1512 value_reg); |
| 1438 } else { | 1513 } else { |
| 1439 __ StoreIntoObjectNoBarrier( | 1514 __ StoreIntoObjectNoBarrier( |
| 1440 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); | 1515 dest_reg, FieldAddress(dest_reg, offset_in_bytes()), value_reg); |
| 1441 } | 1516 } |
| 1442 } | 1517 } |
| 1443 | 1518 |
| 1444 | 1519 |
| 1445 LocationSummary* AllocateObjectComp::MakeLocationSummary() const { | 1520 LocationSummary* AllocateObjectInstr::MakeLocationSummary() const { |
| 1446 return MakeCallSummary(); | 1521 return MakeCallSummary(); |
| 1447 } | 1522 } |
| 1448 | 1523 |
| 1449 | 1524 |
| 1450 void AllocateObjectComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1525 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1451 const Class& cls = Class::ZoneHandle(constructor().Owner()); | 1526 const Class& cls = Class::ZoneHandle(constructor().Owner()); |
| 1452 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 1527 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 1453 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 1528 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 1454 compiler->GenerateCall(token_pos(), | 1529 compiler->GenerateCall(token_pos(), |
| 1455 &label, | 1530 &label, |
| 1456 PcDescriptors::kOther, | 1531 PcDescriptors::kOther, |
| 1457 locs()); | 1532 locs()); |
| 1458 __ Drop(ArgumentCount()); // Discard arguments. | 1533 __ Drop(ArgumentCount()); // Discard arguments. |
| 1459 } | 1534 } |
| 1460 | 1535 |
| 1461 | 1536 |
| 1462 LocationSummary* CreateClosureComp::MakeLocationSummary() const { | 1537 LocationSummary* CreateClosureInstr::MakeLocationSummary() const { |
| 1463 return MakeCallSummary(); | 1538 return MakeCallSummary(); |
| 1464 } | 1539 } |
| 1465 | 1540 |
| 1466 | 1541 |
| 1467 void CreateClosureComp::EmitNativeCode(FlowGraphCompiler* compiler) { | 1542 void CreateClosureInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1468 const Function& closure_function = function(); | 1543 const Function& closure_function = function(); |
| 1469 const Code& stub = Code::Handle( | 1544 const Code& stub = Code::Handle( |
| 1470 StubCode::GetAllocationStubForClosure(closure_function)); | 1545 StubCode::GetAllocationStubForClosure(closure_function)); |
| 1471 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); | 1546 const ExternalLabel label(closure_function.ToCString(), stub.EntryPoint()); |
| 1472 compiler->GenerateCall(token_pos(), | 1547 compiler->GenerateCall(token_pos(), |
| 1473 &label, | 1548 &label, |
| 1474 PcDescriptors::kOther, | 1549 PcDescriptors::kOther, |
| 1475 locs()); | 1550 locs()); |
| 1476 __ Drop(2); // Discard type arguments and receiver. | 1551 __ Drop(2); // Discard type arguments and receiver. |
| 1477 } | 1552 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1522 value->set_use_index(i); | 1597 value->set_use_index(i); |
| 1523 value->AddToEnvUseList(); | 1598 value->AddToEnvUseList(); |
| 1524 } | 1599 } |
| 1525 instr->set_env(copy); | 1600 instr->set_env(copy); |
| 1526 } | 1601 } |
| 1527 | 1602 |
| 1528 | 1603 |
| 1529 #undef __ | 1604 #undef __ |
| 1530 | 1605 |
| 1531 } // namespace dart | 1606 } // namespace dart |
| OLD | NEW |