Chromium Code Reviews| 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 5530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5541 Place* place = (*places)[i]; | 5541 Place* place = (*places)[i]; |
| 5542 aliased_set->AddRepresentative(place); | 5542 aliased_set->AddRepresentative(place); |
| 5543 } | 5543 } |
| 5544 | 5544 |
| 5545 aliased_set->EnsureAliasingForIndexes(); | 5545 aliased_set->EnsureAliasingForIndexes(); |
| 5546 | 5546 |
| 5547 return aliased_set; | 5547 return aliased_set; |
| 5548 } | 5548 } |
| 5549 | 5549 |
| 5550 | 5550 |
| 5551 static bool HasSimpleTypeArguments(AllocateObjectInstr* alloc) { | |
| 5552 if (alloc->ArgumentCount() == 0) return true; | |
| 5553 ASSERT(alloc->ArgumentCount() == 2); | |
| 5554 Value* arg1 = alloc->PushArgumentAt(1)->value(); | |
| 5555 if (!arg1->BindsToConstant()) return false; | |
| 5556 | |
| 5557 const Object& obj = arg1->BoundConstant(); | |
| 5558 return obj.IsSmi() | |
| 5559 && (Smi::Cast(obj).Value() == StubCode::kNoInstantiator); | |
| 5560 } | |
| 5561 | |
| 5562 | |
| 5563 class LoadOptimizer : public ValueObject { | 5551 class LoadOptimizer : public ValueObject { |
| 5564 public: | 5552 public: |
| 5565 LoadOptimizer(FlowGraph* graph, | 5553 LoadOptimizer(FlowGraph* graph, |
| 5566 AliasedSet* aliased_set, | 5554 AliasedSet* aliased_set, |
| 5567 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map) | 5555 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map) |
| 5568 : graph_(graph), | 5556 : graph_(graph), |
| 5569 map_(map), | 5557 map_(map), |
| 5570 aliased_set_(aliased_set), | 5558 aliased_set_(aliased_set), |
| 5571 in_(graph_->preorder().length()), | 5559 in_(graph_->preorder().length()), |
| 5572 out_(graph_->preorder().length()), | 5560 out_(graph_->preorder().length()), |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5716 // initialized in constructor that potentially can be not inlined into | 5704 // initialized in constructor that potentially can be not inlined into |
| 5717 // the function that we are currently optimizing. However at the same | 5705 // the function that we are currently optimizing. However at the same |
| 5718 // time we assume that values of the final fields can be forwarded | 5706 // time we assume that values of the final fields can be forwarded |
| 5719 // across side-effects. If we add 'null' as known values for these | 5707 // across side-effects. If we add 'null' as known values for these |
| 5720 // fields here we will incorrectly propagate this null across | 5708 // fields here we will incorrectly propagate this null across |
| 5721 // constructor invocation. | 5709 // constructor invocation. |
| 5722 // TODO(vegorov): record null-values at least for not final fields of | 5710 // TODO(vegorov): record null-values at least for not final fields of |
| 5723 // escaping object. | 5711 // escaping object. |
| 5724 AllocateObjectInstr* alloc = instr->AsAllocateObject(); | 5712 AllocateObjectInstr* alloc = instr->AsAllocateObject(); |
| 5725 if ((alloc != NULL) && | 5713 if ((alloc != NULL) && |
| 5726 !AliasedSet::CanBeAliased(alloc) && | 5714 !AliasedSet::CanBeAliased(alloc)) { |
|
regis
2014/02/13 19:07:50
single line
Florian Schneider
2014/02/14 11:36:34
Done.
| |
| 5727 HasSimpleTypeArguments(alloc)) { | |
| 5728 for (Value* use = alloc->input_use_list(); | 5715 for (Value* use = alloc->input_use_list(); |
| 5729 use != NULL; | 5716 use != NULL; |
| 5730 use = use->next_use()) { | 5717 use = use->next_use()) { |
| 5731 // Look for all immediate loads from this object. | 5718 // Look for all immediate loads from this object. |
| 5732 if (use->use_index() != 0) { | 5719 if (use->use_index() != 0) { |
| 5733 continue; | 5720 continue; |
| 5734 } | 5721 } |
| 5735 | 5722 |
| 5736 LoadFieldInstr* load = use->instruction()->AsLoadField(); | 5723 LoadFieldInstr* load = use->instruction()->AsLoadField(); |
| 5737 if (load != NULL) { | 5724 if (load != NULL) { |
| 5738 // Found a load. Initialize current value of the field to null for | 5725 // Found a load. Initialize current value of the field to null for |
| 5739 // normal fields, or with type arguments. | 5726 // normal fields, or with type arguments. |
| 5740 gen->Add(load->place_id()); | 5727 gen->Add(load->place_id()); |
| 5741 if (out_values == NULL) out_values = CreateBlockOutValues(); | 5728 if (out_values == NULL) out_values = CreateBlockOutValues(); |
| 5742 | 5729 |
| 5743 if (alloc->ArgumentCount() > 0) { | 5730 if (alloc->ArgumentCount() > 0) { |
| 5744 ASSERT(alloc->ArgumentCount() == 2); | 5731 ASSERT(alloc->ArgumentCount() == 1); |
| 5745 intptr_t type_args_offset = | 5732 intptr_t type_args_offset = |
| 5746 alloc->cls().type_arguments_field_offset(); | 5733 alloc->cls().type_arguments_field_offset(); |
| 5747 if (load->offset_in_bytes() == type_args_offset) { | 5734 if (load->offset_in_bytes() == type_args_offset) { |
| 5748 (*out_values)[load->place_id()] = | 5735 (*out_values)[load->place_id()] = |
| 5749 alloc->PushArgumentAt(0)->value()->definition(); | 5736 alloc->PushArgumentAt(0)->value()->definition(); |
| 5750 continue; | 5737 continue; |
| 5751 } | 5738 } |
| 5752 } | 5739 } |
| 5753 (*out_values)[load->place_id()] = graph_->constant_null(); | 5740 (*out_values)[load->place_id()] = graph_->constant_null(); |
| 5754 } | 5741 } |
| (...skipping 1468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7223 instr->type_arguments().CanShareInstantiatorTypeArguments( | 7210 instr->type_arguments().CanShareInstantiatorTypeArguments( |
| 7224 instr->instantiator_class())) { | 7211 instr->instantiator_class())) { |
| 7225 SetValue(instr, object); | 7212 SetValue(instr, object); |
| 7226 return; | 7213 return; |
| 7227 } | 7214 } |
| 7228 SetValue(instr, non_constant_); | 7215 SetValue(instr, non_constant_); |
| 7229 } | 7216 } |
| 7230 } | 7217 } |
| 7231 | 7218 |
| 7232 | 7219 |
| 7233 void ConstantPropagator::VisitExtractConstructorTypeArguments( | |
| 7234 ExtractConstructorTypeArgumentsInstr* instr) { | |
| 7235 CompileType* type = instr->instantiator()->Type(); | |
| 7236 if (type->HasDecidableNullability()) { | |
| 7237 if (!type->is_nullable()) { | |
| 7238 SetValue(instr, instr->type_arguments()); | |
| 7239 return; | |
| 7240 } | |
| 7241 ASSERT(type->IsNull()); | |
| 7242 SetValue(instr, instr->instantiator()->definition()->constant_value()); | |
| 7243 return; | |
| 7244 } | |
| 7245 SetValue(instr, non_constant_); | |
| 7246 } | |
| 7247 | |
| 7248 | |
| 7249 void ConstantPropagator::VisitExtractConstructorInstantiator( | |
| 7250 ExtractConstructorInstantiatorInstr* instr) { | |
| 7251 CompileType* type = instr->instantiator()->Type(); | |
| 7252 if (type->HasDecidableNullability()) { | |
| 7253 if (type->IsNull()) { | |
| 7254 SetValue(instr, Smi::ZoneHandle(Smi::New(StubCode::kNoInstantiator))); | |
| 7255 return; | |
| 7256 } | |
| 7257 ASSERT(!type->is_nullable()); | |
| 7258 SetValue(instr, instr->instantiator()->definition()->constant_value()); | |
| 7259 return; | |
| 7260 } | |
| 7261 SetValue(instr, non_constant_); | |
| 7262 } | |
| 7263 | |
| 7264 | |
| 7265 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { | 7220 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { |
| 7266 SetValue(instr, non_constant_); | 7221 SetValue(instr, non_constant_); |
| 7267 } | 7222 } |
| 7268 | 7223 |
| 7269 | 7224 |
| 7270 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { | 7225 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { |
| 7271 SetValue(instr, non_constant_); | 7226 SetValue(instr, non_constant_); |
| 7272 } | 7227 } |
| 7273 | 7228 |
| 7274 | 7229 |
| (...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8252 } | 8207 } |
| 8253 } | 8208 } |
| 8254 } | 8209 } |
| 8255 | 8210 |
| 8256 | 8211 |
| 8257 // Right now we are attempting to sink allocation only into | 8212 // Right now we are attempting to sink allocation only into |
| 8258 // deoptimization exit. So candidate should only be used in StoreInstanceField | 8213 // deoptimization exit. So candidate should only be used in StoreInstanceField |
| 8259 // instructions that write into fields of the allocated object. | 8214 // instructions that write into fields of the allocated object. |
| 8260 // We do not support materialization of the object that has type arguments. | 8215 // We do not support materialization of the object that has type arguments. |
| 8261 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { | 8216 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { |
| 8262 if (!HasSimpleTypeArguments(alloc)) return false; | |
| 8263 | |
| 8264 for (Value* use = alloc->input_use_list(); | 8217 for (Value* use = alloc->input_use_list(); |
| 8265 use != NULL; | 8218 use != NULL; |
| 8266 use = use->next_use()) { | 8219 use = use->next_use()) { |
| 8267 if (!(use->instruction()->IsStoreInstanceField() && | 8220 if (!(use->instruction()->IsStoreInstanceField() && |
| 8268 (use->use_index() == 0))) { | 8221 (use->use_index() == 0))) { |
| 8269 return false; | 8222 return false; |
| 8270 } | 8223 } |
| 8271 } | 8224 } |
| 8272 | 8225 |
| 8273 return true; | 8226 return true; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 8291 use = alloc->input_use_list()) { | 8244 use = alloc->input_use_list()) { |
| 8292 use->instruction()->RemoveFromGraph(); | 8245 use->instruction()->RemoveFromGraph(); |
| 8293 } | 8246 } |
| 8294 | 8247 |
| 8295 // There should be no environment uses. The pass replaced them with | 8248 // There should be no environment uses. The pass replaced them with |
| 8296 // MaterializeObject instructions. | 8249 // MaterializeObject instructions. |
| 8297 ASSERT(alloc->env_use_list() == NULL); | 8250 ASSERT(alloc->env_use_list() == NULL); |
| 8298 ASSERT(alloc->input_use_list() == NULL); | 8251 ASSERT(alloc->input_use_list() == NULL); |
| 8299 alloc->RemoveFromGraph(); | 8252 alloc->RemoveFromGraph(); |
| 8300 if (alloc->ArgumentCount() > 0) { | 8253 if (alloc->ArgumentCount() > 0) { |
| 8301 ASSERT(alloc->ArgumentCount() == 2); | 8254 ASSERT(alloc->ArgumentCount() == 1); |
| 8302 for (intptr_t i = 0; i < alloc->ArgumentCount(); ++i) { | 8255 for (intptr_t i = 0; i < alloc->ArgumentCount(); ++i) { |
| 8303 alloc->PushArgumentAt(i)->RemoveFromGraph(); | 8256 alloc->PushArgumentAt(i)->RemoveFromGraph(); |
| 8304 } | 8257 } |
| 8305 } | 8258 } |
| 8306 } | 8259 } |
| 8307 | 8260 |
| 8308 | 8261 |
| 8309 void AllocationSinking::Optimize() { | 8262 void AllocationSinking::Optimize() { |
| 8310 GrowableArray<AllocateObjectInstr*> candidates(5); | 8263 GrowableArray<AllocateObjectInstr*> candidates(5); |
| 8311 | 8264 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8466 new ZoneGrowableArray<const Field*>(5); | 8419 new ZoneGrowableArray<const Field*>(5); |
| 8467 | 8420 |
| 8468 for (Value* use = alloc->input_use_list(); | 8421 for (Value* use = alloc->input_use_list(); |
| 8469 use != NULL; | 8422 use != NULL; |
| 8470 use = use->next_use()) { | 8423 use = use->next_use()) { |
| 8471 ASSERT(use->instruction()->IsStoreInstanceField()); | 8424 ASSERT(use->instruction()->IsStoreInstanceField()); |
| 8472 AddField(fields, use->instruction()->AsStoreInstanceField()->field()); | 8425 AddField(fields, use->instruction()->AsStoreInstanceField()->field()); |
| 8473 } | 8426 } |
| 8474 | 8427 |
| 8475 if (alloc->ArgumentCount() > 0) { | 8428 if (alloc->ArgumentCount() > 0) { |
| 8476 ASSERT(alloc->ArgumentCount() == 2); | 8429 ASSERT(alloc->ArgumentCount() == 1); |
| 8477 const String& name = String::Handle(Symbols::New(":type_args")); | 8430 const String& name = String::Handle(Symbols::New(":type_args")); |
| 8478 const Field& type_args_field = | 8431 const Field& type_args_field = |
| 8479 Field::ZoneHandle(Field::New( | 8432 Field::ZoneHandle(Field::New( |
| 8480 name, | 8433 name, |
| 8481 false, // !static | 8434 false, // !static |
| 8482 false, // !final | 8435 false, // !final |
| 8483 false, // !const | 8436 false, // !const |
| 8484 alloc->cls(), | 8437 alloc->cls(), |
| 8485 0)); // No token position. | 8438 0)); // No token position. |
| 8486 type_args_field.SetOffset(alloc->cls().type_arguments_field_offset()); | 8439 type_args_field.SetOffset(alloc->cls().type_arguments_field_offset()); |
| 8487 AddField(fields, type_args_field); | 8440 AddField(fields, type_args_field); |
| 8488 } | 8441 } |
| 8489 | 8442 |
| 8490 // Collect all instructions that mention this object in the environment. | 8443 // Collect all instructions that mention this object in the environment. |
| 8491 GrowableArray<Instruction*> exits(10); | 8444 GrowableArray<Instruction*> exits(10); |
| 8492 for (Value* use = alloc->env_use_list(); | 8445 for (Value* use = alloc->env_use_list(); |
| 8493 use != NULL; | 8446 use != NULL; |
| 8494 use = use->next_use()) { | 8447 use = use->next_use()) { |
| 8495 AddInstruction(&exits, use->instruction()); | 8448 AddInstruction(&exits, use->instruction()); |
| 8496 } | 8449 } |
| 8497 | 8450 |
| 8498 // Insert materializations at environment uses. | 8451 // Insert materializations at environment uses. |
| 8499 for (intptr_t i = 0; i < exits.length(); i++) { | 8452 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8500 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8453 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8501 } | 8454 } |
| 8502 } | 8455 } |
| 8503 | 8456 |
| 8504 | 8457 |
| 8505 } // namespace dart | 8458 } // namespace dart |
| OLD | NEW |