Chromium Code Reviews| 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_builder.h" | 5 #include "vm/flow_graph_builder.h" |
| 6 | 6 |
| 7 #include "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
| 8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
| 9 #include "vm/code_descriptors.h" | 9 #include "vm/code_descriptors.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 DECLARE_FLAG(bool, enable_type_checks); | 28 DECLARE_FLAG(bool, enable_type_checks); |
| 29 | 29 |
| 30 | 30 |
| 31 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function) | 31 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function) |
| 32 : parsed_function_(parsed_function), | 32 : parsed_function_(parsed_function), |
| 33 preorder_block_entries_(), | 33 preorder_block_entries_(), |
| 34 postorder_block_entries_(), | 34 postorder_block_entries_(), |
| 35 context_level_(0), | 35 context_level_(0), |
| 36 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), | 36 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), |
| 37 try_index_(CatchClauseNode::kInvalidTryIndex), | 37 try_index_(CatchClauseNode::kInvalidTryIndex), |
| 38 graph_entry_(NULL) { } | 38 graph_entry_(NULL), |
| 39 current_ssa_temp_index_(0) { } | |
| 39 | 40 |
| 40 | 41 |
| 41 void FlowGraphBuilder::AddCatchEntry(TargetEntryInstr* entry) { | 42 void FlowGraphBuilder::AddCatchEntry(TargetEntryInstr* entry) { |
| 42 graph_entry_->AddCatchEntry(entry); | 43 graph_entry_->AddCatchEntry(entry); |
| 43 } | 44 } |
| 44 | 45 |
| 45 | 46 |
| 46 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { | 47 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { |
| 47 ASSERT(is_open()); | 48 ASSERT(is_open()); |
| 48 if (other_fragment.is_empty()) return; | 49 if (other_fragment.is_empty()) return; |
| (...skipping 2292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2341 for (intptr_t i = 0; i < block_count; ++i) { | 2342 for (intptr_t i = 0; i < block_count; ++i) { |
| 2342 postorder_block_entries_[i]->set_block_id(block_count - i - 1); | 2343 postorder_block_entries_[i]->set_block_id(block_count - i - 1); |
| 2343 } | 2344 } |
| 2344 if (for_optimized && FLAG_use_ssa) { | 2345 if (for_optimized && FLAG_use_ssa) { |
| 2345 GrowableArray<BitVector*> dominance_frontier; | 2346 GrowableArray<BitVector*> dominance_frontier; |
| 2346 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); | 2347 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); |
| 2347 InsertPhis(preorder_block_entries_, | 2348 InsertPhis(preorder_block_entries_, |
| 2348 assigned_vars, | 2349 assigned_vars, |
| 2349 variable_count, | 2350 variable_count, |
| 2350 dominance_frontier); | 2351 dominance_frontier); |
| 2351 // TODO(fschneider): Perform SSA renaming. | 2352 Rename(variable_count); |
| 2352 } | 2353 } |
| 2353 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { | 2354 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { |
| 2354 intptr_t length = postorder_block_entries_.length(); | 2355 intptr_t length = postorder_block_entries_.length(); |
| 2355 GrowableArray<BlockEntryInstr*> reverse_postorder(length); | 2356 GrowableArray<BlockEntryInstr*> reverse_postorder(length); |
| 2356 for (intptr_t i = length - 1; i >= 0; --i) { | 2357 for (intptr_t i = length - 1; i >= 0; --i) { |
| 2357 reverse_postorder.Add(postorder_block_entries_[i]); | 2358 reverse_postorder.Add(postorder_block_entries_[i]); |
| 2358 } | 2359 } |
| 2359 if (FLAG_print_flow_graph) { | 2360 if (FLAG_print_flow_graph) { |
| 2360 // Print flow graph to stdout. | 2361 // Print flow graph to stdout. |
| 2361 FlowGraphPrinter printer(function, reverse_postorder); | 2362 FlowGraphPrinter printer(function, reverse_postorder); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2547 work[index] = var_index; | 2548 work[index] = var_index; |
| 2548 worklist.Add(block); | 2549 worklist.Add(block); |
| 2549 } | 2550 } |
| 2550 } | 2551 } |
| 2551 } | 2552 } |
| 2552 } | 2553 } |
| 2553 } | 2554 } |
| 2554 } | 2555 } |
| 2555 | 2556 |
| 2556 | 2557 |
| 2558 void FlowGraphBuilder::Rename(intptr_t var_count) { | |
| 2559 // Initialize start environment: | |
| 2560 // All locals are initialized with #null. | |
| 2561 // TODO(fschneider): Support paramters. All parameters are initially located | |
|
srdjan
2012/06/18 18:04:38
parameters
Florian Schneider
2012/06/19 11:26:40
Done.
| |
| 2562 // on the stack. | |
| 2563 ZoneGrowableArray<Value*>* start_env = | |
| 2564 new ZoneGrowableArray<Value*>(var_count); | |
| 2565 if (parsed_function().function().num_fixed_parameters() > 0) { | |
| 2566 Bailout("Fixed parameter support in SSA"); | |
| 2567 } | |
| 2568 if (parsed_function().copied_parameter_count()) { | |
| 2569 Bailout("Copied parameter support in SSA"); | |
| 2570 } | |
| 2571 Value* null_value = new ConstantVal(Object::ZoneHandle()); | |
| 2572 ASSERT(var_count == parsed_function().stack_local_count()); | |
|
srdjan
2012/06/18 18:04:38
Why don't you use stack_local_count instead of pas
Florian Schneider
2012/06/19 11:26:40
Yes, in one of the next CLs it will change to:
va
| |
| 2573 for (intptr_t i = 0; i < var_count; i++) { | |
| 2574 start_env->Add(null_value); | |
| 2575 } | |
| 2576 graph_entry_->set_start_env(start_env); | |
| 2577 | |
| 2578 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); | |
| 2579 ASSERT(normal_entry != NULL); // Graph entry is empty. | |
|
srdjan
2012/06/18 18:04:38
Maybe change comment to: "Must have entry" or simi
Florian Schneider
2012/06/19 11:26:40
Done.
| |
| 2580 ZoneGrowableArray<Value*>* env = new ZoneGrowableArray<Value*>(var_count); | |
| 2581 env->AddArray(*start_env); | |
| 2582 RenameRecursive(normal_entry, env, var_count); | |
| 2583 } | |
| 2584 | |
| 2585 | |
| 2586 static intptr_t WhichPred(BlockEntryInstr* predecessor, | |
| 2587 JoinEntryInstr* join_block) { | |
| 2588 for (intptr_t i = 0; i < join_block->PredecessorCount(); ++i) { | |
| 2589 if (join_block->PredecessorAt(i) == predecessor) return i; | |
| 2590 } | |
| 2591 UNREACHABLE(); | |
| 2592 return -1; | |
| 2593 } | |
| 2594 | |
| 2595 | |
| 2596 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, | |
| 2597 ZoneGrowableArray<Value*>* env, | |
| 2598 intptr_t var_count) { | |
| 2599 // Iterate over instructions. | |
| 2600 // 1. Handle phis first. | |
| 2601 if (block_entry->IsJoinEntry()) { | |
| 2602 JoinEntryInstr* join = block_entry->AsJoinEntry(); | |
| 2603 if (join->phis() != NULL) { | |
|
srdjan
2012/06/18 18:04:38
ASSERT(join->phis() != NULL) ?
Florian Schneider
2012/06/19 11:26:40
Right now I lazily allocate the phis() array when
| |
| 2604 for (intptr_t i = 0; i < join->phis()->length(); ++i) { | |
| 2605 PhiInstr* phi = (*join->phis())[i]; | |
| 2606 if (phi != NULL) { | |
| 2607 (*env)[i] = new UseVal(phi); | |
| 2608 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp. | |
| 2609 } | |
| 2610 } | |
| 2611 } | |
| 2612 } | |
| 2613 | |
| 2614 // 2. Handle normal instructions. | |
| 2615 Instruction* current = block_entry->StraightLineSuccessor(); | |
| 2616 Instruction* prev = block_entry; | |
| 2617 while (current != NULL && !current->IsBlockEntry()) { | |
|
srdjan
2012/06/18 18:04:38
add parenthesis
Florian Schneider
2012/06/19 11:26:40
Done.
| |
| 2618 // 2a. Handle LoadLocal and StoreLocal. | |
| 2619 LoadLocalComp* load = NULL; | |
| 2620 if (current->IsDo() && | |
| 2621 current->AsDo()->computation()->IsLoadLocal()) { | |
| 2622 load = current->AsDo()->computation()->AsLoadLocal(); | |
|
srdjan
2012/06/18 18:04:38
A LoadLocal in a Do has no side effect and can be
Florian Schneider
2012/06/19 11:26:40
Yes. I remove it from the graph below, but better
| |
| 2623 } else if (current->IsBind() && | |
| 2624 current->AsBind()->computation()->IsLoadLocal()) { | |
| 2625 load = current->AsBind()->computation()->AsLoadLocal(); | |
| 2626 } | |
| 2627 StoreLocalComp* store = NULL; | |
| 2628 if (current->IsDo() && | |
| 2629 current->AsDo()->computation()->IsStoreLocal()) { | |
| 2630 store = current->AsDo()->computation()->AsStoreLocal(); | |
| 2631 } else if (current->IsBind() && | |
| 2632 current->AsBind()->computation()->IsStoreLocal()) { | |
| 2633 store = current->AsBind()->computation()->AsStoreLocal(); | |
| 2634 } | |
| 2635 | |
| 2636 if (load != NULL || store != NULL) { | |
|
srdjan
2012/06/18 18:04:38
Add parenthesis
Florian Schneider
2012/06/19 11:26:40
Done.
| |
| 2637 // Remove instruction with LoadLocal or StoreLocal. | |
| 2638 prev->SetSuccessor(current->StraightLineSuccessor()); | |
| 2639 // Update renaming environment for StoreLocal. | |
| 2640 if (store != NULL) { | |
| 2641 (*env)[store->local().BitIndexIn(var_count)] = store->value(); | |
| 2642 } | |
| 2643 } else { | |
| 2644 // Assign new SSA temporary. | |
| 2645 if (current->IsBind()) { | |
| 2646 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); | |
| 2647 } | |
| 2648 } | |
| 2649 | |
| 2650 // 2b. Handle uses of LoadLocal / StoreLocal | |
| 2651 for (intptr_t i = 0; i < current->InputCount(); ++i) { | |
| 2652 // For each use of a LoadLocal/StoreLocal: Replace it with the definition | |
| 2653 // from the enviroment. | |
|
srdjan
2012/06/18 18:04:38
environment
Florian Schneider
2012/06/19 11:26:40
Done.
| |
| 2654 Value* v = current->InputAt(i); | |
| 2655 if (v->IsUse() && | |
| 2656 v->AsUse()->definition()->IsBind() && | |
| 2657 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { | |
| 2658 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); | |
| 2659 intptr_t index = comp->AsLoadLocal()->local().BitIndexIn(var_count); | |
| 2660 Value* new_value = (*env)[index]; | |
| 2661 // Make a copy if it is a UseVal. | |
| 2662 if (new_value->IsUse()) { | |
| 2663 new_value = new UseVal(new_value->AsUse()->definition()); | |
| 2664 } | |
| 2665 current->SetInputAt(i, new_value); | |
| 2666 } | |
| 2667 if (v->IsUse() && | |
| 2668 v->AsUse()->definition()->IsBind() && | |
| 2669 v->AsUse()->definition()->AsBind()->computation()->IsStoreLocal()) { | |
| 2670 // For each use of a LoadLocal: Replace LoadLocal with the definition | |
| 2671 // from the enviroment. | |
| 2672 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); | |
| 2673 intptr_t index = comp->AsStoreLocal()->local().BitIndexIn(var_count); | |
| 2674 Value* new_value = (*env)[index]; | |
| 2675 // Make a copy if it is a UseVal. | |
| 2676 if (new_value->IsUse()) { | |
| 2677 new_value = new UseVal(new_value->AsUse()->definition()); | |
| 2678 } | |
| 2679 current->SetInputAt(i, new_value); | |
| 2680 } | |
| 2681 } | |
| 2682 | |
| 2683 // Update previous only if no instruction was removed from the graph. | |
| 2684 if (load == NULL && store == NULL) { | |
|
srdjan
2012/06/18 18:04:38
parenthesis
Florian Schneider
2012/06/19 11:26:40
Done.
| |
| 2685 prev = current; | |
| 2686 } | |
| 2687 current = current->StraightLineSuccessor(); | |
| 2688 } | |
| 2689 | |
| 2690 // 3. Process dominated blocks. | |
| 2691 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { | |
| 2692 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; | |
| 2693 ZoneGrowableArray<Value*>* new_env = | |
| 2694 new ZoneGrowableArray<Value*>(var_count); | |
| 2695 new_env->AddArray(*env); | |
| 2696 RenameRecursive(block, new_env, var_count); | |
| 2697 } | |
| 2698 | |
| 2699 // 4. Process successor block. We have edge-split form, so that only blocks | |
| 2700 // with one successor can have a join block as successor. | |
| 2701 if (block_entry->last_instruction()->SuccessorCount() == 1 && | |
|
srdjan
2012/06/18 18:04:38
ditto
Florian Schneider
2012/06/19 11:26:40
Done.
| |
| 2702 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { | |
| 2703 JoinEntryInstr* successor = | |
| 2704 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); | |
| 2705 intptr_t pred_index = WhichPred(block_entry, successor); | |
| 2706 if (successor->phis() != NULL) { | |
| 2707 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { | |
| 2708 PhiInstr* phi = (*successor->phis())[i]; | |
| 2709 if (phi != NULL) phi->SetInputAt(pred_index, (*env)[i]); | |
| 2710 } | |
| 2711 } | |
| 2712 } | |
| 2713 } | |
| 2714 | |
| 2715 | |
| 2557 void FlowGraphBuilder::Bailout(const char* reason) { | 2716 void FlowGraphBuilder::Bailout(const char* reason) { |
| 2558 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 2717 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
| 2559 const char* function_name = parsed_function_.function().ToCString(); | 2718 const char* function_name = parsed_function_.function().ToCString(); |
| 2560 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 2719 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 2561 char* chars = reinterpret_cast<char*>( | 2720 char* chars = reinterpret_cast<char*>( |
| 2562 Isolate::Current()->current_zone()->Allocate(len)); | 2721 Isolate::Current()->current_zone()->Allocate(len)); |
| 2563 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2722 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2564 const Error& error = Error::Handle( | 2723 const Error& error = Error::Handle( |
| 2565 LanguageError::New(String::Handle(String::New(chars)))); | 2724 LanguageError::New(String::Handle(String::New(chars)))); |
| 2566 Isolate::Current()->long_jump_base()->Jump(1, error); | 2725 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2567 } | 2726 } |
| 2568 | 2727 |
| 2569 | 2728 |
| 2570 } // namespace dart | 2729 } // namespace dart |
| OLD | NEW |