Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(314)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 163683006: Simplify generated code for object allocation with type arguments. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698