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

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

Issue 10909168: Introduce nested deoptimization environments. (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 | « no previous file | runtime/vm/flow_graph_allocator.cc » ('j') | runtime/vm/intermediate_language.h » ('J')
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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 (Environment::DeepIterator 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 (Environment::DeepIterator 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
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 (Environment::DeepIterator 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
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 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 507 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
506 start_env.Add(param); 508 start_env.Add(param);
507 } 509 }
508 510
509 // All locals are initialized with #null. Use the global definition, uses 511 // All locals are initialized with #null. Use the global definition, uses
510 // will be created in the Environment constructor. 512 // will be created in the Environment constructor.
511 while (start_env.length() < variable_count()) { 513 while (start_env.length() < variable_count()) {
512 start_env.Add(graph_entry_->constant_null()); 514 start_env.Add(graph_entry_->constant_null());
513 } 515 }
514 graph_entry_->set_start_env( 516 graph_entry_->set_start_env(
515 new Environment(start_env, num_non_copied_params_)); 517 Environment::From(start_env, num_non_copied_params_, NULL));
516 518
517 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); 519 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
518 ASSERT(normal_entry != NULL); // Must have entry. 520 ASSERT(normal_entry != NULL); // Must have entry.
519 GrowableArray<Definition*> env(variable_count()); 521 GrowableArray<Definition*> env(variable_count());
520 env.AddArray(start_env); 522 env.AddArray(start_env);
521 RenameRecursive(normal_entry, &env, live_phis); 523 RenameRecursive(normal_entry, &env, live_phis);
522 } 524 }
523 525
524 526
525 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, 527 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry,
(...skipping 12 matching lines...) Expand all
538 } 540 }
539 } 541 }
540 } 542 }
541 543
542 // 2. Process normal instructions. 544 // 2. Process normal instructions.
543 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 545 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
544 Instruction* current = it.Current(); 546 Instruction* current = it.Current();
545 // Attach current environment to the instruction. First, each instruction 547 // Attach current environment to the instruction. First, each instruction
546 // gets a full copy of the environment. Later we optimize this by 548 // gets a full copy of the environment. Later we optimize this by
547 // eliminating unnecessary environments. 549 // eliminating unnecessary environments.
548 current->set_env(new Environment(*env, num_non_copied_params_)); 550 current->set_env(
551 Environment::From(*env, num_non_copied_params_, NULL));
549 552
550 // 2a. Handle uses: 553 // 2a. Handle uses:
551 // Update expression stack environment for each use. 554 // Update expression stack environment for each use.
552 // For each use of a LoadLocal or StoreLocal: Replace it with the value 555 // For each use of a LoadLocal or StoreLocal: Replace it with the value
553 // from the environment. 556 // from the environment.
554 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { 557 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) {
555 Value* v = current->InputAt(i); 558 Value* v = current->InputAt(i);
556 // Update expression stack. 559 // Update expression stack.
557 ASSERT(env->length() > variable_count()); 560 ASSERT(env->length() > variable_count());
558 561
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 // Remove original arguments to the call. 797 // Remove original arguments to the call.
795 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 798 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
796 PushArgumentInstr* push = call->ArgumentAt(i); 799 PushArgumentInstr* push = call->ArgumentAt(i);
797 push->ReplaceUsesWith(push->value()->definition()); 800 push->ReplaceUsesWith(push->value()->definition());
798 push->RemoveFromGraph(); 801 push->RemoveFromGraph();
799 } 802 }
800 } 803 }
801 804
802 805
803 } // namespace dart 806 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_allocator.cc » ('j') | runtime/vm/intermediate_language.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698