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

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

Issue 11856010: Change the inlining context from an enum to a class. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 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/code_descriptors.h" 8 #include "vm/code_descriptors.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flags.h" 10 #include "vm/flags.h"
(...skipping 13 matching lines...) Expand all
24 "Eliminate type checks when allowed by static type analysis."); 24 "Eliminate type checks when allowed by static type analysis.");
25 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); 25 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
26 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); 26 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph.");
27 DEFINE_FLAG(bool, print_flow_graph_optimized, false, 27 DEFINE_FLAG(bool, print_flow_graph_optimized, false,
28 "Print the IR flow graph when optimizing."); 28 "Print the IR flow graph when optimizing.");
29 DEFINE_FLAG(bool, trace_type_check_elimination, false, 29 DEFINE_FLAG(bool, trace_type_check_elimination, false,
30 "Trace type check elimination at compile time."); 30 "Trace type check elimination at compile time.");
31 DECLARE_FLAG(bool, enable_type_checks); 31 DECLARE_FLAG(bool, enable_type_checks);
32 32
33 33
34 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function) 34 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function,
35 InliningContext* inlining_context)
35 : parsed_function_(parsed_function), 36 : parsed_function_(parsed_function),
36 num_copied_params_(parsed_function.num_copied_params()), 37 num_copied_params_(parsed_function.num_copied_params()),
37 // All parameters are copied if any parameter is. 38 // All parameters are copied if any parameter is.
38 num_non_copied_params_((num_copied_params_ == 0) 39 num_non_copied_params_((num_copied_params_ == 0)
39 ? parsed_function.function().num_fixed_parameters() 40 ? parsed_function.function().num_fixed_parameters()
40 : 0), 41 : 0),
41 num_stack_locals_(parsed_function.num_stack_locals()), 42 num_stack_locals_(parsed_function.num_stack_locals()),
43 inlining_context_(inlining_context),
42 last_used_block_id_(0), // 0 is used for the graph entry. 44 last_used_block_id_(0), // 0 is used for the graph entry.
43 context_level_(0), 45 context_level_(0),
44 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), 46 last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
45 try_index_(CatchClauseNode::kInvalidTryIndex), 47 try_index_(CatchClauseNode::kInvalidTryIndex),
46 graph_entry_(NULL), 48 graph_entry_(NULL) { }
47 inlining_context_(kNotInlining),
48 exits_(NULL) { }
49 49
50 50
51 void FlowGraphBuilder::AddCatchEntry(TargetEntryInstr* entry) { 51 void FlowGraphBuilder::AddCatchEntry(TargetEntryInstr* entry) {
52 graph_entry_->AddCatchEntry(entry); 52 graph_entry_->AddCatchEntry(entry);
53 } 53 }
54 54
55 55
56 void ValueInliningContext::AddExit(ReturnInstr* exit) {
57 Data data = { NULL, exit };
58 exits_.Add(data);
59 }
60
61
62 int ValueInliningContext::LowestBlockIdFirst(const Data* a, const Data* b) {
63 return (a->exit_block->block_id() - b->exit_block->block_id());
64 }
65
66
67 void ValueInliningContext::SortExits() {
68 // Assign block entries here because we did not necessarily know them when
69 // the return exit was added to the array.
70 for (int i = 0; i < exits_.length(); ++i) {
71 exits_[i].exit_block = exits_[i].exit_return->GetBlock();
72 }
73 exits_.Sort(LowestBlockIdFirst);
74 }
75
76
56 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { 77 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) {
57 ASSERT(is_open()); 78 ASSERT(is_open());
58 if (other_fragment.is_empty()) return; 79 if (other_fragment.is_empty()) return;
59 if (is_empty()) { 80 if (is_empty()) {
60 entry_ = other_fragment.entry(); 81 entry_ = other_fragment.entry();
61 exit_ = other_fragment.exit(); 82 exit_ = other_fragment.exit();
62 } else { 83 } else {
63 exit()->LinkTo(other_fragment.entry()); 84 exit()->LinkTo(other_fragment.entry());
64 exit_ = other_fragment.exit(); 85 exit_ = other_fragment.exit();
65 } 86 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 DeallocateTempIndex(instruction->InputCount()); 123 DeallocateTempIndex(instruction->InputCount());
103 if (is_empty()) { 124 if (is_empty()) {
104 entry_ = exit_ = instruction; 125 entry_ = exit_ = instruction;
105 } else { 126 } else {
106 exit()->LinkTo(instruction); 127 exit()->LinkTo(instruction);
107 exit_ = instruction; 128 exit_ = instruction;
108 } 129 }
109 } 130 }
110 131
111 132
133 void EffectGraphVisitor::AddReturnExit(intptr_t token_pos, Value* value) {
134 ASSERT(is_open());
135 ReturnInstr* return_instr = new ReturnInstr(token_pos, value);
136 AddInstruction(return_instr);
137 InliningContext* inlining_context = owner()->inlining_context();
138 if (inlining_context != NULL) {
139 inlining_context->AddExit(return_instr);
140 }
141 CloseFragment();
142 }
143
144
112 void EffectGraphVisitor::Goto(JoinEntryInstr* join) { 145 void EffectGraphVisitor::Goto(JoinEntryInstr* join) {
113 ASSERT(is_open()); 146 ASSERT(is_open());
114 if (is_empty()) { 147 if (is_empty()) {
115 entry_ = new GotoInstr(join); 148 entry_ = new GotoInstr(join);
116 } else { 149 } else {
117 exit()->Goto(join); 150 exit()->Goto(join);
118 } 151 }
119 exit_ = NULL; 152 exit_ = NULL;
120 } 153 }
121 154
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
519 ASSERT(current_context_level >= 0); 552 ASSERT(current_context_level >= 0);
520 if (owner()->parsed_function().saved_context_var() != NULL) { 553 if (owner()->parsed_function().saved_context_var() != NULL) {
521 // CTX on entry was saved, but not linked as context parent. 554 // CTX on entry was saved, but not linked as context parent.
522 BuildLoadContext(*owner()->parsed_function().saved_context_var()); 555 BuildLoadContext(*owner()->parsed_function().saved_context_var());
523 } else { 556 } else {
524 while (current_context_level-- > 0) { 557 while (current_context_level-- > 0) {
525 UnchainContext(); 558 UnchainContext();
526 } 559 }
527 } 560 }
528 561
529 ReturnInstr* return_instr = new ReturnInstr(node->token_pos(), return_value); 562 AddReturnExit(node->token_pos(), return_value);
530 AddReturnExit(return_instr);
531 AddInstruction(return_instr);
532 CloseFragment();
533 } 563 }
534 564
535 565
536 // <Expression> ::= Literal { literal: Instance } 566 // <Expression> ::= Literal { literal: Instance }
537 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) { 567 void EffectGraphVisitor::VisitLiteralNode(LiteralNode* node) {
538 return; 568 return;
539 } 569 }
540 570
541 571
542 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) { 572 void ValueGraphVisitor::VisitLiteralNode(LiteralNode* node) {
(...skipping 2480 matching lines...) Expand 10 before | Expand all | Expand 10 after
3023 for_finally_block.Goto(after_finally); 3053 for_finally_block.Goto(after_finally);
3024 for_finally_block.exit_ = after_finally; 3054 for_finally_block.exit_ = after_finally;
3025 } 3055 }
3026 3056
3027 Goto(finally_entry); 3057 Goto(finally_entry);
3028 AppendFragment(finally_entry, for_finally_block); 3058 AppendFragment(finally_entry, for_finally_block);
3029 exit_ = for_finally_block.exit_; 3059 exit_ = for_finally_block.exit_;
3030 } 3060 }
3031 3061
3032 3062
3033 FlowGraph* FlowGraphBuilder::BuildGraph(InliningContext context, 3063 FlowGraph* FlowGraphBuilder::BuildGraph(intptr_t initial_loop_depth) {
3034 intptr_t initial_loop_depth) {
3035 if (FLAG_print_ast) { 3064 if (FLAG_print_ast) {
3036 // Print the function ast before IL generation. 3065 // Print the function ast before IL generation.
3037 AstPrinter::PrintFunctionNodes(parsed_function()); 3066 AstPrinter::PrintFunctionNodes(parsed_function());
3038 } 3067 }
3039 // Set the inlining context.
3040 ASSERT(inlining_context_ == kNotInlining);
3041 inlining_context_ = context;
3042 if (InInliningContext()) exits_ = new ZoneGrowableArray<ReturnInstr*>();
3043 // Compilation can be nested, preserve the computation-id. 3068 // Compilation can be nested, preserve the computation-id.
3044 const Function& function = parsed_function().function(); 3069 const Function& function = parsed_function().function();
3045 TargetEntryInstr* normal_entry = 3070 TargetEntryInstr* normal_entry =
3046 new TargetEntryInstr(AllocateBlockId(), 3071 new TargetEntryInstr(AllocateBlockId(),
3047 CatchClauseNode::kInvalidTryIndex, 3072 CatchClauseNode::kInvalidTryIndex,
3048 initial_loop_depth); 3073 initial_loop_depth);
3049 graph_entry_ = new GraphEntryInstr(normal_entry); 3074 graph_entry_ = new GraphEntryInstr(normal_entry);
3050 EffectGraphVisitor for_effect(this, 0, initial_loop_depth); 3075 EffectGraphVisitor for_effect(this, 0, initial_loop_depth);
3051 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the 3076 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the
3052 // stack check on entry for leaf routines). 3077 // stack check on entry for leaf routines).
3053 Instruction* check = new CheckStackOverflowInstr(function.token_pos()); 3078 Instruction* check = new CheckStackOverflowInstr(function.token_pos());
3054 // If we are inlining don't actually attach the stack check. We must still 3079 // If we are inlining don't actually attach the stack check. We must still
3055 // create the stack check inorder to allocate a deopt id. 3080 // create the stack check inorder to allocate a deopt id.
3056 if (!InInliningContext()) for_effect.AddInstruction(check); 3081 if (!InInliningContext()) for_effect.AddInstruction(check);
3057 parsed_function().node_sequence()->Visit(&for_effect); 3082 parsed_function().node_sequence()->Visit(&for_effect);
3058 AppendFragment(normal_entry, for_effect); 3083 AppendFragment(normal_entry, for_effect);
3059 // Check that the graph is properly terminated. 3084 // Check that the graph is properly terminated.
3060 ASSERT(!for_effect.is_open()); 3085 ASSERT(!for_effect.is_open());
3061 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_); 3086 FlowGraph* graph = new FlowGraph(*this, graph_entry_, last_used_block_id_);
3062 if (InInliningContext()) graph->set_exits(exits_);
3063 return graph; 3087 return graph;
3064 } 3088 }
3065 3089
3066 3090
3067 void FlowGraphBuilder::Bailout(const char* reason) { 3091 void FlowGraphBuilder::Bailout(const char* reason) {
3068 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; 3092 const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
3069 const char* function_name = parsed_function_.function().ToCString(); 3093 const char* function_name = parsed_function_.function().ToCString();
3070 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 3094 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
3071 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 3095 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
3072 OS::SNPrint(chars, len, kFormat, function_name, reason); 3096 OS::SNPrint(chars, len, kFormat, function_name, reason);
3073 const Error& error = Error::Handle( 3097 const Error& error = Error::Handle(
3074 LanguageError::New(String::Handle(String::New(chars)))); 3098 LanguageError::New(String::Handle(String::New(chars))));
3075 Isolate::Current()->long_jump_base()->Jump(1, error); 3099 Isolate::Current()->long_jump_base()->Jump(1, error);
3076 } 3100 }
3077 3101
3078 3102
3079 } // namespace dart 3103 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698