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 |