Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |