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

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

Issue 10928048: 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') | 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 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 (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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698