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

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

Issue 10928232: Deoptimization support in inlined code. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 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_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/compiler.h"
7 #include "vm/flags.h" 8 #include "vm/flags.h"
8 #include "vm/flow_graph.h" 9 #include "vm/flow_graph.h"
9 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
11 #include "vm/flow_graph_optimizer.h"
12 #include "vm/intrinsifier.h"
Kevin Millikin (Google) 2012/09/18 11:01:55 I think we try to keep these sorted according to M
zerny-google 2012/09/18 11:53:07 Thanks again.
10 #include "vm/il_printer.h" 13 #include "vm/il_printer.h"
11 #include "vm/longjump.h" 14 #include "vm/longjump.h"
12 #include "vm/object.h" 15 #include "vm/object.h"
13 #include "vm/object_store.h" 16 #include "vm/object_store.h"
14 17
15 namespace dart { 18 namespace dart {
16 19
17 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining"); 20 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
18 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function"); 21 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
19 DECLARE_FLAG(bool, print_flow_graph); 22 DECLARE_FLAG(bool, print_flow_graph);
23 DECLARE_FLAG(bool, deoptimization_counter_threshold);
20 24
21 #define TRACE_INLINING(statement) \ 25 #define TRACE_INLINING(statement) \
22 do { \ 26 do { \
23 if (FLAG_trace_inlining) statement; \ 27 if (FLAG_trace_inlining) statement; \
24 } while (false) 28 } while (false)
25 29
26 30
27 class CallSiteInliner : public FlowGraphVisitor { 31 class CallSiteInliner : public FlowGraphVisitor {
28 public: 32 public:
29 explicit CallSiteInliner(FlowGraph* flow_graph) 33 explicit CallSiteInliner(FlowGraph* flow_graph)
30 : FlowGraphVisitor(flow_graph->postorder()), 34 : FlowGraphVisitor(flow_graph->postorder()),
31 caller_graph_(flow_graph), 35 caller_graph_(flow_graph),
32 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), 36 next_ssa_temp_index_(flow_graph->max_virtual_register_number()),
33 inlined_(false) { } 37 inlined_(false) { }
34 38
35 bool TryInlining(const Function& function, 39 bool TryInlining(const Function& function,
36 GrowableArray<Value*>* arguments, 40 GrowableArray<Value*>* arguments,
37 Definition* call) { 41 Definition* call) {
38 TRACE_INLINING(OS::Print(" => %s\n", function.ToCString())); 42 TRACE_INLINING(OS::Print(" => %s\n", function.ToCString()));
39 43
40 // Abort if the callee has optional parameters. 44 // Abort if the callee has optional parameters.
41 if (function.HasOptionalParameters()) { 45 if (function.HasOptionalParameters()) {
42 TRACE_INLINING(OS::Print(" Bailout: optional parameters\n")); 46 TRACE_INLINING(OS::Print(" Bailout: optional parameters\n"));
43 return false; 47 return false;
44 } 48 }
45 49
46 // Assuming no optional parameters the actual/formal count should match. 50 // Assuming no optional parameters the actual/formal count should match.
47 ASSERT(arguments->length() == function.num_fixed_parameters()); 51 ASSERT(arguments->length() == function.num_fixed_parameters());
48 52
53 // Abort if the callee has an intrinsic translation.
54 if (Intrinsifier::CanIntrinsify(function)) {
55 TRACE_INLINING(OS::Print(" Bailout: can intrinsify\n"));
56 return false;
57 }
58
49 Isolate* isolate = Isolate::Current(); 59 Isolate* isolate = Isolate::Current();
50 // Save and clear IC data. 60 // Save and clear IC data.
51 const Array& old_ic_data = Array::Handle(isolate->ic_data_array()); 61 const Array& old_ic_data = Array::Handle(isolate->ic_data_array());
52 isolate->set_ic_data_array(Array::null()); 62 isolate->set_ic_data_array(Array::null());
63 // Save and clear deopt id.
64 const intptr_t prev_deopt_id = isolate->deopt_id();
Kevin Millikin (Google) 2012/09/18 11:01:55 It distracts me that we have old_ic_data and prev_
zerny-google 2012/09/18 11:53:07 Done.
65 isolate->set_deopt_id(0);
53 // Install bailout jump. 66 // Install bailout jump.
54 LongJump* base = isolate->long_jump_base(); 67 LongJump* base = isolate->long_jump_base();
55 LongJump jump; 68 LongJump jump;
56 isolate->set_long_jump_base(&jump); 69 isolate->set_long_jump_base(&jump);
57 if (setjmp(*jump.Set()) == 0) { 70 if (setjmp(*jump.Set()) == 0) {
58 // Parse the callee function. 71 // Parse the callee function.
59 ParsedFunction parsed_function(function); 72 ParsedFunction parsed_function(function);
60 Parser::ParseFunction(&parsed_function); 73 Parser::ParseFunction(&parsed_function);
61 parsed_function.AllocateVariables(); 74 parsed_function.AllocateVariables();
62 FlowGraphBuilder builder(parsed_function); 75
76 // Load IC data for the callee.
77 if ((function.deoptimization_counter() <
78 FLAG_deoptimization_counter_threshold) &&
79 function.HasCode()) {
80 const Code& unoptimized_code =
81 Code::Handle(function.unoptimized_code());
82 isolate->set_ic_data_array(
83 Compiler::ExtractTypeFeedbackArray(unoptimized_code));
84 }
63 85
64 // Build the callee graph. 86 // Build the callee graph.
87 FlowGraphBuilder builder(parsed_function);
65 FlowGraph* callee_graph = 88 FlowGraph* callee_graph =
66 builder.BuildGraph(FlowGraphBuilder::kValueContext); 89 builder.BuildGraph(FlowGraphBuilder::kValueContext);
67 90
68 // Abort if the callee graph contains control flow. 91 // Abort if the callee graph contains control flow.
69 if (callee_graph->preorder().length() != 2) { 92 if (callee_graph->preorder().length() != 2) {
70 isolate->set_long_jump_base(base); 93 isolate->set_long_jump_base(base);
71 isolate->set_ic_data_array(old_ic_data.raw()); 94 isolate->set_ic_data_array(old_ic_data.raw());
72 TRACE_INLINING(OS::Print(" Bailout: control flow\n")); 95 TRACE_INLINING(OS::Print(" Bailout: control flow\n"));
73 return false; 96 return false;
74 } 97 }
75 98
99 // Compute SSA on the callee graph. (catching bailouts)
Kevin Millikin (Google) 2012/09/18 11:01:55 Format as a complete sentence: "Compute SSA on the
zerny-google 2012/09/18 11:53:07 Done.
100 callee_graph->ComputeSSA(next_ssa_temp_index_);
101 callee_graph->ComputeUseLists();
102
103 // TODO(zerny): Do optimization passes on the callee graph.
Kevin Millikin (Google) 2012/09/18 11:01:55 "Do more optimization...."
zerny-google 2012/09/18 11:53:07 Done.
104 FlowGraphOptimizer optimizer(callee_graph);
105 optimizer.ApplyICData();
106 callee_graph->ComputeUseLists();
107
76 if (FLAG_trace_inlining && FLAG_print_flow_graph) { 108 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
77 OS::Print("Callee graph before SSA %s\n", 109 OS::Print("Callee graph for inlining %s\n",
78 parsed_function.function().ToFullyQualifiedCString()); 110 parsed_function.function().ToFullyQualifiedCString());
79 FlowGraphPrinter printer(*callee_graph); 111 FlowGraphPrinter printer(*callee_graph);
80 printer.PrintBlocks(); 112 printer.PrintBlocks();
81 } 113 }
82 114
83 // Compute SSA on the callee graph. (catching bailouts)
84 callee_graph->ComputeSSA(next_ssa_temp_index_);
85
86 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
87 OS::Print("Callee graph after SSA %s\n",
88 parsed_function.function().ToFullyQualifiedCString());
89 FlowGraphPrinter printer(*callee_graph);
90 printer.PrintBlocks();
91 }
92
93 callee_graph->ComputeUseLists();
94
95 // TODO(zerny): Do optimization passes on the callee graph.
96
97 // TODO(zerny): If result is more than size threshold then abort. 115 // TODO(zerny): If result is more than size threshold then abort.
98 116
99 // TODO(zerny): If effort is less than threshold then inline recursively. 117 // TODO(zerny): If effort is less than threshold then inline recursively.
100 118
101 // Plug result in the caller graph. 119 // Plug result in the caller graph.
102 caller_graph_->InlineCall(call, callee_graph); 120 caller_graph_->InlineCall(call, callee_graph);
103 next_ssa_temp_index_ = caller_graph_->max_virtual_register_number(); 121 next_ssa_temp_index_ = caller_graph_->max_virtual_register_number();
104 122
105 // Remove (all) push arguments of the call. 123 // Check that inlining maintains use lists.
124 DEBUG_ASSERT(caller_graph_->ValidateUseLists());
125
126 // Remove push arguments of the call.
106 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 127 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
107 PushArgumentInstr* push = call->ArgumentAt(i); 128 PushArgumentInstr* push = call->ArgumentAt(i);
108 push->ReplaceUsesWith(push->value()->definition()); 129 push->ReplaceUsesWith(push->value()->definition());
109 push->RemoveFromGraph(); 130 push->RemoveFromGraph();
110 } 131 }
111 132
112 // Replace all the formal parameters with the actuals. 133 // Replace formal parameters with actuals.
113 for (intptr_t i = 0; i < arguments->length(); ++i) { 134 for (intptr_t i = 0; i < arguments->length(); ++i) {
114 Value* val = callee_graph->graph_entry()->start_env()->ValueAt(i); 135 Value* val = callee_graph->graph_entry()->start_env()->ValueAt(i);
115 ParameterInstr* param = val->definition()->AsParameter(); 136 ParameterInstr* param = val->definition()->AsParameter();
116 ASSERT(param != NULL); 137 ASSERT(param != NULL);
117 param->ReplaceUsesWith((*arguments)[i]->definition()); 138 param->ReplaceUsesWith((*arguments)[i]->definition());
118 } 139 }
119 140
120 // Replace callee's null constant with caller's null constant. 141 // Replace callee's null constant with caller's null constant.
121 callee_graph->graph_entry()->constant_null()->ReplaceUsesWith( 142 callee_graph->graph_entry()->constant_null()->ReplaceUsesWith(
122 caller_graph_->graph_entry()->constant_null()); 143 caller_graph_->graph_entry()->constant_null());
123 144
124 TRACE_INLINING(OS::Print(" Success\n")); 145 TRACE_INLINING(OS::Print(" Success\n"));
125 146
126 // Build succeeded so we restore the bailout jump. 147 // Build succeeded so we restore the bailout jump.
127 inlined_ = true; 148 inlined_ = true;
128 isolate->set_long_jump_base(base); 149 isolate->set_long_jump_base(base);
150 isolate->set_deopt_id(prev_deopt_id);
129 isolate->set_ic_data_array(old_ic_data.raw()); 151 isolate->set_ic_data_array(old_ic_data.raw());
130 return true; 152 return true;
131 } else { 153 } else {
132 Error& error = Error::Handle(); 154 Error& error = Error::Handle();
133 error = isolate->object_store()->sticky_error(); 155 error = isolate->object_store()->sticky_error();
134 isolate->object_store()->clear_sticky_error(); 156 isolate->object_store()->clear_sticky_error();
135 isolate->set_long_jump_base(base); 157 isolate->set_long_jump_base(base);
158 isolate->set_deopt_id(prev_deopt_id);
136 isolate->set_ic_data_array(old_ic_data.raw()); 159 isolate->set_ic_data_array(old_ic_data.raw());
137 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); 160 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString()));
138 return false; 161 return false;
139 } 162 }
140 } 163 }
141 164
142 void VisitClosureCall(ClosureCallInstr* call) { 165 void VisitClosureCall(ClosureCallInstr* call) {
143 TRACE_INLINING(OS::Print(" ClosureCall\n")); 166 TRACE_INLINING(OS::Print(" ClosureCall\n"));
144 // Find the closure of the callee. 167 // Find the closure of the callee.
145 ASSERT(call->ArgumentCount() > 0); 168 ASSERT(call->ArgumentCount() > 0);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 215
193 216
194 void FlowGraphInliner::Inline() { 217 void FlowGraphInliner::Inline() {
195 if ((FLAG_inlining_filter != NULL) && 218 if ((FLAG_inlining_filter != NULL) &&
196 (strstr(flow_graph_-> 219 (strstr(flow_graph_->
197 parsed_function().function().ToFullyQualifiedCString(), 220 parsed_function().function().ToFullyQualifiedCString(),
198 FLAG_inlining_filter) == NULL)) { 221 FLAG_inlining_filter) == NULL)) {
199 return; 222 return;
200 } 223 }
201 224
225 TRACE_INLINING(OS::Print(
226 "Inlining calls in %s\n",
227 flow_graph_->parsed_function().function().ToCString()));
228
202 if (FLAG_trace_inlining && FLAG_print_flow_graph) { 229 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
203 OS::Print("Before Inlining of %s\n", flow_graph_-> 230 OS::Print("Before Inlining of %s\n", flow_graph_->
204 parsed_function().function().ToFullyQualifiedCString()); 231 parsed_function().function().ToFullyQualifiedCString());
205 FlowGraphPrinter printer(*flow_graph_); 232 FlowGraphPrinter printer(*flow_graph_);
206 printer.PrintBlocks(); 233 printer.PrintBlocks();
207 } 234 }
208 235
209 TRACE_INLINING(OS::Print(
210 "Inlining calls in %s\n",
211 flow_graph_->parsed_function().function().ToCString()));
212 CallSiteInliner inliner(flow_graph_); 236 CallSiteInliner inliner(flow_graph_);
213 inliner.VisitBlocks(); 237 inliner.VisitBlocks();
214 238
215 if (inliner.inlined()) { 239 if (inliner.inlined()) {
216 if (FLAG_trace_inlining && FLAG_print_flow_graph) { 240 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
217 OS::Print("After Inlining of %s\n", flow_graph_-> 241 OS::Print("After Inlining of %s\n", flow_graph_->
218 parsed_function().function().ToFullyQualifiedCString()); 242 parsed_function().function().ToFullyQualifiedCString());
219 FlowGraphPrinter printer(*flow_graph_); 243 FlowGraphPrinter printer(*flow_graph_);
220 printer.PrintBlocks(); 244 printer.PrintBlocks();
221 } 245 }
222 } 246 }
223 } 247 }
224 248
225 } // namespace dart 249 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698