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

Side by Side Diff: src/compiler/js-inlining.cc

Issue 944803002: [turbofan] Finally get rid of the generic algorithm. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE. FIX. Created 5 years, 10 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
« no previous file with comments | « src/compiler/js-inlining.h ('k') | test/cctest/compiler/test-control-reducer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/js-inlining.h"
6
5 #include "src/ast.h" 7 #include "src/ast.h"
6 #include "src/ast-numbering.h" 8 #include "src/ast-numbering.h"
7 #include "src/compiler/access-builder.h" 9 #include "src/compiler/access-builder.h"
10 #include "src/compiler/all-nodes.h"
8 #include "src/compiler/ast-graph-builder.h" 11 #include "src/compiler/ast-graph-builder.h"
9 #include "src/compiler/common-operator.h" 12 #include "src/compiler/common-operator.h"
10 #include "src/compiler/graph-inl.h"
11 #include "src/compiler/graph-visualizer.h" 13 #include "src/compiler/graph-visualizer.h"
12 #include "src/compiler/js-inlining.h"
13 #include "src/compiler/js-operator.h" 14 #include "src/compiler/js-operator.h"
14 #include "src/compiler/node-matchers.h" 15 #include "src/compiler/node-matchers.h"
15 #include "src/compiler/node-properties.h" 16 #include "src/compiler/node-properties.h"
16 #include "src/compiler/simplified-operator.h" 17 #include "src/compiler/simplified-operator.h"
17 #include "src/compiler/typer.h" 18 #include "src/compiler/typer.h"
18 #include "src/full-codegen.h" 19 #include "src/full-codegen.h"
19 #include "src/parser.h" 20 #include "src/parser.h"
20 #include "src/rewriter.h" 21 #include "src/rewriter.h"
21 #include "src/scopes.h" 22 #include "src/scopes.h"
22 23
23
24 namespace v8 { 24 namespace v8 {
25 namespace internal { 25 namespace internal {
26 namespace compiler { 26 namespace compiler {
27 27
28 28
29 // Provides convenience accessors for calls to JS functions. 29 // Provides convenience accessors for calls to JS functions.
30 class JSCallFunctionAccessor { 30 class JSCallFunctionAccessor {
31 public: 31 public:
32 explicit JSCallFunctionAccessor(Node* call) : call_(call) { 32 explicit JSCallFunctionAccessor(Node* call) : call_(call) {
33 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode()); 33 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
(...skipping 15 matching lines...) Expand all
49 return value_inputs - 2; 49 return value_inputs - 2;
50 } 50 }
51 51
52 Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); } 52 Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); }
53 53
54 private: 54 private:
55 Node* call_; 55 Node* call_;
56 }; 56 };
57 57
58 58
59 Reduction JSInliner::Reduce(Node* node) { 59 namespace {
60 if (node->opcode() != IrOpcode::kJSCallFunction) return NoChange();
61
62 JSCallFunctionAccessor call(node);
63 HeapObjectMatcher<JSFunction> match(call.jsfunction());
64 if (!match.HasValue()) return NoChange();
65
66 Handle<JSFunction> jsfunction = match.Value().handle();
67
68 if (jsfunction->shared()->native()) {
69 if (FLAG_trace_turbo_inlining) {
70 SmartArrayPointer<char> name =
71 jsfunction->shared()->DebugName()->ToCString();
72 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
73 info_->shared_info()->DebugName()->ToCString().get());
74 }
75 return NoChange();
76 }
77
78 return TryInlineJSCall(node, jsfunction);
79 }
80
81 60
82 // A facade on a JSFunction's graph to facilitate inlining. It assumes the 61 // A facade on a JSFunction's graph to facilitate inlining. It assumes the
83 // that the function graph has only one return statement, and provides 62 // that the function graph has only one return statement, and provides
84 // {UnifyReturn} to convert a function graph to that end. 63 // {UnifyReturn} to convert a function graph to that end.
85 class Inlinee { 64 class Inlinee {
86 public: 65 public:
87 Inlinee(Node* start, Node* end) : start_(start), end_(end) {} 66 Inlinee(Node* start, Node* end) : start_(start), end_(end) {}
88 67
89 // Returns the last regular control node, that is 68 // Returns the last regular control node, that is
90 // the last control node before the end node. 69 // the last control node before the end node.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 Node* phi = 146 Node* phi =
168 graph->NewNode(op_phi, static_cast<int>(values.size()), &values.front()); 147 graph->NewNode(op_phi, static_cast<int>(values.size()), &values.front());
169 Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()), 148 Node* ephi = graph->NewNode(op_ephi, static_cast<int>(effects.size()),
170 &effects.front()); 149 &effects.front());
171 Node* new_return = 150 Node* new_return =
172 graph->NewNode(jsgraph->common()->Return(), phi, ephi, final_merge); 151 graph->NewNode(jsgraph->common()->Return(), phi, ephi, final_merge);
173 graph->end()->ReplaceInput(0, new_return); 152 graph->end()->ReplaceInput(0, new_return);
174 } 153 }
175 154
176 155
177 class CopyVisitor : public NullNodeVisitor { 156 class CopyVisitor {
178 public: 157 public:
179 CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone) 158 CopyVisitor(Graph* source_graph, Graph* target_graph, Zone* temp_zone)
180 : copies_(source_graph->NodeCount(), NULL, temp_zone), 159 : sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "Sentinel", 0, 0,
181 sentinels_(source_graph->NodeCount(), NULL, temp_zone), 160 0, 0, 0, 0),
161 sentinel_(target_graph->NewNode(&sentinel_op_)),
162 copies_(source_graph->NodeCount(), sentinel_, temp_zone),
182 source_graph_(source_graph), 163 source_graph_(source_graph),
183 target_graph_(target_graph), 164 target_graph_(target_graph),
184 temp_zone_(temp_zone), 165 temp_zone_(temp_zone) {}
185 sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "sentinel", 0, 0,
186 0, 0, 0, 0) {}
187 166
188 void Post(Node* original) { 167 Node* GetCopy(Node* orig) { return copies_[orig->id()]; }
189 NodeVector inputs(temp_zone_);
190 for (Node* const node : original->inputs()) {
191 inputs.push_back(GetCopy(node));
192 }
193
194 // Reuse the operator in the copy. This assumes that op lives in a zone
195 // that lives longer than graph()'s zone.
196 Node* copy =
197 target_graph_->NewNode(original->op(), static_cast<int>(inputs.size()),
198 (inputs.empty() ? NULL : &inputs.front()));
199 copies_[original->id()] = copy;
200 }
201
202 Node* GetCopy(Node* original) {
203 Node* copy = copies_[original->id()];
204 if (copy == NULL) {
205 copy = GetSentinel(original);
206 }
207 DCHECK(copy);
208 return copy;
209 }
210 168
211 void CopyGraph() { 169 void CopyGraph() {
212 source_graph_->VisitNodeInputsFromEnd(this); 170 NodeVector inputs(temp_zone_);
213 ReplaceSentinels(); 171 // TODO(bmeurer): AllNodes should be turned into something like
214 } 172 // Graph::CollectNodesReachableFromEnd() and the gray set stuff should be
215 173 // removed since it's only needed by the visualizer.
216 const NodeVector& copies() { return copies_; } 174 AllNodes all(temp_zone_, source_graph_);
217 175 // Copy all nodes reachable from end.
218 private: 176 for (Node* orig : all.live) {
219 void ReplaceSentinels() { 177 Node* copy = GetCopy(orig);
220 for (NodeId id = 0; id < source_graph_->NodeCount(); ++id) { 178 if (copy != sentinel_) {
221 Node* sentinel = sentinels_[id]; 179 // Mapping already exists.
222 if (sentinel == NULL) continue; 180 continue;
223 Node* copy = copies_[id]; 181 }
224 DCHECK(copy); 182 // Copy the node.
225 sentinel->ReplaceUses(copy); 183 inputs.clear();
184 for (Node* input : orig->inputs()) inputs.push_back(copies_[input->id()]);
185 copy = target_graph_->NewNode(orig->op(), orig->InputCount(),
186 inputs.empty() ? nullptr : &inputs[0]);
187 copies_[orig->id()] = copy;
188 }
189 // For missing inputs.
190 for (Node* orig : all.live) {
191 Node* copy = copies_[orig->id()];
192 for (int i = 0; i < copy->InputCount(); ++i) {
193 Node* input = copy->InputAt(i);
194 if (input == sentinel_) {
195 copy->ReplaceInput(i, GetCopy(orig->InputAt(i)));
196 }
197 }
226 } 198 }
227 } 199 }
228 200
229 Node* GetSentinel(Node* original) { 201 const NodeVector& copies() const { return copies_; }
230 if (sentinels_[original->id()] == NULL) {
231 sentinels_[original->id()] = target_graph_->NewNode(&sentinel_op_);
232 }
233 return sentinels_[original->id()];
234 }
235 202
203 private:
204 Operator const sentinel_op_;
205 Node* const sentinel_;
236 NodeVector copies_; 206 NodeVector copies_;
237 NodeVector sentinels_; 207 Graph* const source_graph_;
238 Graph* source_graph_; 208 Graph* const target_graph_;
239 Graph* target_graph_; 209 Zone* const temp_zone_;
240 Zone* temp_zone_;
241 Operator sentinel_op_;
242 }; 210 };
243 211
244 212
245 Reduction Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) { 213 Reduction Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
246 // The scheduler is smart enough to place our code; we just ensure {control} 214 // The scheduler is smart enough to place our code; we just ensure {control}
247 // becomes the control input of the start of the inlinee. 215 // becomes the control input of the start of the inlinee.
248 Node* control = NodeProperties::GetControlInput(call); 216 Node* control = NodeProperties::GetControlInput(call);
249 217
250 // The inlinee uses the context from the JSFunction object. This will 218 // The inlinee uses the context from the JSFunction object. This will
251 // also be the effect dependency for the inlinee as it produces an effect. 219 // also be the effect dependency for the inlinee as it produces an effect.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 UNREACHABLE(); 260 UNREACHABLE();
293 } 261 }
294 break; 262 break;
295 } 263 }
296 } 264 }
297 265
298 NodeProperties::ReplaceWithValue(call, value_output(), effect_output()); 266 NodeProperties::ReplaceWithValue(call, value_output(), effect_output());
299 return Reducer::Replace(value_output()); 267 return Reducer::Replace(value_output());
300 } 268 }
301 269
270 } // namespace
271
302 272
303 void JSInliner::AddClosureToFrameState(Node* frame_state, 273 void JSInliner::AddClosureToFrameState(Node* frame_state,
304 Handle<JSFunction> jsfunction) { 274 Handle<JSFunction> jsfunction) {
305 FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state); 275 FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state);
306 const Operator* op = jsgraph_->common()->FrameState( 276 const Operator* op = jsgraph_->common()->FrameState(
307 FrameStateType::JS_FRAME, call_info.bailout_id(), 277 FrameStateType::JS_FRAME, call_info.bailout_id(),
308 call_info.state_combine(), jsfunction); 278 call_info.state_combine(), jsfunction);
309 frame_state->set_op(op); 279 frame_state->set_op(op);
310 } 280 }
311 281
(...skipping 14 matching lines...) Expand all
326 const Operator* op_param = 296 const Operator* op_param =
327 jsgraph_->common()->StateValues(static_cast<int>(params.size())); 297 jsgraph_->common()->StateValues(static_cast<int>(params.size()));
328 Node* params_node = jsgraph_->graph()->NewNode( 298 Node* params_node = jsgraph_->graph()->NewNode(
329 op_param, static_cast<int>(params.size()), &params.front()); 299 op_param, static_cast<int>(params.size()), &params.front());
330 return jsgraph_->graph()->NewNode(op, params_node, node0, node0, 300 return jsgraph_->graph()->NewNode(op, params_node, node0, node0,
331 jsgraph_->UndefinedConstant(), 301 jsgraph_->UndefinedConstant(),
332 call->frame_state()); 302 call->frame_state());
333 } 303 }
334 304
335 305
336 Reduction JSInliner::TryInlineJSCall(Node* call_node, 306 Reduction JSInliner::Reduce(Node* node) {
337 Handle<JSFunction> function) { 307 if (node->opcode() != IrOpcode::kJSCallFunction) return NoChange();
338 JSCallFunctionAccessor call(call_node); 308
309 JSCallFunctionAccessor call(node);
310 HeapObjectMatcher<JSFunction> match(call.jsfunction());
311 if (!match.HasValue()) return NoChange();
312
313 Handle<JSFunction> function = match.Value().handle();
314
315 if (function->shared()->native()) {
316 if (FLAG_trace_turbo_inlining) {
317 SmartArrayPointer<char> name =
318 function->shared()->DebugName()->ToCString();
319 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
320 info_->shared_info()->DebugName()->ToCString().get());
321 }
322 return NoChange();
323 }
324
339 CompilationInfoWithZone info(function); 325 CompilationInfoWithZone info(function);
340 326
341 if (!Compiler::ParseAndAnalyze(&info)) return NoChange(); 327 if (!Compiler::ParseAndAnalyze(&info)) return NoChange();
342 if (!Compiler::EnsureDeoptimizationSupport(&info)) return NoChange(); 328 if (!Compiler::EnsureDeoptimizationSupport(&info)) return NoChange();
343 329
344 if (info.scope()->arguments() != NULL && is_sloppy(info.language_mode())) { 330 if (info.scope()->arguments() != NULL && is_sloppy(info.language_mode())) {
345 // For now do not inline functions that use their arguments array. 331 // For now do not inline functions that use their arguments array.
346 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); 332 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
347 if (FLAG_trace_turbo_inlining) { 333 if (FLAG_trace_turbo_inlining) {
348 PrintF( 334 PrintF(
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 } 367 }
382 368
383 for (Node* node : visitor.copies()) { 369 for (Node* node : visitor.copies()) {
384 if (node && node->opcode() == IrOpcode::kFrameState) { 370 if (node && node->opcode() == IrOpcode::kFrameState) {
385 AddClosureToFrameState(node, function); 371 AddClosureToFrameState(node, function);
386 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state); 372 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state);
387 } 373 }
388 } 374 }
389 } 375 }
390 376
391 return inlinee.InlineAtCall(jsgraph_, call_node); 377 return inlinee.InlineAtCall(jsgraph_, node);
392 } 378 }
393 379
394 } // namespace compiler 380 } // namespace compiler
395 } // namespace internal 381 } // namespace internal
396 } // namespace v8 382 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-inlining.h ('k') | test/cctest/compiler/test-control-reducer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698