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

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

Issue 12827027: Revert "Compute local variable liveness before translation to SSA." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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_allocator.h » ('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"
11 #include "vm/growable_array.h" 11 #include "vm/growable_array.h"
12 12
13 namespace dart { 13 namespace dart {
14 14
15 DECLARE_FLAG(bool, trace_optimization); 15 DECLARE_FLAG(bool, trace_optimization);
16 DECLARE_FLAG(bool, verify_compiler); 16 DECLARE_FLAG(bool, verify_compiler);
17 17
18 FlowGraph::FlowGraph(const FlowGraphBuilder& builder, 18 FlowGraph::FlowGraph(const FlowGraphBuilder& builder,
19 GraphEntryInstr* graph_entry, 19 GraphEntryInstr* graph_entry,
20 intptr_t max_block_id) 20 intptr_t max_block_id)
21 : parent_(), 21 : parent_(),
22 assigned_vars_(),
22 current_ssa_temp_index_(0), 23 current_ssa_temp_index_(0),
23 max_block_id_(max_block_id), 24 max_block_id_(max_block_id),
24 parsed_function_(builder.parsed_function()), 25 parsed_function_(builder.parsed_function()),
25 num_copied_params_(builder.num_copied_params()), 26 num_copied_params_(builder.num_copied_params()),
26 num_non_copied_params_(builder.num_non_copied_params()), 27 num_non_copied_params_(builder.num_non_copied_params()),
27 num_stack_locals_(builder.num_stack_locals()), 28 num_stack_locals_(builder.num_stack_locals()),
28 graph_entry_(graph_entry), 29 graph_entry_(graph_entry),
29 preorder_(), 30 preorder_(),
30 postorder_(), 31 postorder_(),
31 reverse_postorder_(), 32 reverse_postorder_(),
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 if (env != NULL) env->DeepCopyTo(instr); 81 if (env != NULL) env->DeepCopyTo(instr);
81 } 82 }
82 83
83 84
84 void FlowGraph::DiscoverBlocks() { 85 void FlowGraph::DiscoverBlocks() {
85 // Initialize state. 86 // Initialize state.
86 preorder_.Clear(); 87 preorder_.Clear();
87 postorder_.Clear(); 88 postorder_.Clear();
88 reverse_postorder_.Clear(); 89 reverse_postorder_.Clear();
89 parent_.Clear(); 90 parent_.Clear();
91 assigned_vars_.Clear();
90 // Perform a depth-first traversal of the graph to build preorder and 92 // Perform a depth-first traversal of the graph to build preorder and
91 // postorder block orders. 93 // postorder block orders.
92 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor. 94 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor.
93 &preorder_, 95 &preorder_,
94 &postorder_, 96 &postorder_,
95 &parent_, 97 &parent_,
98 &assigned_vars_,
96 variable_count(), 99 variable_count(),
97 num_non_copied_params()); 100 num_non_copied_params());
98 // Create an array of blocks in reverse postorder. 101 // Create an array of blocks in reverse postorder.
99 intptr_t block_count = postorder_.length(); 102 intptr_t block_count = postorder_.length();
100 for (intptr_t i = 0; i < block_count; ++i) { 103 for (intptr_t i = 0; i < block_count; ++i) {
101 reverse_postorder_.Add(postorder_[block_count - i - 1]); 104 reverse_postorder_.Add(postorder_[block_count - i - 1]);
102 } 105 }
103 } 106 }
104 107
105 108
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 } 198 }
196 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 199 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
197 VerifyUseListsInInstruction(it.Current()); 200 VerifyUseListsInInstruction(it.Current());
198 } 201 }
199 } 202 }
200 return true; // Return true so we can ASSERT validation. 203 return true; // Return true so we can ASSERT validation.
201 } 204 }
202 #endif // DEBUG 205 #endif // DEBUG
203 206
204 207
205 LivenessAnalysis::LivenessAnalysis(
206 intptr_t variable_count,
207 const GrowableArray<BlockEntryInstr*>& postorder)
208 : variable_count_(variable_count),
209 postorder_(postorder),
210 live_out_(postorder.length()),
211 kill_(postorder.length()),
212 live_in_(postorder.length()) {
213 }
214
215
216 bool LivenessAnalysis::UpdateLiveOut(const BlockEntryInstr& block) {
217 BitVector* live_out = live_out_[block.postorder_number()];
218 bool changed = false;
219 Instruction* last = block.last_instruction();
220 ASSERT(last != NULL);
221 for (intptr_t i = 0; i < last->SuccessorCount(); i++) {
222 BlockEntryInstr* succ = last->SuccessorAt(i);
223 ASSERT(succ != NULL);
224 if (live_out->AddAll(live_in_[succ->postorder_number()])) {
225 changed = true;
226 }
227 }
228 return changed;
229 }
230
231
232 bool LivenessAnalysis::UpdateLiveIn(const BlockEntryInstr& block) {
233 BitVector* live_out = live_out_[block.postorder_number()];
234 BitVector* kill = kill_[block.postorder_number()];
235 BitVector* live_in = live_in_[block.postorder_number()];
236 return live_in->KillAndAdd(kill, live_out);
237 }
238
239
240 void LivenessAnalysis::ComputeLiveInAndLiveOutSets() {
241 const intptr_t block_count = postorder_.length();
242 bool changed;
243 do {
244 changed = false;
245
246 for (intptr_t i = 0; i < block_count; i++) {
247 const BlockEntryInstr& block = *postorder_[i];
248
249 // Live-in set depends only on kill set which does not
250 // change in this loop and live-out set. If live-out
251 // set does not change there is no need to recompute
252 // live-in set.
253 if (UpdateLiveOut(block) && UpdateLiveIn(block)) {
254 changed = true;
255 }
256 }
257 } while (changed);
258 }
259
260
261 void LivenessAnalysis::Analyze() {
262 const intptr_t block_count = postorder_.length();
263 for (intptr_t i = 0; i < block_count; i++) {
264 live_out_.Add(new BitVector(variable_count_));
265 kill_.Add(new BitVector(variable_count_));
266 live_in_.Add(new BitVector(variable_count_));
267 }
268
269 ComputeInitialSets();
270 ComputeLiveInAndLiveOutSets();
271 }
272
273
274 static void PrintBitVector(const char* tag, BitVector* v) {
275 OS::Print("%s:", tag);
276 for (BitVector::Iterator it(v); !it.Done(); it.Advance()) {
277 OS::Print(" %"Pd"", it.Current());
278 }
279 OS::Print("\n");
280 }
281
282
283 void LivenessAnalysis::Dump() {
284 const intptr_t block_count = postorder_.length();
285 for (intptr_t i = 0; i < block_count; i++) {
286 BlockEntryInstr* block = postorder_[i];
287 OS::Print("block @%"Pd" -> ", block->block_id());
288
289 Instruction* last = block->last_instruction();
290 for (intptr_t j = 0; j < last->SuccessorCount(); j++) {
291 BlockEntryInstr* succ = last->SuccessorAt(j);
292 OS::Print(" @%"Pd"", succ->block_id());
293 }
294 OS::Print("\n");
295
296 PrintBitVector(" live out", live_out_[i]);
297 PrintBitVector(" kill", kill_[i]);
298 PrintBitVector(" live in", live_in_[i]);
299 }
300 }
301
302
303 // Computes liveness information for local variables.
304 class VariableLivenessAnalysis : public LivenessAnalysis {
305 public:
306 explicit VariableLivenessAnalysis(FlowGraph* flow_graph)
307 : LivenessAnalysis(flow_graph->variable_count(), flow_graph->postorder()),
308 flow_graph_(flow_graph),
309 num_non_copied_params_(flow_graph->num_non_copied_params()),
310 assigned_vars_() { }
311
312 // For every block (in preorder) compute and return set of variables that
313 // have new assigned values flowing out of that block.
314 const GrowableArray<BitVector*>& ComputeAssignedVars() {
315 // We can't directly return kill_ because it uses postorder numbering while
316 // SSA construction uses preorder numbering internally.
317 // We have to permute postorder into preorder.
318 assigned_vars_.Clear();
319
320 const intptr_t block_count = flow_graph_->preorder().length();
321 for (intptr_t i = 0; i < block_count; i++) {
322 BlockEntryInstr* block = flow_graph_->preorder()[i];
323 BitVector* kill = GetKillSet(block);
324 kill->Intersect(GetLiveOutSet(block));
325 assigned_vars_.Add(kill);
326 }
327
328 return assigned_vars_;
329 }
330
331 // Returns true if the value set by the given store reaches any load from the
332 // same local variable.
333 bool IsStoreAlive(BlockEntryInstr* block, StoreLocalInstr* store) {
334 if (store->is_dead()) {
335 return false;
336 }
337
338 if (store->is_last()) {
339 const intptr_t index = store->local().BitIndexIn(num_non_copied_params_);
340 return GetLiveOutSet(block)->Contains(index);
341 }
342
343 return true;
344 }
345
346 // Returns true if the given load is the last for the local and the value
347 // of the local will not flow into another one.
348 bool IsLastLoad(BlockEntryInstr* block, LoadLocalInstr* load) {
349 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_);
350 return load->is_last() && !GetLiveOutSet(block)->Contains(index);
351 }
352
353 private:
354 virtual void ComputeInitialSets();
355
356 const FlowGraph* flow_graph_;
357 const intptr_t num_non_copied_params_;
358 GrowableArray<BitVector*> assigned_vars_;
359 };
360
361
362 void VariableLivenessAnalysis::ComputeInitialSets() {
363 const intptr_t block_count = postorder_.length();
364
365 BitVector* last_loads = new BitVector(variable_count_);
366 for (intptr_t i = 0; i < block_count; i++) {
367 BlockEntryInstr* block = postorder_[i];
368
369 BitVector* kill = kill_[i];
370 BitVector* live_in = live_in_[i];
371 last_loads->Clear();
372
373 // Iterate backwards starting at the last instruction.
374 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
375 Instruction* current = it.Current();
376
377 LoadLocalInstr* load = current->AsLoadLocal();
378 if (load != NULL) {
379 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_);
380 live_in->Add(index);
381
382 if (!last_loads->Contains(index)) {
383 last_loads->Add(index);
384 load->mark_last();
385 }
386
387 continue;
388 }
389
390 StoreLocalInstr* store = current->AsStoreLocal();
391 if (store != NULL) {
392 const intptr_t index =
393 store->local().BitIndexIn(num_non_copied_params_);
394 if (kill->Contains(index)) {
395 if (!live_in->Contains(index)) {
396 store->mark_dead();
397 }
398 } else {
399 if (!live_in->Contains(index)) {
400 store->mark_last();
401 }
402 kill->Add(index);
403 }
404 live_in->Remove(index);
405 continue;
406 }
407 }
408 }
409 }
410
411
412 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, 208 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number,
413 GrowableArray<Definition*>* inlining_parameters) { 209 GrowableArray<Definition*>* inlining_parameters) {
414 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); 210 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL));
415 current_ssa_temp_index_ = next_virtual_register_number; 211 current_ssa_temp_index_ = next_virtual_register_number;
416 GrowableArray<BitVector*> dominance_frontier; 212 GrowableArray<BitVector*> dominance_frontier;
417 ComputeDominators(&dominance_frontier); 213 ComputeDominators(&dominance_frontier);
418 214 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
419 VariableLivenessAnalysis variable_liveness(this);
420 variable_liveness.Analyze();
421
422 InsertPhis(preorder_,
423 variable_liveness.ComputeAssignedVars(),
424 dominance_frontier);
425
426 GrowableArray<PhiInstr*> live_phis; 215 GrowableArray<PhiInstr*> live_phis;
427
428 // Rename uses to reference inserted phis where appropriate. 216 // Rename uses to reference inserted phis where appropriate.
429 // Collect phis that reach a non-environment use. 217 // Collect phis that reach a non-environment use.
430 Rename(&live_phis, &variable_liveness, inlining_parameters); 218 Rename(&live_phis, inlining_parameters);
431
432 // Propagate alive mark transitively from alive phis and then remove 219 // Propagate alive mark transitively from alive phis and then remove
433 // non-live ones. 220 // non-live ones.
434 RemoveDeadPhis(&live_phis); 221 RemoveDeadPhis(&live_phis);
435 } 222 }
436 223
437 224
438 // Compute immediate dominators and the dominance frontier for each basic 225 // Compute immediate dominators and the dominance frontier for each basic
439 // block. As a side effect of the algorithm, sets the immediate dominator 226 // block. As a side effect of the algorithm, sets the immediate dominator
440 // of each basic block. 227 // of each basic block.
441 // 228 //
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 worklist.Add(block); 390 worklist.Add(block);
604 } 391 }
605 } 392 }
606 } 393 }
607 } 394 }
608 } 395 }
609 } 396 }
610 397
611 398
612 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, 399 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
613 VariableLivenessAnalysis* variable_liveness,
614 GrowableArray<Definition*>* inlining_parameters) { 400 GrowableArray<Definition*>* inlining_parameters) {
615 // TODO(fschneider): Support catch-entry. 401 // TODO(fschneider): Support catch-entry.
616 if (graph_entry_->SuccessorCount() > 1) { 402 if (graph_entry_->SuccessorCount() > 1) {
617 Bailout("Catch-entry support in SSA."); 403 Bailout("Catch-entry support in SSA.");
618 } 404 }
619 405
620 // Initial renaming environment. 406 // Initial renaming environment.
621 GrowableArray<Definition*> env(variable_count()); 407 GrowableArray<Definition*> env(variable_count());
622 408
623 // Add global constants to the initial definitions. 409 // Add global constants to the initial definitions.
(...skipping 20 matching lines...) Expand all
644 } 430 }
645 } 431 }
646 432
647 // Initialize all locals with #null in the renaming environment. 433 // Initialize all locals with #null in the renaming environment.
648 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { 434 for (intptr_t i = parameter_count(); i < variable_count(); ++i) {
649 env.Add(constant_null()); 435 env.Add(constant_null());
650 } 436 }
651 437
652 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); 438 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
653 ASSERT(normal_entry != NULL); // Must have entry. 439 ASSERT(normal_entry != NULL); // Must have entry.
654 RenameRecursive(normal_entry, &env, live_phis, variable_liveness); 440 RenameRecursive(normal_entry, &env, live_phis);
655 } 441 }
656 442
657 443
658 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, 444 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry,
659 GrowableArray<Definition*>* env, 445 GrowableArray<Definition*>* env,
660 GrowableArray<PhiInstr*>* live_phis, 446 GrowableArray<PhiInstr*>* live_phis) {
661 VariableLivenessAnalysis* variable_liveness) {
662 // 1. Process phis first. 447 // 1. Process phis first.
663 if (block_entry->IsJoinEntry()) { 448 if (block_entry->IsJoinEntry()) {
664 JoinEntryInstr* join = block_entry->AsJoinEntry(); 449 JoinEntryInstr* join = block_entry->AsJoinEntry();
665 if (join->phis() != NULL) { 450 if (join->phis() != NULL) {
666 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 451 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
667 PhiInstr* phi = (*join->phis())[i]; 452 PhiInstr* phi = (*join->phis())[i];
668 if (phi != NULL) { 453 if (phi != NULL) {
669 (*env)[i] = phi; 454 (*env)[i] = phi;
670 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 455 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
671 } 456 }
672 } 457 }
673 } 458 }
674 } 459 }
675 460
676 // 2. Process normal instructions. 461 // 2. Process normal instructions.
677 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 462 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
678 Instruction* current = it.Current(); 463 Instruction* current = it.Current();
679 // Attach current environment to the instructions that can deoptimize and 464 // Attach current environment to the instructions that can deoptimize and
680 // at goto instructions. Optimizations like LICM expect an environment at 465 // at goto instructions. Optimizations like LICM expect an environment at
681 // gotos. 466 // gotos.
682 if (current->CanDeoptimize() || 467 if (current->CanDeoptimize() || current->IsGoto()) {
683 current->IsGoto() ||
684 (current->IsBranch() &&
685 current->AsBranch()->comparison()->IsStrictCompare())) {
686 Environment* deopt_env = 468 Environment* deopt_env =
687 Environment::From(*env, 469 Environment::From(*env,
688 num_non_copied_params_, 470 num_non_copied_params_,
689 parsed_function_.function()); 471 parsed_function_.function());
690 current->SetEnvironment(deopt_env); 472 current->SetEnvironment(deopt_env);
691 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { 473 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
692 Value* use = it.CurrentValue(); 474 Value* use = it.CurrentValue();
693 use->definition()->AddEnvUse(use); 475 use->definition()->AddEnvUse(use);
694 } 476 }
695 } 477 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 509
728 // 2b. Handle LoadLocal and StoreLocal. 510 // 2b. Handle LoadLocal and StoreLocal.
729 // For each LoadLocal: Remove it from the graph. 511 // For each LoadLocal: Remove it from the graph.
730 // For each StoreLocal: Remove it from the graph and update the environment. 512 // For each StoreLocal: Remove it from the graph and update the environment.
731 Definition* definition = current->AsDefinition(); 513 Definition* definition = current->AsDefinition();
732 if (definition != NULL) { 514 if (definition != NULL) {
733 LoadLocalInstr* load = definition->AsLoadLocal(); 515 LoadLocalInstr* load = definition->AsLoadLocal();
734 StoreLocalInstr* store = definition->AsStoreLocal(); 516 StoreLocalInstr* store = definition->AsStoreLocal();
735 if ((load != NULL) || (store != NULL)) { 517 if ((load != NULL) || (store != NULL)) {
736 intptr_t index; 518 intptr_t index;
737 Definition* result;
738 if (store != NULL) { 519 if (store != NULL) {
520 index = store->local().BitIndexIn(num_non_copied_params_);
739 // Update renaming environment. 521 // Update renaming environment.
740 index = store->local().BitIndexIn(num_non_copied_params_); 522 (*env)[index] = store->value()->definition();
741 result = store->value()->definition();
742
743 if (variable_liveness->IsStoreAlive(block_entry, store)) {
744 (*env)[index] = result;
745 } else {
746 (*env)[index] = constant_null();
747 }
748 } else { 523 } else {
749 // The graph construction ensures we do not have an unused LoadLocal 524 // The graph construction ensures we do not have an unused LoadLocal
750 // computation. 525 // computation.
751 ASSERT(definition->is_used()); 526 ASSERT(definition->is_used());
752 index = load->local().BitIndexIn(num_non_copied_params_); 527 index = load->local().BitIndexIn(num_non_copied_params_);
753 result = (*env)[index];
754 528
755 PhiInstr* phi = result->AsPhi(); 529 PhiInstr* phi = (*env)[index]->AsPhi();
756 if ((phi != NULL) && !phi->is_alive()) { 530 if ((phi != NULL) && !phi->is_alive()) {
757 phi->mark_alive(); 531 phi->mark_alive();
758 live_phis->Add(phi); 532 live_phis->Add(phi);
759 } 533 }
760
761 if (variable_liveness->IsLastLoad(block_entry, load)) {
762 (*env)[index] = constant_null();
763 }
764 } 534 }
765 // Update expression stack or remove from graph. 535 // Update expression stack or remove from graph.
766 if (definition->is_used()) { 536 if (definition->is_used()) {
767 env->Add(result); 537 env->Add((*env)[index]);
768 // We remove load/store instructions when we find their use in 2a. 538 // We remove load/store instructions when we find their use in 2a.
769 } else { 539 } else {
770 it.RemoveCurrentFromGraph(); 540 it.RemoveCurrentFromGraph();
771 } 541 }
772 } else { 542 } else {
773 // Not a load or store. 543 // Not a load or store.
774 if (definition->is_used()) { 544 if (definition->is_used()) {
775 // Assign fresh SSA temporary and update expression stack. 545 // Assign fresh SSA temporary and update expression stack.
776 definition->set_ssa_temp_index(alloc_ssa_temp_index()); 546 definition->set_ssa_temp_index(alloc_ssa_temp_index());
777 env->Add(definition); 547 env->Add(definition);
778 } 548 }
779 } 549 }
780 } 550 }
781 551
782 // 2c. Handle pushed argument. 552 // 2c. Handle pushed argument.
783 PushArgumentInstr* push = current->AsPushArgument(); 553 PushArgumentInstr* push = current->AsPushArgument();
784 if (push != NULL) { 554 if (push != NULL) {
785 env->Add(push); 555 env->Add(push);
786 } 556 }
787 } 557 }
788 558
789 // 3. Process dominated blocks. 559 // 3. Process dominated blocks.
790 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { 560 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
791 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; 561 BlockEntryInstr* block = block_entry->dominated_blocks()[i];
792 GrowableArray<Definition*> new_env(env->length()); 562 GrowableArray<Definition*> new_env(env->length());
793 new_env.AddArray(*env); 563 new_env.AddArray(*env);
794 RenameRecursive(block, &new_env, live_phis, variable_liveness); 564 RenameRecursive(block, &new_env, live_phis);
795 } 565 }
796 566
797 // 4. Process successor block. We have edge-split form, so that only blocks 567 // 4. Process successor block. We have edge-split form, so that only blocks
798 // with one successor can have a join block as successor. 568 // with one successor can have a join block as successor.
799 if ((block_entry->last_instruction()->SuccessorCount() == 1) && 569 if ((block_entry->last_instruction()->SuccessorCount() == 1) &&
800 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 570 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
801 JoinEntryInstr* successor = 571 JoinEntryInstr* successor =
802 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 572 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
803 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 573 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
804 ASSERT(pred_index >= 0); 574 ASSERT(pred_index >= 0);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 if (!found) { 725 if (!found) {
956 result->Add(field); 726 result->Add(field);
957 } 727 }
958 } 728 }
959 } 729 }
960 730
961 return result; 731 return result;
962 } 732 }
963 733
964 } // namespace dart 734 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698