| 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 defn->set_input_use_list(NULL); | 87 defn->set_input_use_list(NULL); |
| 88 defn->set_env_use_list(NULL); | 88 defn->set_env_use_list(NULL); |
| 89 } | 89 } |
| 90 for (intptr_t i = 0; i < instr->InputCount(); ++i) { | 90 for (intptr_t i = 0; i < instr->InputCount(); ++i) { |
| 91 Value* use = instr->InputAt(i); | 91 Value* use = instr->InputAt(i); |
| 92 use->set_instruction(NULL); | 92 use->set_instruction(NULL); |
| 93 use->set_use_index(-1); | 93 use->set_use_index(-1); |
| 94 use->set_next_use(NULL); | 94 use->set_next_use(NULL); |
| 95 } | 95 } |
| 96 if (instr->env() != NULL) { | 96 if (instr->env() != NULL) { |
| 97 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) { | 97 for (EnvironmentIterator it(instr->env()); !it.Done(); it.Advance()) { |
| 98 Value* use = instr->env()->values()[i]; | 98 Value* use = it.CurrentValue(); |
| 99 use->set_instruction(NULL); | 99 use->set_instruction(NULL); |
| 100 use->set_use_index(-1); | 100 use->set_use_index(-1); |
| 101 use->set_next_use(NULL); | 101 use->set_next_use(NULL); |
| 102 } | 102 } |
| 103 } | 103 } |
| 104 } | 104 } |
| 105 | 105 |
| 106 | 106 |
| 107 bool FlowGraph::ResetUseLists() { | 107 bool FlowGraph::ResetUseLists() { |
| 108 // Reset global constants. | 108 // Reset global constants. |
| 109 ResetUseListsInInstruction(graph_entry_->constant_null()); | 109 ResetUseListsInInstruction(graph_entry_->constant_null()); |
| 110 | 110 |
| 111 // Reset definitions referenced from the start environment. | 111 // Reset definitions referenced from the start environment. |
| 112 for (intptr_t i = 0; i < graph_entry_->start_env()->values().length(); ++i) { | 112 for (intptr_t i = 0; i < graph_entry_->start_env()->Length(); ++i) { |
| 113 Value* env_use = graph_entry_->start_env()->values()[i]; | 113 Value* env_use = graph_entry_->start_env()->ValueAt(i); |
| 114 ResetUseListsInInstruction(env_use->definition()); | 114 ResetUseListsInInstruction(env_use->definition()); |
| 115 } | 115 } |
| 116 | 116 |
| 117 // Reset phis in join entries and the instructions in each block. | 117 // Reset phis in join entries and the instructions in each block. |
| 118 for (intptr_t i = 0; i < preorder_.length(); ++i) { | 118 for (intptr_t i = 0; i < preorder_.length(); ++i) { |
| 119 BlockEntryInstr* entry = preorder_[i]; | 119 BlockEntryInstr* entry = preorder_[i]; |
| 120 JoinEntryInstr* join = entry->AsJoinEntry(); | 120 JoinEntryInstr* join = entry->AsJoinEntry(); |
| 121 if (join != NULL && join->phis() != NULL) { | 121 if (join != NULL && join->phis() != NULL) { |
| 122 for (intptr_t i = 0; i < join->phis()->length(); ++i) { | 122 for (intptr_t i = 0; i < join->phis()->length(); ++i) { |
| 123 PhiInstr* phi = (*join->phis())[i]; | 123 PhiInstr* phi = (*join->phis())[i]; |
| 124 if (phi != NULL) ResetUseListsInInstruction(phi); | 124 if (phi != NULL) ResetUseListsInInstruction(phi); |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 127 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 128 ResetUseListsInInstruction(it.Current()); | 128 ResetUseListsInInstruction(it.Current()); |
| 129 } | 129 } |
| 130 } | 130 } |
| 131 return true; // Return true so we can ASSERT the reset code. | 131 return true; // Return true so we can ASSERT the reset code. |
| 132 } | 132 } |
| 133 | 133 |
| 134 | 134 |
| 135 static void ValidateUseListsInInstruction(Instruction* instr) { | 135 static void ValidateUseListsInInstruction(Instruction* instr) { |
| 136 ASSERT(instr != NULL); | 136 ASSERT(instr != NULL); |
| 137 ASSERT(!instr->IsJoinEntry()); | 137 ASSERT(!instr->IsJoinEntry()); |
| 138 for (intptr_t i = 0; i < instr->InputCount(); ++i) { | 138 for (intptr_t i = 0; i < instr->InputCount(); ++i) { |
| 139 Value* use = instr->InputAt(i); | 139 Value* use = instr->InputAt(i); |
| 140 ASSERT(use->use_index() == i); | 140 ASSERT(use->use_index() == i); |
| 141 ASSERT(1 == MembershipCount(use, use->definition()->input_use_list())); | 141 ASSERT(1 == MembershipCount(use, use->definition()->input_use_list())); |
| 142 } | 142 } |
| 143 Environment* env = instr->env(); | 143 if (instr->env() != NULL) { |
| 144 if (env != NULL) { | 144 intptr_t use_index = 0; |
| 145 for (intptr_t i = 0; i < env->values().length(); ++i) { | 145 for (EnvironmentIterator it(instr->env()); !it.Done(); it.Advance()) { |
| 146 Value* use = env->values()[i]; | 146 Value* use = it.CurrentValue(); |
| 147 ASSERT(use->use_index() == i); | 147 ASSERT(use->use_index() == use_index++); |
| 148 ASSERT(1 == MembershipCount(use, use->definition()->env_use_list())); | 148 ASSERT(1 == MembershipCount(use, use->definition()->env_use_list())); |
| 149 } | 149 } |
| 150 } | 150 } |
| 151 Definition* defn = instr->AsDefinition(); | 151 Definition* defn = instr->AsDefinition(); |
| 152 if (defn != NULL) { | 152 if (defn != NULL) { |
| 153 for (Value* use = defn->input_use_list(); | 153 for (Value* use = defn->input_use_list(); |
| 154 use != NULL; | 154 use != NULL; |
| 155 use = use->next_use()) { | 155 use = use->next_use()) { |
| 156 ASSERT(defn == use->definition()); | 156 ASSERT(defn == use->definition()); |
| 157 ASSERT(use == use->instruction()->InputAt(use->use_index())); | 157 ASSERT(use == use->instruction()->InputAt(use->use_index())); |
| 158 } | 158 } |
| 159 for (Value* use = defn->env_use_list(); | 159 for (Value* use = defn->env_use_list(); |
| 160 use != NULL; | 160 use != NULL; |
| 161 use = use->next_use()) { | 161 use = use->next_use()) { |
| 162 ASSERT(defn == use->definition()); | 162 ASSERT(defn == use->definition()); |
| 163 ASSERT(use == use->instruction()->env()->values()[use->use_index()]); | 163 ASSERT(use == |
| 164 use->instruction()->env()->ValueAtUseIndex(use->use_index())); |
| 164 } | 165 } |
| 165 } | 166 } |
| 166 } | 167 } |
| 167 | 168 |
| 168 | 169 |
| 169 bool FlowGraph::ValidateUseLists() { | 170 bool FlowGraph::ValidateUseLists() { |
| 170 // Validate global constants. | 171 // Validate global constants. |
| 171 ValidateUseListsInInstruction(graph_entry_->constant_null()); | 172 ValidateUseListsInInstruction(graph_entry_->constant_null()); |
| 172 | 173 |
| 173 // Validate definitions referenced from the start environment. | 174 // Validate definitions referenced from the start environment. |
| 174 for (intptr_t i = 0; i < graph_entry_->start_env()->values().length(); ++i) { | 175 for (intptr_t i = 0; i < graph_entry_->start_env()->Length(); ++i) { |
| 175 Value* env_use = graph_entry_->start_env()->values()[i]; | 176 Value* env_use = graph_entry_->start_env()->ValueAt(i); |
| 176 ValidateUseListsInInstruction(env_use->definition()); | 177 ValidateUseListsInInstruction(env_use->definition()); |
| 177 } | 178 } |
| 178 | 179 |
| 179 // Validate phis in join entries and the instructions in each block. | 180 // Validate phis in join entries and the instructions in each block. |
| 180 for (intptr_t i = 0; i < preorder_.length(); ++i) { | 181 for (intptr_t i = 0; i < preorder_.length(); ++i) { |
| 181 BlockEntryInstr* entry = preorder_[i]; | 182 BlockEntryInstr* entry = preorder_[i]; |
| 182 JoinEntryInstr* join = entry->AsJoinEntry(); | 183 JoinEntryInstr* join = entry->AsJoinEntry(); |
| 183 if (join != NULL && join->phis() != NULL) { | 184 if (join != NULL && join->phis() != NULL) { |
| 184 for (intptr_t i = 0; i < join->phis()->length(); ++i) { | 185 for (intptr_t i = 0; i < join->phis()->length(); ++i) { |
| 185 PhiInstr* phi = (*join->phis())[i]; | 186 PhiInstr* phi = (*join->phis())[i]; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 216 use->set_instruction(instr); | 217 use->set_instruction(instr); |
| 217 use->set_use_index(i); | 218 use->set_use_index(i); |
| 218 use->AddToInputUseList(); | 219 use->AddToInputUseList(); |
| 219 } | 220 } |
| 220 } | 221 } |
| 221 | 222 |
| 222 | 223 |
| 223 static void RecordEnvUses(Instruction* instr) { | 224 static void RecordEnvUses(Instruction* instr) { |
| 224 ASSERT(instr != NULL); | 225 ASSERT(instr != NULL); |
| 225 if (instr->env() == NULL) return; | 226 if (instr->env() == NULL) return; |
| 226 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) { | 227 intptr_t use_index = 0; |
| 227 Value* use = instr->env()->values()[i]; | 228 for (EnvironmentIterator it(instr->env()); !it.Done(); it.Advance()) { |
| 229 Value* use = it.CurrentValue(); |
| 228 DEBUG_ASSERT(use->instruction() == NULL); | 230 DEBUG_ASSERT(use->instruction() == NULL); |
| 229 DEBUG_ASSERT(use->use_index() == -1); | 231 DEBUG_ASSERT(use->use_index() == -1); |
| 230 DEBUG_ASSERT(use->next_use() == NULL); | 232 DEBUG_ASSERT(use->next_use() == NULL); |
| 231 DEBUG_ASSERT(0 == MembershipCount(use, use->definition()->env_use_list())); | 233 DEBUG_ASSERT(0 == MembershipCount(use, use->definition()->env_use_list())); |
| 232 use->set_instruction(instr); | 234 use->set_instruction(instr); |
| 233 use->set_use_index(i); | 235 use->set_use_index(use_index++); |
| 234 use->AddToEnvUseList(); | 236 use->AddToEnvUseList(); |
| 235 } | 237 } |
| 236 } | 238 } |
| 237 | 239 |
| 238 | 240 |
| 239 static void ComputeUseListsRecursive(BlockEntryInstr* block) { | 241 static void ComputeUseListsRecursive(BlockEntryInstr* block) { |
| 240 // Clear phi definitions. | 242 // Clear phi definitions. |
| 241 JoinEntryInstr* join = block->AsJoinEntry(); | 243 JoinEntryInstr* join = block->AsJoinEntry(); |
| 242 if (join != NULL && join->phis() != NULL) { | 244 if (join != NULL && join->phis() != NULL) { |
| 243 for (intptr_t i = 0; i < join->phis()->length(); ++i) { | 245 for (intptr_t i = 0; i < join->phis()->length(); ++i) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 } | 281 } |
| 280 } | 282 } |
| 281 } | 283 } |
| 282 } | 284 } |
| 283 | 285 |
| 284 | 286 |
| 285 void FlowGraph::ComputeUseLists() { | 287 void FlowGraph::ComputeUseLists() { |
| 286 DEBUG_ASSERT(ResetUseLists()); | 288 DEBUG_ASSERT(ResetUseLists()); |
| 287 // Clear global constants and definitions in the start environment. | 289 // Clear global constants and definitions in the start environment. |
| 288 ClearUseLists(graph_entry_->constant_null()); | 290 ClearUseLists(graph_entry_->constant_null()); |
| 289 for (intptr_t i = 0; i < graph_entry_->start_env()->values().length(); ++i) { | 291 for (intptr_t i = 0; i < graph_entry_->start_env()->Length(); ++i) { |
| 290 ClearUseLists(graph_entry_->start_env()->values()[i]->definition()); | 292 ClearUseLists(graph_entry_->start_env()->ValueAt(i)->definition()); |
| 291 } | 293 } |
| 292 ComputeUseListsRecursive(graph_entry_); | 294 ComputeUseListsRecursive(graph_entry_); |
| 293 DEBUG_ASSERT(ValidateUseLists()); | 295 DEBUG_ASSERT(ValidateUseLists()); |
| 294 } | 296 } |
| 295 | 297 |
| 296 | 298 |
| 297 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number) { | 299 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number) { |
| 298 current_ssa_temp_index_ = next_virtual_register_number; | 300 current_ssa_temp_index_ = next_virtual_register_number; |
| 299 GrowableArray<BitVector*> dominance_frontier; | 301 GrowableArray<BitVector*> dominance_frontier; |
| 300 ComputeDominators(&preorder_, &parent_, &dominance_frontier); | 302 ComputeDominators(&preorder_, &parent_, &dominance_frontier); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 505 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 504 start_env.Add(param); | 506 start_env.Add(param); |
| 505 } | 507 } |
| 506 | 508 |
| 507 // All locals are initialized with #null. Use the global definition, uses | 509 // All locals are initialized with #null. Use the global definition, uses |
| 508 // will be created in the Environment constructor. | 510 // will be created in the Environment constructor. |
| 509 while (start_env.length() < variable_count()) { | 511 while (start_env.length() < variable_count()) { |
| 510 start_env.Add(graph_entry_->constant_null()); | 512 start_env.Add(graph_entry_->constant_null()); |
| 511 } | 513 } |
| 512 graph_entry_->set_start_env( | 514 graph_entry_->set_start_env( |
| 513 new Environment(start_env, num_non_copied_params_)); | 515 Environment::From(start_env, num_non_copied_params_, NULL)); |
| 514 | 516 |
| 515 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); | 517 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); |
| 516 ASSERT(normal_entry != NULL); // Must have entry. | 518 ASSERT(normal_entry != NULL); // Must have entry. |
| 517 GrowableArray<Definition*> env(variable_count()); | 519 GrowableArray<Definition*> env(variable_count()); |
| 518 env.AddArray(start_env); | 520 env.AddArray(start_env); |
| 519 RenameRecursive(normal_entry, &env, live_phis); | 521 RenameRecursive(normal_entry, &env, live_phis); |
| 520 } | 522 } |
| 521 | 523 |
| 522 | 524 |
| 523 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, | 525 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 536 } | 538 } |
| 537 } | 539 } |
| 538 } | 540 } |
| 539 | 541 |
| 540 // 2. Process normal instructions. | 542 // 2. Process normal instructions. |
| 541 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { | 543 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { |
| 542 Instruction* current = it.Current(); | 544 Instruction* current = it.Current(); |
| 543 // Attach current environment to the instruction. First, each instruction | 545 // Attach current environment to the instruction. First, each instruction |
| 544 // gets a full copy of the environment. Later we optimize this by | 546 // gets a full copy of the environment. Later we optimize this by |
| 545 // eliminating unnecessary environments. | 547 // eliminating unnecessary environments. |
| 546 current->set_env(new Environment(*env, num_non_copied_params_)); | 548 current->set_env( |
| 549 Environment::From(*env, num_non_copied_params_, NULL)); |
| 547 | 550 |
| 548 // 2a. Handle uses: | 551 // 2a. Handle uses: |
| 549 // Update expression stack environment for each use. | 552 // Update expression stack environment for each use. |
| 550 // For each use of a LoadLocal or StoreLocal: Replace it with the value | 553 // For each use of a LoadLocal or StoreLocal: Replace it with the value |
| 551 // from the environment. | 554 // from the environment. |
| 552 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { | 555 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { |
| 553 Value* v = current->InputAt(i); | 556 Value* v = current->InputAt(i); |
| 554 // Update expression stack. | 557 // Update expression stack. |
| 555 ASSERT(env->length() > variable_count()); | 558 ASSERT(env->length() > variable_count()); |
| 556 | 559 |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 // Remove original arguments to the call. | 795 // Remove original arguments to the call. |
| 793 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 796 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 794 PushArgumentInstr* push = call->ArgumentAt(i); | 797 PushArgumentInstr* push = call->ArgumentAt(i); |
| 795 push->ReplaceUsesWith(push->value()->definition()); | 798 push->ReplaceUsesWith(push->value()->definition()); |
| 796 push->RemoveFromGraph(); | 799 push->RemoveFromGraph(); |
| 797 } | 800 } |
| 798 } | 801 } |
| 799 | 802 |
| 800 | 803 |
| 801 } // namespace dart | 804 } // namespace dart |
| OLD | NEW |