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

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

Issue 10828018: Add support for fixed parameters in the register allocator. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 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
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_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 2268 matching lines...) Expand 10 before | Expand all | Expand 10 after
2279 const Function& function = parsed_function().function(); 2279 const Function& function = parsed_function().function();
2280 TargetEntryInstr* normal_entry = new TargetEntryInstr(); 2280 TargetEntryInstr* normal_entry = new TargetEntryInstr();
2281 graph_entry_ = new GraphEntryInstr(normal_entry); 2281 graph_entry_ = new GraphEntryInstr(normal_entry);
2282 EffectGraphVisitor for_effect(this, 0); 2282 EffectGraphVisitor for_effect(this, 0);
2283 parsed_function().node_sequence()->Visit(&for_effect); 2283 parsed_function().node_sequence()->Visit(&for_effect);
2284 AppendFragment(normal_entry, for_effect); 2284 AppendFragment(normal_entry, for_effect);
2285 // Check that the graph is properly terminated. 2285 // Check that the graph is properly terminated.
2286 ASSERT(!for_effect.is_open()); 2286 ASSERT(!for_effect.is_open());
2287 GrowableArray<intptr_t> parent; 2287 GrowableArray<intptr_t> parent;
2288 GrowableArray<BitVector*> assigned_vars; 2288 GrowableArray<BitVector*> assigned_vars;
2289 intptr_t variable_count = parsed_function_.function().num_fixed_parameters() + 2289
2290 const intptr_t fixed_param_count =
Kevin Millikin (Google) 2012/07/26 09:29:08 fixed_parameter_count is barely longer.
Vyacheslav Egorov (Google) 2012/07/26 11:33:53 Done.
2291 parsed_function_.function().num_fixed_parameters();
2292 const intptr_t variable_count = fixed_param_count +
2290 parsed_function_.copied_parameter_count() + 2293 parsed_function_.copied_parameter_count() +
2291 parsed_function_.stack_local_count(); 2294 parsed_function_.stack_local_count();
2292 // Perform a depth-first traversal of the graph to build preorder and 2295 // Perform a depth-first traversal of the graph to build preorder and
2293 // postorder block orders. 2296 // postorder block orders.
2294 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor. 2297 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor.
2295 &preorder_block_entries_, 2298 &preorder_block_entries_,
2296 &postorder_block_entries_, 2299 &postorder_block_entries_,
2297 &parent, 2300 &parent,
2298 &assigned_vars, 2301 &assigned_vars,
2299 variable_count); 2302 variable_count,
2303 fixed_param_count);
2300 // Number blocks in reverse postorder. 2304 // Number blocks in reverse postorder.
2301 intptr_t block_count = postorder_block_entries_.length(); 2305 intptr_t block_count = postorder_block_entries_.length();
2302 for (intptr_t i = 0; i < block_count; ++i) { 2306 for (intptr_t i = 0; i < block_count; ++i) {
2303 postorder_block_entries_[i]->set_block_id(block_count - i - 1); 2307 postorder_block_entries_[i]->set_block_id(block_count - i - 1);
2304 } 2308 }
2305 2309
2306 if (for_optimized) { 2310 if (for_optimized) {
2307 // Link instructions backwards for optimized compilation. 2311 // Link instructions backwards for optimized compilation.
2308 for (intptr_t i = 0; i < block_count; ++i) { 2312 for (intptr_t i = 0; i < block_count; ++i) {
2309 BlockEntryInstr* entry = postorder_block_entries_[i]; 2313 BlockEntryInstr* entry = postorder_block_entries_[i];
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
2535 // TODO(fschneider): Support copied parameters. 2539 // TODO(fschneider): Support copied parameters.
2536 if (parsed_function().copied_parameter_count() != 0) { 2540 if (parsed_function().copied_parameter_count() != 0) {
2537 Bailout("Copied parameter support in SSA"); 2541 Bailout("Copied parameter support in SSA");
2538 } 2542 }
2539 ASSERT(var_count == (parsed_function().stack_local_count() + 2543 ASSERT(var_count == (parsed_function().stack_local_count() +
2540 parsed_function().function().num_fixed_parameters())); 2544 parsed_function().function().num_fixed_parameters()));
2541 2545
2542 // Initialize start environment. 2546 // Initialize start environment.
2543 GrowableArray<Value*> start_env(var_count); 2547 GrowableArray<Value*> start_env(var_count);
2544 intptr_t i = 0; 2548 intptr_t i = 0;
2545 for (; i < parsed_function().function().num_fixed_parameters(); ++i) { 2549 const intptr_t fixed_param_count =
2546 ParameterInstr* param = new ParameterInstr(i); 2550 parsed_function().function().num_fixed_parameters();
2551 for (; i < fixed_param_count; ++i) {
2552 ParameterInstr* param = new ParameterInstr(i - fixed_param_count);
Kevin Millikin (Google) 2012/07/26 09:29:08 I'm not thrilled with negative parameter indices h
Vyacheslav Egorov (Google) 2012/07/26 11:33:53 The index of rightmost parameter is -1 and left mo
2547 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 2553 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
2548 start_env.Add(new UseVal(param)); 2554 start_env.Add(new UseVal(param));
2549 } 2555 }
2550 2556
2551 // All locals are initialized with #null. 2557 // All locals are initialized with #null.
2552 Value* null_value = new ConstantVal(Object::ZoneHandle()); 2558 Value* null_value = new ConstantVal(Object::ZoneHandle());
2553 for (; i < var_count; i++) { 2559 for (; i < var_count; i++) {
2554 start_env.Add(null_value); 2560 start_env.Add(null_value);
2555 } 2561 }
2556 graph_entry_->set_start_env(new Environment(start_env)); 2562 graph_entry_->set_start_env(new Environment(start_env, fixed_param_count));
2557 2563
2558 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); 2564 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
2559 ASSERT(normal_entry != NULL); // Must have entry. 2565 ASSERT(normal_entry != NULL); // Must have entry.
2560 GrowableArray<Value*> env(var_count); 2566 GrowableArray<Value*> env(var_count);
2561 env.AddArray(start_env); 2567 env.AddArray(start_env);
2562 RenameRecursive(normal_entry, &env, var_count); 2568 RenameRecursive(normal_entry,
2569 &env,
2570 var_count,
2571 parsed_function().function().num_fixed_parameters());
Kevin Millikin (Google) 2012/07/26 09:29:08 Can this be just fixed_param[eter]_count?
Vyacheslav Egorov (Google) 2012/07/26 11:33:53 Done.
2563 } 2572 }
2564 2573
2565 2574
2566 // Helper to a copy a value iff it is a UseVal. 2575 // Helper to a copy a value iff it is a UseVal.
2567 static Value* CopyValue(Value* value) { 2576 static Value* CopyValue(Value* value) {
2568 return value->IsUse() 2577 return value->IsUse()
2569 ? new UseVal(value->AsUse()->definition()) 2578 ? new UseVal(value->AsUse()->definition())
2570 : value; 2579 : value;
2571 } 2580 }
2572 2581
2573 2582
2574 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, 2583 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry,
2575 GrowableArray<Value*>* env, 2584 GrowableArray<Value*>* env,
2576 intptr_t var_count) { 2585 intptr_t var_count,
2586 intptr_t fixed_param_count) {
2577 // 1. Process phis first. 2587 // 1. Process phis first.
2578 if (block_entry->IsJoinEntry()) { 2588 if (block_entry->IsJoinEntry()) {
2579 JoinEntryInstr* join = block_entry->AsJoinEntry(); 2589 JoinEntryInstr* join = block_entry->AsJoinEntry();
2580 if (join->phis() != NULL) { 2590 if (join->phis() != NULL) {
2581 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 2591 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
2582 PhiInstr* phi = (*join->phis())[i]; 2592 PhiInstr* phi = (*join->phis())[i];
2583 if (phi != NULL) { 2593 if (phi != NULL) {
2584 (*env)[i] = new UseVal(phi); 2594 (*env)[i] = new UseVal(phi);
2585 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 2595 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
2586 } 2596 }
2587 } 2597 }
2588 } 2598 }
2589 } 2599 }
2590 2600
2591 // 2. Process normal instructions. 2601 // 2. Process normal instructions.
2592 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 2602 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
2593 Instruction* current = it.Current(); 2603 Instruction* current = it.Current();
2594 // Attach current environment to the instruction. 2604 // Attach current environment to the instruction.
2595 // TODO(fschneider): Currently each instruction gets a full copy of the 2605 // TODO(fschneider): Currently each instruction gets a full copy of the
2596 // environment. This should be optimized: Only instructions that can 2606 // environment. This should be optimized: Only instructions that can
2597 // deoptimize should have uses of the environment values. 2607 // deoptimize should have uses of the environment values.
2598 current->set_env(new Environment(*env)); 2608 current->set_env(new Environment(*env, fixed_param_count));
2599 2609
2600 // 2a. Handle uses: 2610 // 2a. Handle uses:
2601 // Update expression stack environment for each use. 2611 // Update expression stack environment for each use.
2602 // For each use of a LoadLocal or StoreLocal: Replace it with the value 2612 // For each use of a LoadLocal or StoreLocal: Replace it with the value
2603 // from the environment. 2613 // from the environment.
2604 for (intptr_t i = 0; i < current->InputCount(); ++i) { 2614 for (intptr_t i = 0; i < current->InputCount(); ++i) {
2605 Value* v = current->InputAt(i); 2615 Value* v = current->InputAt(i);
2606 if (!v->IsUse()) continue; 2616 if (!v->IsUse()) continue;
2607 // Update expression stack. 2617 // Update expression stack.
2608 ASSERT(env->length() > var_count); 2618 ASSERT(env->length() > var_count);
2609 env->RemoveLast(); 2619 env->RemoveLast();
2610 BindInstr* as_bind = v->AsUse()->definition()->AsBind(); 2620 BindInstr* as_bind = v->AsUse()->definition()->AsBind();
2611 if ((as_bind != NULL) && as_bind->computation()->IsLoadLocal()) { 2621 if ((as_bind != NULL) && as_bind->computation()->IsLoadLocal()) {
2612 Computation* comp = as_bind->computation(); 2622 Computation* comp = as_bind->computation();
2613 intptr_t index = comp->AsLoadLocal()->local().BitIndexIn(var_count); 2623 intptr_t index =
2624 comp->AsLoadLocal()->local().BitIndexIn(fixed_param_count);
2614 current->SetInputAt(i, CopyValue((*env)[index])); 2625 current->SetInputAt(i, CopyValue((*env)[index]));
2615 } 2626 }
2616 if ((as_bind != NULL) && as_bind->computation()->IsStoreLocal()) { 2627 if ((as_bind != NULL) && as_bind->computation()->IsStoreLocal()) {
2617 // For each use of a StoreLocal: Replace it with the value from the 2628 // For each use of a StoreLocal: Replace it with the value from the
2618 // environment. 2629 // environment.
2619 Computation* comp = as_bind->computation(); 2630 Computation* comp = as_bind->computation();
2620 intptr_t index = comp->AsStoreLocal()->local().BitIndexIn(var_count); 2631 intptr_t index =
2632 comp->AsStoreLocal()->local().BitIndexIn(fixed_param_count);
2621 current->SetInputAt(i, CopyValue((*env)[index])); 2633 current->SetInputAt(i, CopyValue((*env)[index]));
2622 } 2634 }
2623 } 2635 }
2624 2636
2625 // 2b. Handle LoadLocal and StoreLocal. 2637 // 2b. Handle LoadLocal and StoreLocal.
2626 // For each LoadLocal: Remove it from the graph. 2638 // For each LoadLocal: Remove it from the graph.
2627 // For each StoreLocal: Remove it from the graph and update the environment. 2639 // For each StoreLocal: Remove it from the graph and update the environment.
2628 BindInstr* bind = current->AsBind(); 2640 BindInstr* bind = current->AsBind();
2629 if (bind != NULL) { 2641 if (bind != NULL) {
2630 LoadLocalComp* load = bind->computation()->AsLoadLocal(); 2642 LoadLocalComp* load = bind->computation()->AsLoadLocal();
2631 StoreLocalComp* store = bind->computation()->AsStoreLocal(); 2643 StoreLocalComp* store = bind->computation()->AsStoreLocal();
2632 if ((load != NULL) || (store != NULL)) { 2644 if ((load != NULL) || (store != NULL)) {
2633 intptr_t index; 2645 intptr_t index;
2634 if (store != NULL) { 2646 if (store != NULL) {
2635 index = store->local().BitIndexIn(var_count); 2647 index = store->local().BitIndexIn(fixed_param_count);
2636 // Update renaming environment. 2648 // Update renaming environment.
2637 (*env)[index] = store->value(); 2649 (*env)[index] = store->value();
2638 } else { 2650 } else {
2639 // The graph construction ensures we do not have an unused LoadLocal 2651 // The graph construction ensures we do not have an unused LoadLocal
2640 // computation. 2652 // computation.
2641 ASSERT(bind->is_used()); 2653 ASSERT(bind->is_used());
2642 index = load->local().BitIndexIn(var_count); 2654 index = load->local().BitIndexIn(fixed_param_count);
2643 } 2655 }
2644 // Update expression stack and remove from graph. 2656 // Update expression stack and remove from graph.
2645 if (bind->is_used()) { 2657 if (bind->is_used()) {
2646 env->Add(CopyValue((*env)[index])); 2658 env->Add(CopyValue((*env)[index]));
2647 } 2659 }
2648 it.RemoveCurrentFromGraph(); 2660 it.RemoveCurrentFromGraph();
2649 } else { 2661 } else {
2650 // Not a load or store. 2662 // Not a load or store.
2651 if (bind->is_used()) { 2663 if (bind->is_used()) {
2652 // Assign fresh SSA temporary and update expression stack. 2664 // Assign fresh SSA temporary and update expression stack.
2653 bind->set_ssa_temp_index(alloc_ssa_temp_index()); 2665 bind->set_ssa_temp_index(alloc_ssa_temp_index());
2654 env->Add(new UseVal(bind)); 2666 env->Add(new UseVal(bind));
2655 } 2667 }
2656 } 2668 }
2657 } 2669 }
2658 } 2670 }
2659 2671
2660 // 3. Process dominated blocks. 2672 // 3. Process dominated blocks.
2661 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { 2673 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
2662 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; 2674 BlockEntryInstr* block = block_entry->dominated_blocks()[i];
2663 GrowableArray<Value*> new_env(env->length()); 2675 GrowableArray<Value*> new_env(env->length());
2664 new_env.AddArray(*env); 2676 new_env.AddArray(*env);
2665 RenameRecursive(block, &new_env, var_count); 2677 RenameRecursive(block, &new_env, var_count, fixed_param_count);
2666 } 2678 }
2667 2679
2668 // 4. Process successor block. We have edge-split form, so that only blocks 2680 // 4. Process successor block. We have edge-split form, so that only blocks
2669 // with one successor can have a join block as successor. 2681 // with one successor can have a join block as successor.
2670 if ((block_entry->last_instruction()->SuccessorCount() == 1) && 2682 if ((block_entry->last_instruction()->SuccessorCount() == 1) &&
2671 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 2683 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
2672 JoinEntryInstr* successor = 2684 JoinEntryInstr* successor =
2673 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 2685 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
2674 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 2686 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
2675 ASSERT(pred_index >= 0); 2687 ASSERT(pred_index >= 0);
(...skipping 20 matching lines...) Expand all
2696 char* chars = reinterpret_cast<char*>( 2708 char* chars = reinterpret_cast<char*>(
2697 Isolate::Current()->current_zone()->Allocate(len)); 2709 Isolate::Current()->current_zone()->Allocate(len));
2698 OS::SNPrint(chars, len, kFormat, function_name, reason); 2710 OS::SNPrint(chars, len, kFormat, function_name, reason);
2699 const Error& error = Error::Handle( 2711 const Error& error = Error::Handle(
2700 LanguageError::New(String::Handle(String::New(chars)))); 2712 LanguageError::New(String::Handle(String::New(chars))));
2701 Isolate::Current()->long_jump_base()->Jump(1, error); 2713 Isolate::Current()->long_jump_base()->Jump(1, error);
2702 } 2714 }
2703 2715
2704 2716
2705 } // namespace dart 2717 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698