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

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

Issue 934723002: [turbofan] Refactor JSInliner to be a Reducer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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') | src/compiler/pipeline.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/ast.h" 5 #include "src/ast.h"
6 #include "src/ast-numbering.h" 6 #include "src/ast-numbering.h"
7 #include "src/compiler/access-builder.h" 7 #include "src/compiler/access-builder.h"
8 #include "src/compiler/ast-graph-builder.h" 8 #include "src/compiler/ast-graph-builder.h"
9 #include "src/compiler/common-operator.h" 9 #include "src/compiler/common-operator.h"
10 #include "src/compiler/graph-inl.h" 10 #include "src/compiler/graph-inl.h"
11 #include "src/compiler/graph-visualizer.h" 11 #include "src/compiler/graph-visualizer.h"
12 #include "src/compiler/js-inlining.h" 12 #include "src/compiler/js-inlining.h"
13 #include "src/compiler/js-operator.h" 13 #include "src/compiler/js-operator.h"
14 #include "src/compiler/node-matchers.h" 14 #include "src/compiler/node-matchers.h"
15 #include "src/compiler/node-properties.h" 15 #include "src/compiler/node-properties.h"
16 #include "src/compiler/simplified-operator.h" 16 #include "src/compiler/simplified-operator.h"
17 #include "src/compiler/typer.h" 17 #include "src/compiler/typer.h"
18 #include "src/full-codegen.h" 18 #include "src/full-codegen.h"
19 #include "src/parser.h" 19 #include "src/parser.h"
20 #include "src/rewriter.h" 20 #include "src/rewriter.h"
21 #include "src/scopes.h" 21 #include "src/scopes.h"
22 22
23 23
24 namespace v8 { 24 namespace v8 {
25 namespace internal { 25 namespace internal {
26 namespace compiler { 26 namespace compiler {
27 27
28 class InlinerVisitor : public NullNodeVisitor { 28
29 // Provides convenience accessors for calls to JS functions.
30 class JSCallFunctionAccessor {
29 public: 31 public:
30 explicit InlinerVisitor(JSInliner* inliner) : inliner_(inliner) {} 32 explicit JSCallFunctionAccessor(Node* call) : call_(call) {
31 33 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
32 void Post(Node* node) {
33 switch (node->opcode()) {
34 case IrOpcode::kJSCallFunction:
35 inliner_->TryInlineJSCall(node);
36 break;
37 default:
38 break;
39 }
40 } 34 }
41 35
36 Node* jsfunction() { return call_->InputAt(0); }
37
38 Node* receiver() { return call_->InputAt(1); }
39
40 Node* formal_argument(size_t index) {
41 DCHECK(index < formal_arguments());
42 return call_->InputAt(static_cast<int>(2 + index));
43 }
44
45 size_t formal_arguments() {
46 // {value_inputs} includes jsfunction and receiver.
47 size_t value_inputs = call_->op()->ValueInputCount();
48 DCHECK_GE(call_->InputCount(), 2);
49 return value_inputs - 2;
50 }
51
52 Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); }
53
42 private: 54 private:
43 JSInliner* inliner_; 55 Node* call_;
44 }; 56 };
45 57
46 58
47 void JSInliner::Inline() { 59 Reduction JSInliner::Reduce(Node* node) {
48 InlinerVisitor visitor(this); 60 if (node->opcode() != IrOpcode::kJSCallFunction) return NoChange();
49 jsgraph_->graph()->VisitNodeInputsFromEnd(&visitor); 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);
50 } 79 }
51 80
52 81
53 // A facade on a JSFunction's graph to facilitate inlining. It assumes the 82 // A facade on a JSFunction's graph to facilitate inlining. It assumes the
54 // that the function graph has only one return statement, and provides 83 // that the function graph has only one return statement, and provides
55 // {UnifyReturn} to convert a function graph to that end. 84 // {UnifyReturn} to convert a function graph to that end.
56 class Inlinee { 85 class Inlinee {
57 public: 86 public:
58 Inlinee(Node* start, Node* end) : start_(start), end_(end) {} 87 Inlinee(Node* start, Node* end) : start_(start), end_(end) {}
59 88
(...skipping 22 matching lines...) Expand all
82 size_t total_parameters() { return start_->op()->ValueOutputCount(); } 111 size_t total_parameters() { return start_->op()->ValueOutputCount(); }
83 112
84 // Counts only formal parameters. 113 // Counts only formal parameters.
85 size_t formal_parameters() { 114 size_t formal_parameters() {
86 DCHECK_GE(total_parameters(), 3u); 115 DCHECK_GE(total_parameters(), 3u);
87 return total_parameters() - 3; 116 return total_parameters() - 3;
88 } 117 }
89 118
90 // Inline this graph at {call}, use {jsgraph} and its zone to create 119 // Inline this graph at {call}, use {jsgraph} and its zone to create
91 // any new nodes. 120 // any new nodes.
92 void InlineAtCall(JSGraph* jsgraph, Node* call); 121 Reduction InlineAtCall(JSGraph* jsgraph, Node* call);
93 122
94 // Ensure that only a single return reaches the end node. 123 // Ensure that only a single return reaches the end node.
95 static void UnifyReturn(JSGraph* jsgraph); 124 static void UnifyReturn(JSGraph* jsgraph);
96 125
97 private: 126 private:
98 Node* start_; 127 Node* start_;
99 Node* end_; 128 Node* end_;
100 }; 129 };
101 130
102 131
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 235
207 NodeVector copies_; 236 NodeVector copies_;
208 NodeVector sentinels_; 237 NodeVector sentinels_;
209 Graph* source_graph_; 238 Graph* source_graph_;
210 Graph* target_graph_; 239 Graph* target_graph_;
211 Zone* temp_zone_; 240 Zone* temp_zone_;
212 Operator sentinel_op_; 241 Operator sentinel_op_;
213 }; 242 };
214 243
215 244
216 void Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) { 245 Reduction Inlinee::InlineAtCall(JSGraph* jsgraph, Node* call) {
217 // The scheduler is smart enough to place our code; we just ensure {control} 246 // The scheduler is smart enough to place our code; we just ensure {control}
218 // becomes the control input of the start of the inlinee. 247 // becomes the control input of the start of the inlinee.
219 Node* control = NodeProperties::GetControlInput(call); 248 Node* control = NodeProperties::GetControlInput(call);
220 249
221 // The inlinee uses the context from the JSFunction object. This will 250 // The inlinee uses the context from the JSFunction object. This will
222 // also be the effect dependency for the inlinee as it produces an effect. 251 // also be the effect dependency for the inlinee as it produces an effect.
223 SimplifiedOperatorBuilder simplified(jsgraph->zone()); 252 SimplifiedOperatorBuilder simplified(jsgraph->zone());
224 Node* context = jsgraph->graph()->NewNode( 253 Node* context = jsgraph->graph()->NewNode(
225 simplified.LoadField(AccessBuilder::ForJSFunctionContext()), 254 simplified.LoadField(AccessBuilder::ForJSFunctionContext()),
226 NodeProperties::GetValueInput(call, 0), 255 NodeProperties::GetValueInput(call, 0),
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 } else if (NodeProperties::IsControlEdge(edge)) { 289 } else if (NodeProperties::IsControlEdge(edge)) {
261 edge.UpdateTo(control); 290 edge.UpdateTo(control);
262 } else { 291 } else {
263 UNREACHABLE(); 292 UNREACHABLE();
264 } 293 }
265 break; 294 break;
266 } 295 }
267 } 296 }
268 297
269 NodeProperties::ReplaceWithValue(call, value_output(), effect_output()); 298 NodeProperties::ReplaceWithValue(call, value_output(), effect_output());
270 call->RemoveAllInputs(); 299 return Reducer::Replace(value_output());
271 DCHECK_EQ(0, call->UseCount());
272 } 300 }
273 301
274 302
275 // TODO(turbofan) Provide such accessors for every node, possibly even
276 // generate them.
277 class JSCallFunctionAccessor {
278 public:
279 explicit JSCallFunctionAccessor(Node* call) : call_(call) {
280 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode());
281 }
282
283 Node* jsfunction() { return call_->InputAt(0); }
284
285 Node* receiver() { return call_->InputAt(1); }
286
287 Node* formal_argument(size_t index) {
288 DCHECK(index < formal_arguments());
289 return call_->InputAt(static_cast<int>(2 + index));
290 }
291
292 size_t formal_arguments() {
293 // {value_inputs} includes jsfunction and receiver.
294 size_t value_inputs = call_->op()->ValueInputCount();
295 DCHECK_GE(call_->InputCount(), 2);
296 return value_inputs - 2;
297 }
298
299 Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); }
300
301 private:
302 Node* call_;
303 };
304
305
306 void JSInliner::AddClosureToFrameState(Node* frame_state, 303 void JSInliner::AddClosureToFrameState(Node* frame_state,
307 Handle<JSFunction> jsfunction) { 304 Handle<JSFunction> jsfunction) {
308 FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state); 305 FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state);
309 const Operator* op = jsgraph_->common()->FrameState( 306 const Operator* op = jsgraph_->common()->FrameState(
310 FrameStateType::JS_FRAME, call_info.bailout_id(), 307 FrameStateType::JS_FRAME, call_info.bailout_id(),
311 call_info.state_combine(), jsfunction); 308 call_info.state_combine(), jsfunction);
312 frame_state->set_op(op); 309 frame_state->set_op(op);
313 } 310 }
314 311
315 312
(...skipping 13 matching lines...) Expand all
329 const Operator* op_param = 326 const Operator* op_param =
330 jsgraph_->common()->StateValues(static_cast<int>(params.size())); 327 jsgraph_->common()->StateValues(static_cast<int>(params.size()));
331 Node* params_node = jsgraph_->graph()->NewNode( 328 Node* params_node = jsgraph_->graph()->NewNode(
332 op_param, static_cast<int>(params.size()), &params.front()); 329 op_param, static_cast<int>(params.size()), &params.front());
333 return jsgraph_->graph()->NewNode(op, params_node, node0, node0, 330 return jsgraph_->graph()->NewNode(op, params_node, node0, node0,
334 jsgraph_->UndefinedConstant(), 331 jsgraph_->UndefinedConstant(),
335 call->frame_state()); 332 call->frame_state());
336 } 333 }
337 334
338 335
339 void JSInliner::TryInlineJSCall(Node* call_node) { 336 Reduction JSInliner::TryInlineJSCall(Node* call_node,
337 Handle<JSFunction> function) {
340 JSCallFunctionAccessor call(call_node); 338 JSCallFunctionAccessor call(call_node);
339 CompilationInfoWithZone info(function);
341 340
342 HeapObjectMatcher<JSFunction> match(call.jsfunction()); 341 if (!Compiler::ParseAndAnalyze(&info)) return NoChange();
343 if (!match.HasValue()) { 342 if (!Compiler::EnsureDeoptimizationSupport(&info)) return NoChange();
344 return;
345 }
346
347 Handle<JSFunction> function = match.Value().handle();
348
349 if (function->shared()->native()) {
350 if (FLAG_trace_turbo_inlining) {
351 SmartArrayPointer<char> name =
352 function->shared()->DebugName()->ToCString();
353 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
354 info_->shared_info()->DebugName()->ToCString().get());
355 }
356 return;
357 }
358
359 CompilationInfoWithZone info(function);
360 // TODO(wingo): ParseAndAnalyze can fail due to stack overflow.
361 CHECK(Compiler::ParseAndAnalyze(&info));
362 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
363 343
364 if (info.scope()->arguments() != NULL && is_sloppy(info.language_mode())) { 344 if (info.scope()->arguments() != NULL && is_sloppy(info.language_mode())) {
365 // For now do not inline functions that use their arguments array. 345 // For now do not inline functions that use their arguments array.
366 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); 346 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
367 if (FLAG_trace_turbo_inlining) { 347 if (FLAG_trace_turbo_inlining) {
368 PrintF( 348 PrintF(
369 "Not Inlining %s into %s because inlinee uses arguments " 349 "Not Inlining %s into %s because inlinee uses arguments "
370 "array\n", 350 "array\n",
371 name.get(), info_->shared_info()->DebugName()->ToCString().get()); 351 name.get(), info_->shared_info()->DebugName()->ToCString().get());
372 } 352 }
373 return; 353 return NoChange();
374 } 354 }
375 355
376 if (FLAG_trace_turbo_inlining) { 356 if (FLAG_trace_turbo_inlining) {
377 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); 357 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
378 PrintF("Inlining %s into %s\n", name.get(), 358 PrintF("Inlining %s into %s\n", name.get(),
379 info_->shared_info()->DebugName()->ToCString().get()); 359 info_->shared_info()->DebugName()->ToCString().get());
380 } 360 }
381 361
382 Graph graph(info.zone()); 362 Graph graph(info.zone());
383 JSGraph jsgraph(info.isolate(), &graph, jsgraph_->common(), 363 JSGraph jsgraph(info.isolate(), &graph, jsgraph_->common(),
(...skipping 17 matching lines...) Expand all
401 } 381 }
402 382
403 for (Node* node : visitor.copies()) { 383 for (Node* node : visitor.copies()) {
404 if (node && node->opcode() == IrOpcode::kFrameState) { 384 if (node && node->opcode() == IrOpcode::kFrameState) {
405 AddClosureToFrameState(node, function); 385 AddClosureToFrameState(node, function);
406 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state); 386 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state);
407 } 387 }
408 } 388 }
409 } 389 }
410 390
411 inlinee.InlineAtCall(jsgraph_, call_node); 391 return inlinee.InlineAtCall(jsgraph_, call_node);
412 } 392 }
413 393
414 } // namespace compiler 394 } // namespace compiler
415 } // namespace internal 395 } // namespace internal
416 } // namespace v8 396 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-inlining.h ('k') | src/compiler/pipeline.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698