| 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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5715 // The reason to ignore escaping objects is that final fields are | 5703 // The reason to ignore escaping objects is that final fields are |
| 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) && !AliasedSet::CanBeAliased(alloc)) { |
| 5726 !AliasedSet::CanBeAliased(alloc) && | |
| 5727 HasSimpleTypeArguments(alloc)) { | |
| 5728 for (Value* use = alloc->input_use_list(); | 5714 for (Value* use = alloc->input_use_list(); |
| 5729 use != NULL; | 5715 use != NULL; |
| 5730 use = use->next_use()) { | 5716 use = use->next_use()) { |
| 5731 // Look for all immediate loads from this object. | 5717 // Look for all immediate loads from this object. |
| 5732 if (use->use_index() != 0) { | 5718 if (use->use_index() != 0) { |
| 5733 continue; | 5719 continue; |
| 5734 } | 5720 } |
| 5735 | 5721 |
| 5736 LoadFieldInstr* load = use->instruction()->AsLoadField(); | 5722 LoadFieldInstr* load = use->instruction()->AsLoadField(); |
| 5737 if (load != NULL) { | 5723 if (load != NULL) { |
| 5738 // Found a load. Initialize current value of the field to null for | 5724 // Found a load. Initialize current value of the field to null for |
| 5739 // normal fields, or with type arguments. | 5725 // normal fields, or with type arguments. |
| 5740 gen->Add(load->place_id()); | 5726 gen->Add(load->place_id()); |
| 5741 if (out_values == NULL) out_values = CreateBlockOutValues(); | 5727 if (out_values == NULL) out_values = CreateBlockOutValues(); |
| 5742 | 5728 |
| 5743 if (alloc->ArgumentCount() > 0) { | 5729 if (alloc->ArgumentCount() > 0) { |
| 5744 ASSERT(alloc->ArgumentCount() == 2); | 5730 ASSERT(alloc->ArgumentCount() == 1); |
| 5745 intptr_t type_args_offset = | 5731 intptr_t type_args_offset = |
| 5746 alloc->cls().type_arguments_field_offset(); | 5732 alloc->cls().type_arguments_field_offset(); |
| 5747 if (load->offset_in_bytes() == type_args_offset) { | 5733 if (load->offset_in_bytes() == type_args_offset) { |
| 5748 (*out_values)[load->place_id()] = | 5734 (*out_values)[load->place_id()] = |
| 5749 alloc->PushArgumentAt(0)->value()->definition(); | 5735 alloc->PushArgumentAt(0)->value()->definition(); |
| 5750 continue; | 5736 continue; |
| 5751 } | 5737 } |
| 5752 } | 5738 } |
| 5753 (*out_values)[load->place_id()] = graph_->constant_null(); | 5739 (*out_values)[load->place_id()] = graph_->constant_null(); |
| 5754 } | 5740 } |
| (...skipping 1468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7223 instr->type_arguments().CanShareInstantiatorTypeArguments( | 7209 instr->type_arguments().CanShareInstantiatorTypeArguments( |
| 7224 instr->instantiator_class())) { | 7210 instr->instantiator_class())) { |
| 7225 SetValue(instr, object); | 7211 SetValue(instr, object); |
| 7226 return; | 7212 return; |
| 7227 } | 7213 } |
| 7228 SetValue(instr, non_constant_); | 7214 SetValue(instr, non_constant_); |
| 7229 } | 7215 } |
| 7230 } | 7216 } |
| 7231 | 7217 |
| 7232 | 7218 |
| 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) { | 7219 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) { |
| 7266 SetValue(instr, non_constant_); | 7220 SetValue(instr, non_constant_); |
| 7267 } | 7221 } |
| 7268 | 7222 |
| 7269 | 7223 |
| 7270 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { | 7224 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) { |
| 7271 SetValue(instr, non_constant_); | 7225 SetValue(instr, non_constant_); |
| 7272 } | 7226 } |
| 7273 | 7227 |
| 7274 | 7228 |
| (...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8252 } | 8206 } |
| 8253 } | 8207 } |
| 8254 } | 8208 } |
| 8255 | 8209 |
| 8256 | 8210 |
| 8257 // Right now we are attempting to sink allocation only into | 8211 // Right now we are attempting to sink allocation only into |
| 8258 // deoptimization exit. So candidate should only be used in StoreInstanceField | 8212 // deoptimization exit. So candidate should only be used in StoreInstanceField |
| 8259 // instructions that write into fields of the allocated object. | 8213 // instructions that write into fields of the allocated object. |
| 8260 // We do not support materialization of the object that has type arguments. | 8214 // We do not support materialization of the object that has type arguments. |
| 8261 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { | 8215 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { |
| 8262 if (!HasSimpleTypeArguments(alloc)) return false; | |
| 8263 | |
| 8264 for (Value* use = alloc->input_use_list(); | 8216 for (Value* use = alloc->input_use_list(); |
| 8265 use != NULL; | 8217 use != NULL; |
| 8266 use = use->next_use()) { | 8218 use = use->next_use()) { |
| 8267 if (!(use->instruction()->IsStoreInstanceField() && | 8219 if (!(use->instruction()->IsStoreInstanceField() && |
| 8268 (use->use_index() == 0))) { | 8220 (use->use_index() == 0))) { |
| 8269 return false; | 8221 return false; |
| 8270 } | 8222 } |
| 8271 } | 8223 } |
| 8272 | 8224 |
| 8273 return true; | 8225 return true; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 8291 use = alloc->input_use_list()) { | 8243 use = alloc->input_use_list()) { |
| 8292 use->instruction()->RemoveFromGraph(); | 8244 use->instruction()->RemoveFromGraph(); |
| 8293 } | 8245 } |
| 8294 | 8246 |
| 8295 // There should be no environment uses. The pass replaced them with | 8247 // There should be no environment uses. The pass replaced them with |
| 8296 // MaterializeObject instructions. | 8248 // MaterializeObject instructions. |
| 8297 ASSERT(alloc->env_use_list() == NULL); | 8249 ASSERT(alloc->env_use_list() == NULL); |
| 8298 ASSERT(alloc->input_use_list() == NULL); | 8250 ASSERT(alloc->input_use_list() == NULL); |
| 8299 alloc->RemoveFromGraph(); | 8251 alloc->RemoveFromGraph(); |
| 8300 if (alloc->ArgumentCount() > 0) { | 8252 if (alloc->ArgumentCount() > 0) { |
| 8301 ASSERT(alloc->ArgumentCount() == 2); | 8253 ASSERT(alloc->ArgumentCount() == 1); |
| 8302 for (intptr_t i = 0; i < alloc->ArgumentCount(); ++i) { | 8254 for (intptr_t i = 0; i < alloc->ArgumentCount(); ++i) { |
| 8303 alloc->PushArgumentAt(i)->RemoveFromGraph(); | 8255 alloc->PushArgumentAt(i)->RemoveFromGraph(); |
| 8304 } | 8256 } |
| 8305 } | 8257 } |
| 8306 } | 8258 } |
| 8307 | 8259 |
| 8308 | 8260 |
| 8309 void AllocationSinking::Optimize() { | 8261 void AllocationSinking::Optimize() { |
| 8310 GrowableArray<AllocateObjectInstr*> candidates(5); | 8262 GrowableArray<AllocateObjectInstr*> candidates(5); |
| 8311 | 8263 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8466 new ZoneGrowableArray<const Field*>(5); | 8418 new ZoneGrowableArray<const Field*>(5); |
| 8467 | 8419 |
| 8468 for (Value* use = alloc->input_use_list(); | 8420 for (Value* use = alloc->input_use_list(); |
| 8469 use != NULL; | 8421 use != NULL; |
| 8470 use = use->next_use()) { | 8422 use = use->next_use()) { |
| 8471 ASSERT(use->instruction()->IsStoreInstanceField()); | 8423 ASSERT(use->instruction()->IsStoreInstanceField()); |
| 8472 AddField(fields, use->instruction()->AsStoreInstanceField()->field()); | 8424 AddField(fields, use->instruction()->AsStoreInstanceField()->field()); |
| 8473 } | 8425 } |
| 8474 | 8426 |
| 8475 if (alloc->ArgumentCount() > 0) { | 8427 if (alloc->ArgumentCount() > 0) { |
| 8476 ASSERT(alloc->ArgumentCount() == 2); | 8428 ASSERT(alloc->ArgumentCount() == 1); |
| 8477 const String& name = String::Handle(Symbols::New(":type_args")); | 8429 const String& name = String::Handle(Symbols::New(":type_args")); |
| 8478 const Field& type_args_field = | 8430 const Field& type_args_field = |
| 8479 Field::ZoneHandle(Field::New( | 8431 Field::ZoneHandle(Field::New( |
| 8480 name, | 8432 name, |
| 8481 false, // !static | 8433 false, // !static |
| 8482 false, // !final | 8434 false, // !final |
| 8483 false, // !const | 8435 false, // !const |
| 8484 alloc->cls(), | 8436 alloc->cls(), |
| 8485 0)); // No token position. | 8437 0)); // No token position. |
| 8486 type_args_field.SetOffset(alloc->cls().type_arguments_field_offset()); | 8438 type_args_field.SetOffset(alloc->cls().type_arguments_field_offset()); |
| 8487 AddField(fields, type_args_field); | 8439 AddField(fields, type_args_field); |
| 8488 } | 8440 } |
| 8489 | 8441 |
| 8490 // Collect all instructions that mention this object in the environment. | 8442 // Collect all instructions that mention this object in the environment. |
| 8491 GrowableArray<Instruction*> exits(10); | 8443 GrowableArray<Instruction*> exits(10); |
| 8492 for (Value* use = alloc->env_use_list(); | 8444 for (Value* use = alloc->env_use_list(); |
| 8493 use != NULL; | 8445 use != NULL; |
| 8494 use = use->next_use()) { | 8446 use = use->next_use()) { |
| 8495 AddInstruction(&exits, use->instruction()); | 8447 AddInstruction(&exits, use->instruction()); |
| 8496 } | 8448 } |
| 8497 | 8449 |
| 8498 // Insert materializations at environment uses. | 8450 // Insert materializations at environment uses. |
| 8499 for (intptr_t i = 0; i < exits.length(); i++) { | 8451 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8500 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8452 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8501 } | 8453 } |
| 8502 } | 8454 } |
| 8503 | 8455 |
| 8504 | 8456 |
| 8505 } // namespace dart | 8457 } // namespace dart |
| OLD | NEW |