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 |