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

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

Issue 16799003: Support type arguments for allocation sinking in certain conditions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: rebased Created 7 years, 5 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 | « no previous file | tests/language/allocation_sinking_vm_test.dart » ('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/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 4328 matching lines...) Expand 10 before | Expand all | Expand 10 after
4339 AliasedSet* aliased_set = new AliasedSet(places, phi_moves); 4339 AliasedSet* aliased_set = new AliasedSet(places, phi_moves);
4340 for (intptr_t i = 0; i < places->length(); i++) { 4340 for (intptr_t i = 0; i < places->length(); i++) {
4341 Place* place = (*places)[i]; 4341 Place* place = (*places)[i];
4342 aliased_set->AddRepresentative(place); 4342 aliased_set->AddRepresentative(place);
4343 } 4343 }
4344 4344
4345 return aliased_set; 4345 return aliased_set;
4346 } 4346 }
4347 4347
4348 4348
4349 static bool HasSimpleTypeArguments(AllocateObjectInstr* alloc) {
4350 if (alloc->ArgumentCount() == 0) return true;
4351 ASSERT(alloc->ArgumentCount() == 2);
4352 Value* arg1 = alloc->PushArgumentAt(1)->value();
4353 if (!arg1->BindsToConstant()) return false;
4354
4355 const Object& obj = arg1->BoundConstant();
4356 return obj.IsSmi()
4357 && (Smi::Cast(obj).Value() == StubCode::kNoInstantiator);
4358 }
4359
4360
4349 class LoadOptimizer : public ValueObject { 4361 class LoadOptimizer : public ValueObject {
4350 public: 4362 public:
4351 LoadOptimizer(FlowGraph* graph, 4363 LoadOptimizer(FlowGraph* graph,
4352 AliasedSet* aliased_set, 4364 AliasedSet* aliased_set,
4353 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map) 4365 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map)
4354 : graph_(graph), 4366 : graph_(graph),
4355 map_(map), 4367 map_(map),
4356 aliased_set_(aliased_set), 4368 aliased_set_(aliased_set),
4357 in_(graph_->preorder().length()), 4369 in_(graph_->preorder().length()),
4358 out_(graph_->preorder().length()), 4370 out_(graph_->preorder().length()),
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
4500 // type arguments. 4512 // type arguments.
4501 // The reason to ignore escaping objects is that final fields are 4513 // The reason to ignore escaping objects is that final fields are
4502 // initialized in constructor that potentially can be not inlined into 4514 // initialized in constructor that potentially can be not inlined into
4503 // the function that we are currently optimizing. However at the same 4515 // the function that we are currently optimizing. However at the same
4504 // time we assume that values of the final fields can be forwarded 4516 // time we assume that values of the final fields can be forwarded
4505 // across side-effects. If we add 'null' as known values for these 4517 // across side-effects. If we add 'null' as known values for these
4506 // fields here we will incorrectly propagate this null across 4518 // fields here we will incorrectly propagate this null across
4507 // constructor invocation. 4519 // constructor invocation.
4508 // TODO(vegorov): record null-values at least for not final fields of 4520 // TODO(vegorov): record null-values at least for not final fields of
4509 // escaping object. 4521 // escaping object.
4510 // TODO(vegorov): enable forwarding of type arguments.
4511 AllocateObjectInstr* alloc = instr->AsAllocateObject(); 4522 AllocateObjectInstr* alloc = instr->AsAllocateObject();
4512 if ((alloc != NULL) && 4523 if ((alloc != NULL) &&
4513 (alloc->identity() == AllocateObjectInstr::kNotAliased) && 4524 (alloc->identity() == AllocateObjectInstr::kNotAliased) &&
4514 (alloc->ArgumentCount() == 0)) { 4525 HasSimpleTypeArguments(alloc)) {
4515 for (Value* use = alloc->input_use_list(); 4526 for (Value* use = alloc->input_use_list();
4516 use != NULL; 4527 use != NULL;
4517 use = use->next_use()) { 4528 use = use->next_use()) {
4518 // Look for all immediate loads from this object. 4529 // Look for all immediate loads from this object.
4519 if (use->use_index() != 0) { 4530 if (use->use_index() != 0) {
4520 continue; 4531 continue;
4521 } 4532 }
4522 4533
4523 LoadFieldInstr* load = use->instruction()->AsLoadField(); 4534 LoadFieldInstr* load = use->instruction()->AsLoadField();
4524 if (load != NULL) { 4535 if (load != NULL) {
4525 // Found a load. Initialize current value of the field to null. 4536 // Found a load. Initialize current value of the field to null for
4537 // normal fields, or with type arguments.
4526 gen->Add(load->place_id()); 4538 gen->Add(load->place_id());
4527 if (out_values == NULL) out_values = CreateBlockOutValues(); 4539 if (out_values == NULL) out_values = CreateBlockOutValues();
4540
4541 if (alloc->ArgumentCount() > 0) {
4542 ASSERT(alloc->ArgumentCount() == 2);
4543 const Class& cls = Class::Handle(alloc->constructor().Owner());
4544 intptr_t type_args_offset = cls.type_arguments_field_offset();
4545 if (load->offset_in_bytes() == type_args_offset) {
4546 (*out_values)[load->place_id()] =
4547 alloc->PushArgumentAt(0)->value()->definition();
4548 continue;
4549 }
4550 }
4528 (*out_values)[load->place_id()] = graph_->constant_null(); 4551 (*out_values)[load->place_id()] = graph_->constant_null();
4529 } 4552 }
4530 } 4553 }
4531 continue; 4554 continue;
4532 } 4555 }
4533 4556
4534 if (!IsLoadEliminationCandidate(defn)) { 4557 if (!IsLoadEliminationCandidate(defn)) {
4535 continue; 4558 continue;
4536 } 4559 }
4537 4560
(...skipping 2332 matching lines...) Expand 10 before | Expand all | Expand 10 after
6870 } 6893 }
6871 } 6894 }
6872 } 6895 }
6873 6896
6874 6897
6875 // Right now we are attempting to sink allocation only into 6898 // Right now we are attempting to sink allocation only into
6876 // deoptimization exit. So candidate should only be used in StoreInstanceField 6899 // deoptimization exit. So candidate should only be used in StoreInstanceField
6877 // instructions that write into fields of the allocated object. 6900 // instructions that write into fields of the allocated object.
6878 // We do not support materialization of the object that has type arguments. 6901 // We do not support materialization of the object that has type arguments.
6879 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) { 6902 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc) {
6880 // TODO(vegorov): support AllocateObject with type arguments. 6903 if (!HasSimpleTypeArguments(alloc)) return false;
6881 if (alloc->ArgumentCount() > 0) {
6882 return false;
6883 }
6884 6904
6885 for (Value* use = alloc->input_use_list(); 6905 for (Value* use = alloc->input_use_list();
6886 use != NULL; 6906 use != NULL;
6887 use = use->next_use()) { 6907 use = use->next_use()) {
6888 if (!(use->instruction()->IsStoreInstanceField() && 6908 if (!(use->instruction()->IsStoreInstanceField() &&
6889 use->use_index() == 0)) { 6909 use->use_index() == 0)) {
6890 return false; 6910 return false;
6891 } 6911 }
6892 } 6912 }
6893 6913
(...skipping 17 matching lines...) Expand all
6911 use != NULL; 6931 use != NULL;
6912 use = alloc->input_use_list()) { 6932 use = alloc->input_use_list()) {
6913 use->instruction()->RemoveFromGraph(); 6933 use->instruction()->RemoveFromGraph();
6914 } 6934 }
6915 6935
6916 // There should be no environment uses. The pass replaced them with 6936 // There should be no environment uses. The pass replaced them with
6917 // MaterializeObject instructions. 6937 // MaterializeObject instructions.
6918 ASSERT(alloc->env_use_list() == NULL); 6938 ASSERT(alloc->env_use_list() == NULL);
6919 ASSERT(alloc->input_use_list() == NULL); 6939 ASSERT(alloc->input_use_list() == NULL);
6920 alloc->RemoveFromGraph(); 6940 alloc->RemoveFromGraph();
6941 if (alloc->ArgumentCount() > 0) {
6942 ASSERT(alloc->ArgumentCount() == 2);
6943 for (intptr_t i = 0; i < alloc->ArgumentCount(); ++i) {
6944 alloc->PushArgumentAt(i)->RemoveFromGraph();
6945 }
6946 }
6921 } 6947 }
6922 6948
6923 6949
6924 void AllocationSinking::Optimize() { 6950 void AllocationSinking::Optimize() {
6925 GrowableArray<AllocateObjectInstr*> candidates(5); 6951 GrowableArray<AllocateObjectInstr*> candidates(5);
6926 6952
6927 // Collect sinking candidates. 6953 // Collect sinking candidates.
6928 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph_->postorder(); 6954 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph_->postorder();
6929 for (BlockIterator block_it(postorder); 6955 for (BlockIterator block_it(postorder);
6930 !block_it.Done(); 6956 !block_it.Done();
(...skipping 30 matching lines...) Expand all
6961 } 6987 }
6962 6988
6963 // Run load forwarding to eliminate LoadField instructions inserted above. 6989 // Run load forwarding to eliminate LoadField instructions inserted above.
6964 // All loads will be successfully eliminated because: 6990 // All loads will be successfully eliminated because:
6965 // a) they use fields (not offsets) and thus provide precise aliasing 6991 // a) they use fields (not offsets) and thus provide precise aliasing
6966 // information 6992 // information
6967 // b) candidate does not escape and thus its fields is not affected by 6993 // b) candidate does not escape and thus its fields is not affected by
6968 // external effects from calls. 6994 // external effects from calls.
6969 LoadOptimizer::OptimizeGraph(flow_graph_); 6995 LoadOptimizer::OptimizeGraph(flow_graph_);
6970 6996
6997 if (FLAG_trace_optimization) {
6998 FlowGraphPrinter::PrintGraph("Sinking", flow_graph_);
6999 }
7000
6971 // At this point we have computed the state of object at each deoptimization 7001 // At this point we have computed the state of object at each deoptimization
6972 // point and we can eliminate it. Loads inserted above were forwarded so there 7002 // point and we can eliminate it. Loads inserted above were forwarded so there
6973 // are no uses of the allocation just as in the begging of the pass. 7003 // are no uses of the allocation just as in the begging of the pass.
6974 for (intptr_t i = 0; i < candidates.length(); i++) { 7004 for (intptr_t i = 0; i < candidates.length(); i++) {
6975 EliminateAllocation(candidates[i]); 7005 EliminateAllocation(candidates[i]);
6976 } 7006 }
6977 7007
6978 // Process materializations and unbox their arguments: materializations 7008 // Process materializations and unbox their arguments: materializations
6979 // are part of the environment and can materialize boxes for double/mint/simd 7009 // are part of the environment and can materialize boxes for double/mint/simd
6980 // values when needed. 7010 // values when needed.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
7076 ZoneGrowableArray<const Field*>* fields = 7106 ZoneGrowableArray<const Field*>* fields =
7077 new ZoneGrowableArray<const Field*>(5); 7107 new ZoneGrowableArray<const Field*>(5);
7078 7108
7079 for (Value* use = alloc->input_use_list(); 7109 for (Value* use = alloc->input_use_list();
7080 use != NULL; 7110 use != NULL;
7081 use = use->next_use()) { 7111 use = use->next_use()) {
7082 ASSERT(use->instruction()->IsStoreInstanceField()); 7112 ASSERT(use->instruction()->IsStoreInstanceField());
7083 AddField(fields, use->instruction()->AsStoreInstanceField()->field()); 7113 AddField(fields, use->instruction()->AsStoreInstanceField()->field());
7084 } 7114 }
7085 7115
7116 if (alloc->ArgumentCount() > 0) {
7117 ASSERT(alloc->ArgumentCount() == 2);
7118 const String& name = String::Handle(Symbols::New(":type_args"));
7119 const Field& type_args_field =
7120 Field::ZoneHandle(Field::New(
7121 name,
7122 false, // !static
7123 false, // !final
7124 false, // !const
7125 Class::Handle(alloc->constructor().Owner()),
7126 0)); // No token position.
7127 const Class& cls = Class::Handle(alloc->constructor().Owner());
7128 type_args_field.SetOffset(cls.type_arguments_field_offset());
7129 AddField(fields, type_args_field);
7130 }
7131
7086 // Collect all instructions that mention this object in the environment. 7132 // Collect all instructions that mention this object in the environment.
7087 GrowableArray<Instruction*> exits(10); 7133 GrowableArray<Instruction*> exits(10);
7088 for (Value* use = alloc->env_use_list(); 7134 for (Value* use = alloc->env_use_list();
7089 use != NULL; 7135 use != NULL;
7090 use = use->next_use()) { 7136 use = use->next_use()) {
7091 AddInstruction(&exits, use->instruction()); 7137 AddInstruction(&exits, use->instruction());
7092 } 7138 }
7093 7139
7094 // Insert materializations at environment uses. 7140 // Insert materializations at environment uses.
7095 const Class& cls = Class::Handle(alloc->constructor().Owner()); 7141 const Class& cls = Class::Handle(alloc->constructor().Owner());
7096 for (intptr_t i = 0; i < exits.length(); i++) { 7142 for (intptr_t i = 0; i < exits.length(); i++) {
7097 CreateMaterializationAt(exits[i], alloc, cls, *fields); 7143 CreateMaterializationAt(exits[i], alloc, cls, *fields);
7098 } 7144 }
7099 } 7145 }
7100 7146
7101 7147
7102 } // namespace dart 7148 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | tests/language/allocation_sinking_vm_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698