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