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

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

Issue 10879041: Validate well-formedness of the use lists in debug mode. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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_optimizer.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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 67 #ifdef DEBUG
68 // Helper class to check consistency of the use list construction. Clears all 68 // Debugging code to verify the construction of use lists.
69 // use-list data in one pass which is then used for assertions when building the 69
70 // use lists. 70 static intptr_t MembershipCount(UseVal* use, UseVal* list) {
71 class DefUseCleanup : public FlowGraphVisitor { 71 intptr_t count = 0;
72 public: 72 while (list != NULL) {
73 explicit DefUseCleanup(FlowGraph* flow_graph) 73 if (list == use) ++count;
74 : FlowGraphVisitor(flow_graph->preorder()) { } 74 list = list->next_use();
75 void CleanupInstruction(Instruction* instr) { 75 }
76 JoinEntryInstr* join = instr->AsJoinEntry(); 76 return count;
77 if (join != NULL && join->phis() != NULL) { 77 }
78 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 78
79 PhiInstr* phi = (*join->phis())[i]; 79
80 if (phi != NULL) CleanupInstruction(phi); 80 static void ResetUseListsInInstruction(Instruction* instr) {
81 } 81 Definition* defn = instr->AsDefinition();
82 } 82 if (defn != NULL) {
83 Definition* defn = instr->AsDefinition(); 83 defn->set_input_use_list(NULL);
84 if (defn != NULL) { 84 defn->set_env_use_list(NULL);
85 defn->set_input_use_list(NULL); 85 }
86 defn->set_env_use_list(NULL); 86 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
87 } 87 UseVal* use = instr->InputAt(i)->AsUse();
88 for (intptr_t i = 0; i < instr->InputCount(); ++i) { 88 if (use == NULL) continue;
89 UseVal* use = instr->InputAt(i)->AsUse(); 89 use->set_instruction(NULL);
90 use->set_use_index(-1);
91 use->set_next_use(NULL);
92 }
93 if (instr->env() != NULL) {
94 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) {
95 UseVal* use = instr->env()->values()[i]->AsUse();
90 if (use == NULL) continue; 96 if (use == NULL) continue;
91 use->set_instruction(NULL); 97 use->set_instruction(NULL);
92 use->set_use_index(-1); 98 use->set_use_index(-1);
93 use->set_next_use(NULL); 99 use->set_next_use(NULL);
94 } 100 }
95 if (instr->env() != NULL) { 101 }
96 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) { 102 }
97 UseVal* use = instr->env()->values()[i]->AsUse(); 103
98 if (use == NULL) continue; 104
99 use->set_instruction(NULL); 105 bool FlowGraph::ResetUseLists() {
100 use->set_use_index(-1); 106 // Reset use lists of parameters in the start environment.
Kevin Millikin (Google) 2012/08/27 12:11:12 It's not just parameters, but all definitions, rig
101 use->set_next_use(NULL); 107 for (intptr_t i = 0; i < graph_entry_->start_env()->values().length(); ++i) {
108 UseVal* env_use = graph_entry_->start_env()->values()[i]->AsUse();
109 if (env_use != NULL) ResetUseListsInInstruction(env_use->definition());
110 }
111 // Reset phis in join entries and the instructions in each block.
112 for (intptr_t i = 0; i < preorder_.length(); ++i) {
113 BlockEntryInstr* entry = preorder_[i];
114 JoinEntryInstr* join = entry->AsJoinEntry();
115 if (join != NULL && join->phis() != NULL) {
116 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
117 PhiInstr* phi = (*join->phis())[i];
118 if (phi != NULL) ResetUseListsInInstruction(phi);
102 } 119 }
103 } 120 }
121 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
122 ResetUseListsInInstruction(it.Current());
123 }
104 } 124 }
105 #define DEFINE_VISIT(type) \ 125 return true; // Return true so we can ASSERT the reset code.
106 virtual void Visit##type(type##Instr* instr) { CleanupInstruction(instr); } 126 }
107 FOR_EACH_INSTRUCTION(DEFINE_VISIT) 127
108 #undef DEFINE_VISIT 128
109 }; 129 static void ValidateUseListsInInstruction(Instruction* instr) {
130 ASSERT(instr != NULL);
131 ASSERT(!instr->IsJoinEntry());
132 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
133 UseVal* use = instr->InputAt(i)->AsUse();
134 if (use == NULL) continue;
135 ASSERT(use->use_index() == i);
136 ASSERT(1 == MembershipCount(use, use->definition()->input_use_list()));
137 }
138 Environment* env = instr->env();
139 if (env != NULL) {
140 for (intptr_t i = 0; i < env->values().length(); ++i) {
141 UseVal* use = env->values()[i]->AsUse();
142 if (use == NULL) continue;
143 ASSERT(use->use_index() == i);
144 ASSERT(1 == MembershipCount(use, use->definition()->env_use_list()));
145 }
146 }
147 Definition* defn = instr->AsDefinition();
148 if (defn != NULL) {
149 for (UseVal* use = defn->input_use_list();
150 use != NULL;
151 use = use->next_use()) {
152 ASSERT(defn == use->definition());
153 ASSERT(use == use->instruction()->InputAt(use->use_index()));
154 }
155 for (UseVal* use = defn->env_use_list();
156 use != NULL;
157 use = use->next_use()) {
158 ASSERT(defn == use->definition());
159 ASSERT(use == use->instruction()->env()->values()[use->use_index()]);
160 }
161 }
162 }
163
164
165 bool FlowGraph::ValidateUseLists() {
166 // Validate parameters in the start environment.
Kevin Millikin (Google) 2012/08/27 12:11:12 All definitions.
167 for (intptr_t i = 0; i < graph_entry_->start_env()->values().length(); ++i) {
168 UseVal* env_use = graph_entry_->start_env()->values()[i]->AsUse();
169 if (env_use != NULL) ValidateUseListsInInstruction(env_use->definition());
170 }
171 // Validate phis in join entries and the instructions in each block.
172 for (intptr_t i = 0; i < preorder_.length(); ++i) {
173 BlockEntryInstr* entry = preorder_[i];
174 JoinEntryInstr* join = entry->AsJoinEntry();
175 if (join != NULL && join->phis() != NULL) {
176 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
177 PhiInstr* phi = (*join->phis())[i];
178 if (phi != NULL) ValidateUseListsInInstruction(phi);
179 }
180 }
181 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
182 ValidateUseListsInInstruction(it.Current());
183 }
184 }
185 return true; // Return true so we can ASSERT validation.
186 }
110 #endif // DEBUG 187 #endif // DEBUG
111 188
112 189
113 static void ClearUseLists(Definition* defn) { 190 static void ClearUseLists(Definition* defn) {
114 ASSERT(defn != NULL); 191 ASSERT(defn != NULL);
115 ASSERT(defn->input_use_list() == NULL); 192 DEBUG_ASSERT(defn->input_use_list() == NULL);
116 ASSERT(defn->env_use_list() == NULL); 193 DEBUG_ASSERT(defn->env_use_list() == NULL);
117 defn->set_input_use_list(NULL); 194 defn->set_input_use_list(NULL);
118 defn->set_env_use_list(NULL); 195 defn->set_env_use_list(NULL);
119 } 196 }
120 197
121 198
122 static void RecordInputUses(Instruction* instr) { 199 static void RecordInputUses(Instruction* instr) {
123 ASSERT(instr != NULL); 200 ASSERT(instr != NULL);
124 for (intptr_t i = 0; i < instr->InputCount(); ++i) { 201 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
125 UseVal* use = instr->InputAt(i)->AsUse(); 202 UseVal* use = instr->InputAt(i)->AsUse();
126 if (use == NULL) continue; 203 if (use == NULL) continue;
127 ASSERT(use->instruction() == NULL); 204 DEBUG_ASSERT(use->instruction() == NULL);
128 ASSERT(use->use_index() == -1); 205 DEBUG_ASSERT(use->use_index() == -1);
129 ASSERT(use->next_use() == NULL); 206 DEBUG_ASSERT(use->next_use() == NULL);
207 DEBUG_ASSERT(0 == MembershipCount(use,
208 use->definition()->input_use_list()));
130 use->set_instruction(instr); 209 use->set_instruction(instr);
131 use->set_use_index(i); 210 use->set_use_index(i);
132 use->AddToInputUseList(); 211 use->AddToInputUseList();
133 } 212 }
134 } 213 }
135 214
136 215
137 static void RecordEnvUses(Instruction* instr) { 216 static void RecordEnvUses(Instruction* instr) {
138 ASSERT(instr != NULL); 217 ASSERT(instr != NULL);
139 if (instr->env() == NULL) return; 218 if (instr->env() == NULL) return;
140 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) { 219 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) {
141 UseVal* use = instr->env()->values()[i]->AsUse(); 220 UseVal* use = instr->env()->values()[i]->AsUse();
142 if (use == NULL) continue; 221 if (use == NULL) continue;
143 ASSERT(use->instruction() == NULL); 222 DEBUG_ASSERT(use->instruction() == NULL);
144 ASSERT(use->use_index() == -1); 223 DEBUG_ASSERT(use->use_index() == -1);
145 ASSERT(use->next_use() == NULL); 224 DEBUG_ASSERT(use->next_use() == NULL);
225 DEBUG_ASSERT(0 == MembershipCount(use, use->definition()->env_use_list()));
146 use->set_instruction(instr); 226 use->set_instruction(instr);
147 use->set_use_index(i); 227 use->set_use_index(i);
148 use->AddToEnvUseList(); 228 use->AddToEnvUseList();
149 } 229 }
150 } 230 }
151 231
152 232
153 static void ComputeUseListsRecursive(BlockEntryInstr* block) { 233 static void ComputeUseListsRecursive(BlockEntryInstr* block) {
154 // Clear phi definitions. 234 // Clear phi definitions.
155 JoinEntryInstr* join = block->AsJoinEntry(); 235 JoinEntryInstr* join = block->AsJoinEntry();
(...skipping 20 matching lines...) Expand all
176 JoinEntryInstr* join = 256 JoinEntryInstr* join =
177 block->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 257 block->last_instruction()->SuccessorAt(0)->AsJoinEntry();
178 intptr_t pred_index = join->IndexOfPredecessor(block); 258 intptr_t pred_index = join->IndexOfPredecessor(block);
179 ASSERT(pred_index >= 0); 259 ASSERT(pred_index >= 0);
180 if (join->phis() != NULL) { 260 if (join->phis() != NULL) {
181 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 261 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
182 PhiInstr* phi = (*join->phis())[i]; 262 PhiInstr* phi = (*join->phis())[i];
183 if (phi == NULL) continue; 263 if (phi == NULL) continue;
184 UseVal* use = phi->InputAt(pred_index)->AsUse(); 264 UseVal* use = phi->InputAt(pred_index)->AsUse();
185 if (use == NULL) continue; 265 if (use == NULL) continue;
186 ASSERT(use->instruction() == NULL); 266 DEBUG_ASSERT(use->instruction() == NULL);
187 ASSERT(use->use_index() == -1); 267 DEBUG_ASSERT(use->use_index() == -1);
188 ASSERT(use->next_use() == NULL); 268 DEBUG_ASSERT(use->next_use() == NULL);
269 DEBUG_ASSERT(0 == MembershipCount(use,
270 use->definition()->input_use_list()));
189 use->set_instruction(phi); 271 use->set_instruction(phi);
190 use->set_use_index(pred_index); 272 use->set_use_index(pred_index);
191 use->AddToInputUseList(); 273 use->AddToInputUseList();
192 } 274 }
193 } 275 }
194 } 276 }
195 } 277 }
196 278
197 279
198 void FlowGraph::ComputeUseLists() { 280 void FlowGraph::ComputeUseLists() {
199 #ifdef DEBUG 281 DEBUG_ASSERT(ResetUseLists());
200 DefUseCleanup cleanup(this);
201 cleanup.VisitBlocks();
202 #endif // DEBUG
203 ComputeUseListsRecursive(graph_entry_); 282 ComputeUseListsRecursive(graph_entry_);
283 DEBUG_ASSERT(ValidateUseLists());
204 } 284 }
205 285
206 286
207 void FlowGraph::ComputeSSA() { 287 void FlowGraph::ComputeSSA() {
208 GrowableArray<BitVector*> dominance_frontier; 288 GrowableArray<BitVector*> dominance_frontier;
209 ComputeDominators(&preorder_, &parent_, &dominance_frontier); 289 ComputeDominators(&preorder_, &parent_, &dominance_frontier);
210 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 290 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
211 GrowableArray<PhiInstr*> live_phis; 291 GrowableArray<PhiInstr*> live_phis;
212 // Rename uses to reference inserted phis where appropriate. 292 // Rename uses to reference inserted phis where appropriate.
213 // Collect phis that reach a non-environment use. 293 // Collect phis that reach a non-environment use.
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 677 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
598 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 678 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
599 OS::SNPrint(chars, len, kFormat, function_name, reason); 679 OS::SNPrint(chars, len, kFormat, function_name, reason);
600 const Error& error = Error::Handle( 680 const Error& error = Error::Handle(
601 LanguageError::New(String::Handle(String::New(chars)))); 681 LanguageError::New(String::Handle(String::New(chars))));
602 Isolate::Current()->long_jump_base()->Jump(1, error); 682 Isolate::Current()->long_jump_base()->Jump(1, error);
603 } 683 }
604 684
605 685
606 } // namespace dart 686 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_optimizer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698