OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 5122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5133 check->value()->BindTo(phi->InputAt(non_smi_input)->definition()); | 5133 check->value()->BindTo(phi->InputAt(non_smi_input)->definition()); |
5134 | 5134 |
5135 phi->UpdateType(CompileType::FromCid(kSmiCid)); | 5135 phi->UpdateType(CompileType::FromCid(kSmiCid)); |
5136 } | 5136 } |
5137 | 5137 |
5138 | 5138 |
5139 // Load instructions handled by load elimination. | 5139 // Load instructions handled by load elimination. |
5140 static bool IsLoadEliminationCandidate(Instruction* instr) { | 5140 static bool IsLoadEliminationCandidate(Instruction* instr) { |
5141 return instr->IsLoadField() | 5141 return instr->IsLoadField() |
5142 || instr->IsLoadIndexed() | 5142 || instr->IsLoadIndexed() |
5143 || instr->IsLoadStaticField() | 5143 || instr->IsLoadStaticField(); |
5144 || instr->IsCurrentContext(); | |
5145 } | 5144 } |
5146 | 5145 |
5147 | 5146 |
5148 static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets, | 5147 static bool IsLoopInvariantLoad(ZoneGrowableArray<BitVector*>* sets, |
5149 intptr_t loop_header_index, | 5148 intptr_t loop_header_index, |
5150 Instruction* instr) { | 5149 Instruction* instr) { |
5151 return IsLoadEliminationCandidate(instr) && | 5150 return IsLoadEliminationCandidate(instr) && |
5152 (sets != NULL) && | 5151 (sets != NULL) && |
5153 instr->HasPlaceId() && | 5152 instr->HasPlaceId() && |
5154 ((*sets)[loop_header_index] != NULL) && | 5153 ((*sets)[loop_header_index] != NULL) && |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5277 | 5276 |
5278 // VMField location. Represented as a pair of an instance (SSA definition) | 5277 // VMField location. Represented as a pair of an instance (SSA definition) |
5279 // being accessed and offset to the field. | 5278 // being accessed and offset to the field. |
5280 kVMField, | 5279 kVMField, |
5281 | 5280 |
5282 // Indexed location with a non-constant index. | 5281 // Indexed location with a non-constant index. |
5283 kIndexed, | 5282 kIndexed, |
5284 | 5283 |
5285 // Indexed location with a constant index. | 5284 // Indexed location with a constant index. |
5286 kConstantIndexed, | 5285 kConstantIndexed, |
5287 | |
5288 // Current context. | |
5289 kContext | |
5290 }; | 5286 }; |
5291 | 5287 |
5292 Place(const Place& other) | 5288 Place(const Place& other) |
5293 : ValueObject(), | 5289 : ValueObject(), |
5294 kind_(other.kind_), | 5290 kind_(other.kind_), |
5295 representation_(other.representation_), | 5291 representation_(other.representation_), |
5296 instance_(other.instance_), | 5292 instance_(other.instance_), |
5297 raw_selector_(other.raw_selector_), | 5293 raw_selector_(other.raw_selector_), |
5298 id_(other.id_) { | 5294 id_(other.id_) { |
5299 } | 5295 } |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5366 case Instruction::kStoreIndexed: { | 5362 case Instruction::kStoreIndexed: { |
5367 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed(); | 5363 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed(); |
5368 representation_ = store_indexed-> | 5364 representation_ = store_indexed-> |
5369 RequiredInputRepresentation(StoreIndexedInstr::kValuePos); | 5365 RequiredInputRepresentation(StoreIndexedInstr::kValuePos); |
5370 instance_ = store_indexed->array()->definition()->OriginalDefinition(); | 5366 instance_ = store_indexed->array()->definition()->OriginalDefinition(); |
5371 SetIndex(store_indexed->index()->definition()); | 5367 SetIndex(store_indexed->index()->definition()); |
5372 *is_store = true; | 5368 *is_store = true; |
5373 break; | 5369 break; |
5374 } | 5370 } |
5375 | 5371 |
5376 case Instruction::kCurrentContext: | |
5377 kind_ = kContext; | |
5378 ASSERT(instr->AsCurrentContext()->representation() == kTagged); | |
5379 representation_ = kTagged; | |
5380 *is_load = true; | |
5381 break; | |
5382 | |
5383 case Instruction::kStoreContext: | |
5384 kind_ = kContext; | |
5385 ASSERT(instr->AsStoreContext()->RequiredInputRepresentation( | |
5386 StoreContextInstr::kValuePos) == kTagged); | |
5387 representation_ = kTagged; | |
5388 *is_store = true; | |
5389 break; | |
5390 | |
5391 default: | 5372 default: |
5392 break; | 5373 break; |
5393 } | 5374 } |
5394 } | 5375 } |
5395 | 5376 |
5396 // Create object representing *[*] alias. | 5377 // Create object representing *[*] alias. |
5397 static Place* CreateAnyInstanceAnyIndexAlias(Isolate* isolate, | 5378 static Place* CreateAnyInstanceAnyIndexAlias(Isolate* isolate, |
5398 intptr_t id) { | 5379 intptr_t id) { |
5399 return Wrap(isolate, Place(kIndexed, NULL, 0), id); | 5380 return Wrap(isolate, Place(kIndexed, NULL, 0), id); |
5400 } | 5381 } |
(...skipping 19 matching lines...) Expand all Loading... |
5420 } | 5401 } |
5421 | 5402 |
5422 bool DependsOnInstance() const { | 5403 bool DependsOnInstance() const { |
5423 switch (kind()) { | 5404 switch (kind()) { |
5424 case kField: | 5405 case kField: |
5425 case kVMField: | 5406 case kVMField: |
5426 case kIndexed: | 5407 case kIndexed: |
5427 case kConstantIndexed: | 5408 case kConstantIndexed: |
5428 return true; | 5409 return true; |
5429 | 5410 |
5430 case kContext: | |
5431 case kNone: | 5411 case kNone: |
5432 return false; | 5412 return false; |
5433 } | 5413 } |
5434 | 5414 |
5435 UNREACHABLE(); | 5415 UNREACHABLE(); |
5436 return false; | 5416 return false; |
5437 } | 5417 } |
5438 | 5418 |
5439 // Given instance dependent alias X.f, X.@offs, X[C], X[*] return | 5419 // Given instance dependent alias X.f, X.@offs, X[C], X[*] return |
5440 // wild-card dependent alias *.f, *.@offs, *[C] or *[*] respectively. | 5420 // wild-card dependent alias *.f, *.@offs, *[C] or *[*] respectively. |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5520 return Isolate::Current()->current_zone()->PrintToString( | 5500 return Isolate::Current()->current_zone()->PrintToString( |
5521 "<%s[%s]>", | 5501 "<%s[%s]>", |
5522 DefinitionName(instance()), | 5502 DefinitionName(instance()), |
5523 DefinitionName(index())); | 5503 DefinitionName(index())); |
5524 | 5504 |
5525 case kConstantIndexed: | 5505 case kConstantIndexed: |
5526 return Isolate::Current()->current_zone()->PrintToString( | 5506 return Isolate::Current()->current_zone()->PrintToString( |
5527 "<%s[%" Pd "]>", | 5507 "<%s[%" Pd "]>", |
5528 DefinitionName(instance()), | 5508 DefinitionName(instance()), |
5529 index_constant()); | 5509 index_constant()); |
5530 | |
5531 case kContext: | |
5532 return "<context>"; | |
5533 } | 5510 } |
5534 UNREACHABLE(); | 5511 UNREACHABLE(); |
5535 return "<?>"; | 5512 return "<?>"; |
5536 } | 5513 } |
5537 | 5514 |
5538 bool IsFinalField() const { | 5515 bool IsFinalField() const { |
5539 return (kind() == kField) && field().is_final(); | 5516 return (kind() == kField) && field().is_final(); |
5540 } | 5517 } |
5541 | 5518 |
5542 intptr_t Hashcode() const { | 5519 intptr_t Hashcode() const { |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5949 } | 5926 } |
5950 } | 5927 } |
5951 break; | 5928 break; |
5952 | 5929 |
5953 case Place::kField: | 5930 case Place::kField: |
5954 case Place::kVMField: | 5931 case Place::kVMField: |
5955 if (CanBeAliased(alias->instance())) { | 5932 if (CanBeAliased(alias->instance())) { |
5956 // X.f or X.@offs alias with *.f and *.@offs respectively. | 5933 // X.f or X.@offs alias with *.f and *.@offs respectively. |
5957 CrossAlias(alias, alias->CopyWithoutInstance()); | 5934 CrossAlias(alias, alias->CopyWithoutInstance()); |
5958 } | 5935 } |
5959 | 5936 break; |
5960 case Place::kContext: | |
5961 return; | |
5962 | 5937 |
5963 case Place::kNone: | 5938 case Place::kNone: |
5964 UNREACHABLE(); | 5939 UNREACHABLE(); |
5965 } | 5940 } |
5966 } | 5941 } |
5967 | 5942 |
5968 // Returns true if the given load is unaffected by external side-effects. | 5943 // Returns true if the given load is unaffected by external side-effects. |
5969 // This essentially means that no stores to the same location can | 5944 // This essentially means that no stores to the same location can |
5970 // occur in other functions. | 5945 // occur in other functions. |
5971 bool IsIndependentFromEffects(Place* place) { | 5946 bool IsIndependentFromEffects(Place* place) { |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6151 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); | 6126 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); |
6152 if (store_instance_field != NULL) { | 6127 if (store_instance_field != NULL) { |
6153 return store_instance_field->value()->definition(); | 6128 return store_instance_field->value()->definition(); |
6154 } | 6129 } |
6155 | 6130 |
6156 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); | 6131 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); |
6157 if (store_static_field != NULL) { | 6132 if (store_static_field != NULL) { |
6158 return store_static_field->value()->definition(); | 6133 return store_static_field->value()->definition(); |
6159 } | 6134 } |
6160 | 6135 |
6161 if (instr->IsStoreContext()) { | |
6162 return instr->InputAt(0)->definition(); | |
6163 } | |
6164 | |
6165 UNREACHABLE(); // Should only be called for supported store instructions. | 6136 UNREACHABLE(); // Should only be called for supported store instructions. |
6166 return NULL; | 6137 return NULL; |
6167 } | 6138 } |
6168 | 6139 |
6169 | 6140 |
6170 static bool IsPhiDependentPlace(Place* place) { | 6141 static bool IsPhiDependentPlace(Place* place) { |
6171 return ((place->kind() == Place::kField) || | 6142 return ((place->kind() == Place::kField) || |
6172 (place->kind() == Place::kVMField)) && | 6143 (place->kind() == Place::kVMField)) && |
6173 (place->instance() != NULL) && | 6144 (place->instance() != NULL) && |
6174 place->instance()->IsPhi(); | 6145 place->instance()->IsPhi(); |
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7218 } | 7189 } |
7219 } | 7190 } |
7220 | 7191 |
7221 bool CanEliminateStore(Instruction* instr) { | 7192 bool CanEliminateStore(Instruction* instr) { |
7222 switch (instr->tag()) { | 7193 switch (instr->tag()) { |
7223 case Instruction::kStoreInstanceField: | 7194 case Instruction::kStoreInstanceField: |
7224 if (instr->AsStoreInstanceField()->is_initialization()) { | 7195 if (instr->AsStoreInstanceField()->is_initialization()) { |
7225 // Can't eliminate stores that initialized unboxed fields. | 7196 // Can't eliminate stores that initialized unboxed fields. |
7226 return false; | 7197 return false; |
7227 } | 7198 } |
7228 case Instruction::kStoreContext: | |
7229 case Instruction::kStoreIndexed: | 7199 case Instruction::kStoreIndexed: |
7230 case Instruction::kStoreStaticField: | 7200 case Instruction::kStoreStaticField: |
7231 return true; | 7201 return true; |
7232 default: | 7202 default: |
7233 UNREACHABLE(); | 7203 UNREACHABLE(); |
7234 return false; | 7204 return false; |
7235 } | 7205 } |
7236 } | 7206 } |
7237 | 7207 |
7238 virtual void ComputeInitialSets() { | 7208 virtual void ComputeInitialSets() { |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7758 SetReachable(instr->false_successor()); | 7728 SetReachable(instr->false_successor()); |
7759 } | 7729 } |
7760 } | 7730 } |
7761 } | 7731 } |
7762 } | 7732 } |
7763 | 7733 |
7764 | 7734 |
7765 // -------------------------------------------------------------------------- | 7735 // -------------------------------------------------------------------------- |
7766 // Analysis of non-definition instructions. They do not have values so they | 7736 // Analysis of non-definition instructions. They do not have values so they |
7767 // cannot have constant values. | 7737 // cannot have constant values. |
7768 void ConstantPropagator::VisitStoreContext(StoreContextInstr* instr) { } | |
7769 | |
7770 | |
7771 void ConstantPropagator::VisitCheckStackOverflow( | 7738 void ConstantPropagator::VisitCheckStackOverflow( |
7772 CheckStackOverflowInstr* instr) { } | 7739 CheckStackOverflowInstr* instr) { } |
7773 | 7740 |
7774 | 7741 |
7775 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { } | 7742 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) { } |
7776 | 7743 |
7777 | 7744 |
7778 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) { } | 7745 void ConstantPropagator::VisitCheckClassId(CheckClassIdInstr* instr) { } |
7779 | 7746 |
7780 | 7747 |
(...skipping 2341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10122 | 10089 |
10123 // Insert materializations at environment uses. | 10090 // Insert materializations at environment uses. |
10124 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10091 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
10125 CreateMaterializationAt( | 10092 CreateMaterializationAt( |
10126 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10093 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
10127 } | 10094 } |
10128 } | 10095 } |
10129 | 10096 |
10130 | 10097 |
10131 } // namespace dart | 10098 } // namespace dart |
OLD | NEW |