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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 curr = curr->next_use(); | 163 curr = curr->next_use(); |
164 } | 164 } |
165 | 165 |
166 prev = NULL; | 166 prev = NULL; |
167 curr = defn->env_use_list(); | 167 curr = defn->env_use_list(); |
168 while (curr != NULL) { | 168 while (curr != NULL) { |
169 ASSERT(prev == curr->previous_use()); | 169 ASSERT(prev == curr->previous_use()); |
170 ASSERT(defn == curr->definition()); | 170 ASSERT(defn == curr->definition()); |
171 Instruction* instr = curr->instruction(); | 171 Instruction* instr = curr->instruction(); |
172 ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index())); | 172 ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index())); |
173 ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) || | 173 // BlockEntry instructions have environments attached to them but |
| 174 // have no reliable way to verify if they are still in the graph. |
| 175 // Thus we just assume they are. |
| 176 ASSERT(instr->IsBlockEntry() || |
| 177 (instr->IsPhi() && instr->AsPhi()->is_alive()) || |
174 (instr->previous() != NULL)); | 178 (instr->previous() != NULL)); |
175 prev = curr; | 179 prev = curr; |
176 curr = curr->next_use(); | 180 curr = curr->next_use(); |
177 } | 181 } |
178 } | 182 } |
179 } | 183 } |
180 | 184 |
181 | 185 |
182 bool FlowGraph::VerifyUseLists() { | 186 bool FlowGraph::VerifyUseLists() { |
183 // Verify the initial definitions. | 187 // Verify the initial definitions. |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { | 438 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { |
435 env.Add(constant_null()); | 439 env.Add(constant_null()); |
436 } | 440 } |
437 | 441 |
438 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); | 442 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); |
439 ASSERT(normal_entry != NULL); // Must have entry. | 443 ASSERT(normal_entry != NULL); // Must have entry. |
440 RenameRecursive(normal_entry, &env, live_phis); | 444 RenameRecursive(normal_entry, &env, live_phis); |
441 } | 445 } |
442 | 446 |
443 | 447 |
| 448 void FlowGraph::AttachEnvironment(Instruction* instr, |
| 449 GrowableArray<Definition*>* env) { |
| 450 Environment* deopt_env = |
| 451 Environment::From(*env, |
| 452 num_non_copied_params_, |
| 453 parsed_function_.function()); |
| 454 instr->SetEnvironment(deopt_env); |
| 455 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { |
| 456 Value* use = it.CurrentValue(); |
| 457 use->definition()->AddEnvUse(use); |
| 458 } |
| 459 if (instr->CanDeoptimize()) { |
| 460 instr->env()->set_deopt_id(instr->deopt_id()); |
| 461 } |
| 462 } |
| 463 |
| 464 |
444 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, | 465 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, |
445 GrowableArray<Definition*>* env, | 466 GrowableArray<Definition*>* env, |
446 GrowableArray<PhiInstr*>* live_phis) { | 467 GrowableArray<PhiInstr*>* live_phis) { |
447 // 1. Process phis first. | 468 // 1. Process phis first. |
448 if (block_entry->IsJoinEntry()) { | 469 if (block_entry->IsJoinEntry()) { |
449 JoinEntryInstr* join = block_entry->AsJoinEntry(); | 470 JoinEntryInstr* join = block_entry->AsJoinEntry(); |
450 if (join->phis() != NULL) { | 471 if (join->phis() != NULL) { |
451 for (intptr_t i = 0; i < join->phis()->length(); ++i) { | 472 for (intptr_t i = 0; i < join->phis()->length(); ++i) { |
452 PhiInstr* phi = (*join->phis())[i]; | 473 PhiInstr* phi = (*join->phis())[i]; |
453 if (phi != NULL) { | 474 if (phi != NULL) { |
454 (*env)[i] = phi; | 475 (*env)[i] = phi; |
455 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 476 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
456 } | 477 } |
457 } | 478 } |
458 } | 479 } |
459 } | 480 } |
460 | 481 |
| 482 // Attach environment to the block entry. |
| 483 AttachEnvironment(block_entry, env); |
| 484 |
461 // 2. Process normal instructions. | 485 // 2. Process normal instructions. |
| 486 |
462 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { | 487 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { |
463 Instruction* current = it.Current(); | 488 Instruction* current = it.Current(); |
464 // Attach current environment to the instructions that can deoptimize and | 489 |
465 // at goto instructions. Optimizations like LICM expect an environment at | 490 // Attach current environment to the instructions that need it. |
466 // gotos. | 491 if (current->NeedsEnvironment()) { |
467 if (current->CanDeoptimize() || current->IsGoto()) { | 492 AttachEnvironment(current, env); |
468 Environment* deopt_env = | |
469 Environment::From(*env, | |
470 num_non_copied_params_, | |
471 parsed_function_.function()); | |
472 current->SetEnvironment(deopt_env); | |
473 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { | |
474 Value* use = it.CurrentValue(); | |
475 use->definition()->AddEnvUse(use); | |
476 } | |
477 } | |
478 if (current->CanDeoptimize()) { | |
479 current->env()->set_deopt_id(current->deopt_id()); | |
480 } | 493 } |
481 | 494 |
482 // 2a. Handle uses: | 495 // 2a. Handle uses: |
483 // Update expression stack environment for each use. | 496 // Update expression stack environment for each use. |
484 // For each use of a LoadLocal or StoreLocal: Replace it with the value | 497 // For each use of a LoadLocal or StoreLocal: Replace it with the value |
485 // from the environment. | 498 // from the environment. |
486 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { | 499 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { |
487 Value* v = current->InputAt(i); | 500 Value* v = current->InputAt(i); |
488 // Update expression stack. | 501 // Update expression stack. |
489 ASSERT(env->length() > variable_count()); | 502 ASSERT(env->length() > variable_count()); |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 if (!found) { | 738 if (!found) { |
726 result->Add(field); | 739 result->Add(field); |
727 } | 740 } |
728 } | 741 } |
729 } | 742 } |
730 | 743 |
731 return result; | 744 return result; |
732 } | 745 } |
733 | 746 |
734 } // namespace dart | 747 } // namespace dart |
OLD | NEW |