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

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

Issue 10879036: Compute the def-use list on-demand by walking the dominator tree. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Unneeded include. Created 8 years, 3 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.h ('k') | runtime/vm/flow_graph_allocator.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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.h" 5 #include "vm/flow_graph.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/flow_graph_builder.h" 8 #include "vm/flow_graph_builder.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 Instruction* previous = entry; 57 Instruction* previous = entry;
58 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 58 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
59 Instruction* current = it.Current(); 59 Instruction* current = it.Current();
60 current->set_previous(previous); 60 current->set_previous(previous);
61 previous = current; 61 previous = current;
62 } 62 }
63 } 63 }
64 } 64 }
65 65
66 66
67 #ifdef DEBUG
68 // Helper class to check consistency of the use list construction. Clears all
69 // use-list data in one pass which is then used for assertions when building the
70 // use lists.
71 class DefUseCleanup : public FlowGraphVisitor {
Kevin Millikin (Google) 2012/08/24 08:53:05 While it's a noun, this isn't a very tangible name
72 public:
73 explicit DefUseCleanup(FlowGraph* flow_graph)
74 : FlowGraphVisitor(flow_graph->preorder()) { }
75 void CleanupInstruction(Instruction* instr) {
Kevin Millikin (Google) 2012/08/24 08:53:05 I like "ResetInstruction" slightly better. Cleanu
76 JoinEntryInstr* join = instr->AsJoinEntry();
77 if (join != NULL && join->phis() != NULL) {
78 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
79 PhiInstr* phi = (*join->phis())[i];
80 if (phi != NULL) CleanupInstruction(phi);
81 }
82 }
83 Definition* defn = instr->AsDefinition();
84 if (defn != NULL) {
85 defn->set_input_use_list(NULL);
86 defn->set_env_use_list(NULL);
87 }
88 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
89 UseVal* use = instr->InputAt(i)->AsUse();
90 if (use == NULL) continue;
91 use->set_instruction(NULL);
Kevin Millikin (Google) 2012/08/24 08:53:05 Here you could just use a virtual Reset function o
92 use->set_use_index(-1);
93 use->set_next_use(NULL);
94 }
95 if (instr->env() != NULL) {
96 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) {
97 UseVal* use = instr->env()->values()[i]->AsUse();
98 if (use == NULL) continue;
99 use->set_instruction(NULL);
100 use->set_use_index(-1);
101 use->set_next_use(NULL);
102 }
103 }
104 }
105 #define DEFINE_VISIT(type) \
106 virtual void Visit##type(type##Instr* instr) { CleanupInstruction(instr); }
107 FOR_EACH_INSTRUCTION(DEFINE_VISIT)
108 #undef DEFINE_VISIT
109 };
110 #endif // DEBUG
111
112
113 static void ClearUseLists(Definition* defn) {
114 ASSERT(defn != NULL);
115 ASSERT(defn->input_use_list() == NULL);
116 ASSERT(defn->env_use_list() == NULL);
117 defn->set_input_use_list(NULL);
118 defn->set_env_use_list(NULL);
119 }
120
121
122 static void RecordInputUses(Instruction* instr) {
123 ASSERT(instr != NULL);
124 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
125 UseVal* use = instr->InputAt(i)->AsUse();
126 if (use == NULL) continue;
127 ASSERT(use->instruction() == NULL);
128 ASSERT(use->use_index() == -1);
129 ASSERT(use->next_use() == NULL);
130 use->set_instruction(instr);
131 use->set_use_index(i);
132 use->AddToInputUseList();
133 }
134 }
135
136
137 static void RecordEnvUses(Instruction* instr) {
138 ASSERT(instr != NULL);
139 if (instr->env() == NULL) return;
140 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) {
141 UseVal* use = instr->env()->values()[i]->AsUse();
142 if (use == NULL) continue;
143 ASSERT(use->instruction() == NULL);
144 ASSERT(use->use_index() == -1);
145 ASSERT(use->next_use() == NULL);
146 use->set_instruction(instr);
147 use->set_use_index(i);
148 use->AddToEnvUseList();
149 }
150 }
151
152
153 static void ComputeUseListsRecursive(BlockEntryInstr* block) {
154 // Clear phi definitions.
155 JoinEntryInstr* join = block->AsJoinEntry();
156 if (join != NULL && join->phis() != NULL) {
157 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
158 PhiInstr* phi = (*join->phis())[i];
159 if (phi != NULL) ClearUseLists(phi);
160 }
161 }
162 // Compute uses on normal instructions.
163 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
164 Instruction* instr = it.Current();
165 if (instr->IsDefinition()) ClearUseLists(instr->AsDefinition());
166 RecordInputUses(instr);
167 RecordEnvUses(instr);
168 }
169 // Compute recursively on dominated blocks.
170 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
171 ComputeUseListsRecursive(block->dominated_blocks()[i]);
172 }
173 // Add phi uses on successor edges.
174 if (block->last_instruction()->SuccessorCount() == 1 &&
175 block->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
176 JoinEntryInstr* join =
177 block->last_instruction()->SuccessorAt(0)->AsJoinEntry();
178 intptr_t pred_index = join->IndexOfPredecessor(block);
179 ASSERT(pred_index >= 0);
180 if (join->phis() != NULL) {
181 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
182 PhiInstr* phi = (*join->phis())[i];
183 if (phi == NULL) continue;
184 UseVal* use = phi->InputAt(pred_index)->AsUse();
185 if (use == NULL) continue;
186 ASSERT(use->instruction() == NULL);
187 ASSERT(use->use_index() == -1);
188 ASSERT(use->next_use() == NULL);
189 use->set_instruction(phi);
190 use->set_use_index(pred_index);
191 use->AddToInputUseList();
192 }
193 }
194 }
195 }
196
197
198 void FlowGraph::ComputeUseLists() {
199 #ifdef DEBUG
200 DefUseCleanup cleanup(this);
201 cleanup.VisitBlocks();
202 #endif // DEBUG
203 ComputeUseListsRecursive(graph_entry_);
204 }
205
206
67 void FlowGraph::ComputeSSA() { 207 void FlowGraph::ComputeSSA() {
68 GrowableArray<BitVector*> dominance_frontier; 208 GrowableArray<BitVector*> dominance_frontier;
69 ComputeDominators(&preorder_, &parent_, &dominance_frontier); 209 ComputeDominators(&preorder_, &parent_, &dominance_frontier);
70 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 210 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
71 GrowableArray<PhiInstr*> live_phis; 211 GrowableArray<PhiInstr*> live_phis;
72 // Rename uses to reference inserted phis where appropriate. 212 // Rename uses to reference inserted phis where appropriate.
73 // Collect phis that reach a non-environment use. 213 // Collect phis that reach a non-environment use.
74 Rename(&live_phis); 214 Rename(&live_phis);
75 // Propagate alive mark transitively from alive phis. 215 // Propagate alive mark transitively from alive phis.
76 MarkLivePhis(&live_phis); 216 MarkLivePhis(&live_phis);
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // Update expression stack. 475 // Update expression stack.
336 ASSERT(env->length() > variable_count()); 476 ASSERT(env->length() > variable_count());
337 477
338 Definition* input_defn = env->Last(); 478 Definition* input_defn = env->Last();
339 env->RemoveLast(); 479 env->RemoveLast();
340 480
341 BindInstr* as_bind = v->AsUse()->definition()->AsBind(); 481 BindInstr* as_bind = v->AsUse()->definition()->AsBind();
342 if ((as_bind != NULL) && 482 if ((as_bind != NULL) &&
343 (as_bind->computation()->IsLoadLocal() || 483 (as_bind->computation()->IsLoadLocal() ||
344 as_bind->computation()->IsStoreLocal())) { 484 as_bind->computation()->IsStoreLocal())) {
345 // Assert exactly one use. 485 // Remove the load/store from the graph.
346 ASSERT(as_bind->use_list() == v);
347 ASSERT(as_bind->use_list()->next_use() == NULL);
348 // Remove the use, its definition and copy the environment value.
349 v->RemoveFromUseList();
350 as_bind->RemoveFromGraph(); 486 as_bind->RemoveFromGraph();
351 // Assert we are not referencing nulls in the initial environment. 487 // Assert we are not referencing nulls in the initial environment.
352 ASSERT(input_defn->ssa_temp_index() != -1); 488 ASSERT(input_defn->ssa_temp_index() != -1);
353 current->SetInputAt(i, new UseVal(input_defn)); 489 current->SetInputAt(i, new UseVal(input_defn));
354 } 490 }
355 } 491 }
356 492
357 // Drop pushed arguments for calls. 493 // Drop pushed arguments for calls.
358 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { 494 for (intptr_t j = 0; j < current->ArgumentCount(); j++) {
359 env->RemoveLast(); 495 env->RemoveLast();
(...skipping 20 matching lines...) Expand all
380 index = load->local().BitIndexIn(non_copied_parameter_count_); 516 index = load->local().BitIndexIn(non_copied_parameter_count_);
381 517
382 PhiInstr* phi = (*env)[index]->AsPhi(); 518 PhiInstr* phi = (*env)[index]->AsPhi();
383 if ((phi != NULL) && !phi->is_alive()) { 519 if ((phi != NULL) && !phi->is_alive()) {
384 phi->mark_alive(); 520 phi->mark_alive();
385 live_phis->Add(phi); 521 live_phis->Add(phi);
386 } 522 }
387 } 523 }
388 // Update expression stack or remove from graph. 524 // Update expression stack or remove from graph.
389 if (bind->is_used()) { 525 if (bind->is_used()) {
390 // Assert exactly one use.
391 ASSERT(bind->use_list() != NULL);
392 ASSERT(bind->use_list()->next_use() == NULL);
393 env->Add((*env)[index]); 526 env->Add((*env)[index]);
394 // We remove load/store instructions when we find their use in 2a. 527 // We remove load/store instructions when we find their use in 2a.
395 } else { 528 } else {
396 it.RemoveCurrentFromGraph(); 529 it.RemoveCurrentFromGraph();
397 } 530 }
398 } else { 531 } else {
399 // Not a load or store. 532 // Not a load or store.
400 if (bind->is_used()) { 533 if (bind->is_used()) {
401 // Assign fresh SSA temporary and update expression stack. 534 // Assign fresh SSA temporary and update expression stack.
402 bind->set_ssa_temp_index(alloc_ssa_temp_index()); 535 bind->set_ssa_temp_index(alloc_ssa_temp_index());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 597 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
465 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 598 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
466 OS::SNPrint(chars, len, kFormat, function_name, reason); 599 OS::SNPrint(chars, len, kFormat, function_name, reason);
467 const Error& error = Error::Handle( 600 const Error& error = Error::Handle(
468 LanguageError::New(String::Handle(String::New(chars)))); 601 LanguageError::New(String::Handle(String::New(chars))));
469 Isolate::Current()->long_jump_base()->Jump(1, error); 602 Isolate::Current()->long_jump_base()->Jump(1, error);
470 } 603 }
471 604
472 605
473 } // namespace dart 606 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698