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

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

Issue 807693003: [turbofan] Unify custom node matchers. Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix Win64 Created 6 years 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/node.h » ('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"
8 #include "src/compiler/ast-graph-builder.h" 10 #include "src/compiler/ast-graph-builder.h"
9 #include "src/compiler/common-operator.h" 11 #include "src/compiler/common-operator.h"
10 #include "src/compiler/graph-inl.h" 12 #include "src/compiler/graph-inl.h"
11 #include "src/compiler/graph-visualizer.h" 13 #include "src/compiler/js-graph.h"
12 #include "src/compiler/js-inlining.h"
13 #include "src/compiler/js-intrinsic-builder.h" 14 #include "src/compiler/js-intrinsic-builder.h"
14 #include "src/compiler/js-operator.h" 15 #include "src/compiler/js-operator.h"
15 #include "src/compiler/node-aux-data-inl.h"
16 #include "src/compiler/node-matchers.h" 16 #include "src/compiler/node-matchers.h"
17 #include "src/compiler/node-properties-inl.h" 17 #include "src/compiler/node-properties-inl.h"
18 #include "src/compiler/simplified-operator.h" 18 #include "src/compiler/simplified-operator.h"
19 #include "src/compiler/typer.h"
20 #include "src/full-codegen.h"
21 #include "src/parser.h" 19 #include "src/parser.h"
22 #include "src/rewriter.h" 20 #include "src/rewriter.h"
23 #include "src/scopes.h" 21 #include "src/scopes.h"
24 22
25 23
26 namespace v8 { 24 namespace v8 {
27 namespace internal { 25 namespace internal {
28 namespace compiler { 26 namespace compiler {
29 27
30 class InlinerVisitor : public NullNodeVisitor { 28 class InlinerVisitor : public NullNodeVisitor {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 98
101 // Ensure that only a single return reaches the end node. 99 // Ensure that only a single return reaches the end node.
102 static void UnifyReturn(JSGraph* jsgraph); 100 static void UnifyReturn(JSGraph* jsgraph);
103 101
104 private: 102 private:
105 Node* start_; 103 Node* start_;
106 Node* end_; 104 Node* end_;
107 }; 105 };
108 106
109 107
108 // static
110 void Inlinee::UnifyReturn(JSGraph* jsgraph) { 109 void Inlinee::UnifyReturn(JSGraph* jsgraph) {
111 Graph* graph = jsgraph->graph(); 110 Graph* graph = jsgraph->graph();
112 111
113 Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0); 112 Node* final_merge = NodeProperties::GetControlInput(graph->end(), 0);
114 if (final_merge->opcode() == IrOpcode::kReturn) { 113 if (final_merge->opcode() == IrOpcode::kReturn) {
115 // nothing to do 114 // nothing to do
116 return; 115 return;
117 } 116 }
118 DCHECK_EQ(IrOpcode::kMerge, final_merge->opcode()); 117 DCHECK_EQ(IrOpcode::kMerge, final_merge->opcode());
119 118
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 } else if (NodeProperties::IsControlEdge(edge)) { 266 } else if (NodeProperties::IsControlEdge(edge)) {
268 edge.UpdateTo(control); 267 edge.UpdateTo(control);
269 } else { 268 } else {
270 UNREACHABLE(); 269 UNREACHABLE();
271 } 270 }
272 break; 271 break;
273 } 272 }
274 } 273 }
275 274
276 NodeProperties::ReplaceWithValue(call, value_output(), effect_output()); 275 NodeProperties::ReplaceWithValue(call, value_output(), effect_output());
277 call->RemoveAllInputs(); 276 call->Kill();
278 DCHECK_EQ(0, call->UseCount());
279 } 277 }
280 278
281 279
282 // TODO(turbofan) Provide such accessors for every node, possibly even 280 template <typename InputIterator>
283 // generate them. 281 Node* JSInliner::CreateArgumentsAdaptorFrameState(
284 class JSCallFunctionAccessor { 282 const Handle<JSFunction>& function, InputIterator first, InputIterator last,
285 public: 283 Node* frame_state) {
286 explicit JSCallFunctionAccessor(Node* call) : call_(call) { 284 NodeVector parameters(zone());
287 DCHECK_EQ(IrOpcode::kJSCallFunction, call->opcode()); 285 parameters.insert(parameters.begin(), first, last);
288 } 286 int const num_parameters = static_cast<int>(parameters.size());
289 287 Node* state_values0 = graph()->NewNode(common()->StateValues(0));
290 Node* jsfunction() { return call_->InputAt(0); } 288 Node* state_values = graph()->NewNode(common()->StateValues(num_parameters),
291 289 num_parameters, &parameters.front());
292 Node* receiver() { return call_->InputAt(1); } 290 return graph()->NewNode(
293 291 common()->FrameState(FrameStateType::ARGUMENTS_ADAPTOR, BailoutId(-1),
294 Node* formal_argument(size_t index) { 292 OutputFrameStateCombine::Ignore(), function),
295 DCHECK(index < formal_arguments()); 293 state_values, state_values0, state_values0,
296 return call_->InputAt(static_cast<int>(2 + index)); 294 jsgraph()->UndefinedConstant(), frame_state);
297 }
298
299 size_t formal_arguments() {
300 // {value_inputs} includes jsfunction and receiver.
301 size_t value_inputs = call_->op()->ValueInputCount();
302 DCHECK_GE(call_->InputCount(), 2);
303 return value_inputs - 2;
304 }
305
306 Node* frame_state() { return NodeProperties::GetFrameStateInput(call_); }
307
308 private:
309 Node* call_;
310 };
311
312
313 void JSInliner::AddClosureToFrameState(Node* frame_state,
314 Handle<JSFunction> jsfunction) {
315 FrameStateCallInfo call_info = OpParameter<FrameStateCallInfo>(frame_state);
316 const Operator* op = jsgraph_->common()->FrameState(
317 FrameStateType::JS_FRAME, call_info.bailout_id(),
318 call_info.state_combine(), jsfunction);
319 frame_state->set_op(op);
320 } 295 }
321 296
322 297
323 Node* JSInliner::CreateArgumentsAdaptorFrameState(JSCallFunctionAccessor* call, 298 void JSInliner::TryInlineJSCall(Node* node) {
324 Handle<JSFunction> jsfunction, 299 JSCallFunctionMatcher const m(node);
325 Zone* temp_zone) { 300 if (!m.function().HasValue()) return;
326 const Operator* op = jsgraph_->common()->FrameState( 301 Handle<JSFunction> const function = m.function().Value().handle();
327 FrameStateType::ARGUMENTS_ADAPTOR, BailoutId(-1),
328 OutputFrameStateCombine::Ignore(), jsfunction);
329 const Operator* op0 = jsgraph_->common()->StateValues(0);
330 Node* node0 = jsgraph_->graph()->NewNode(op0);
331 NodeVector params(temp_zone);
332 params.push_back(call->receiver());
333 for (size_t argument = 0; argument != call->formal_arguments(); ++argument) {
334 params.push_back(call->formal_argument(argument));
335 }
336 const Operator* op_param =
337 jsgraph_->common()->StateValues(static_cast<int>(params.size()));
338 Node* params_node = jsgraph_->graph()->NewNode(
339 op_param, static_cast<int>(params.size()), &params.front());
340 return jsgraph_->graph()->NewNode(op, params_node, node0, node0,
341 jsgraph_->UndefinedConstant(),
342 call->frame_state());
343 }
344
345
346 void JSInliner::TryInlineJSCall(Node* call_node) {
347 JSCallFunctionAccessor call(call_node);
348
349 HeapObjectMatcher<JSFunction> match(call.jsfunction());
350 if (!match.HasValue()) {
351 return;
352 }
353
354 Handle<JSFunction> function = match.Value().handle();
355 302
356 if (function->shared()->native()) { 303 if (function->shared()->native()) {
357 if (FLAG_trace_turbo_inlining) { 304 if (FLAG_trace_turbo_inlining) {
358 SmartArrayPointer<char> name = 305 SmartArrayPointer<char> name =
359 function->shared()->DebugName()->ToCString(); 306 function->shared()->DebugName()->ToCString();
360 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(), 307 PrintF("Not Inlining %s into %s because inlinee is native\n", name.get(),
361 info_->shared_info()->DebugName()->ToCString().get()); 308 info_->shared_info()->DebugName()->ToCString().get());
362 } 309 }
363 return; 310 return;
364 } 311 }
365 312
366 CompilationInfoWithZone info(function); 313 CompilationInfoWithZone info(function);
367 // TODO(wingo): ParseAndAnalyze can fail due to stack overflow. 314 // TODO(wingo): ParseAndAnalyze can fail due to stack overflow.
368 CHECK(Compiler::ParseAndAnalyze(&info)); 315 CHECK(Compiler::ParseAndAnalyze(&info));
369 CHECK(Compiler::EnsureDeoptimizationSupport(&info)); 316 CHECK(Compiler::EnsureDeoptimizationSupport(&info));
370 317
371 if (info.scope()->arguments() != NULL && info.strict_mode() != STRICT) { 318 if (info.scope()->arguments() && info.strict_mode() != STRICT) {
372 // For now do not inline functions that use their arguments array. 319 // For now do not inline functions that use their arguments array.
373 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); 320 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
374 if (FLAG_trace_turbo_inlining) { 321 if (FLAG_trace_turbo_inlining) {
375 PrintF( 322 PrintF(
376 "Not Inlining %s into %s because inlinee uses arguments " 323 "Not Inlining %s into %s because inlinee uses arguments "
377 "array\n", 324 "array\n",
378 name.get(), info_->shared_info()->DebugName()->ToCString().get()); 325 name.get(), info_->shared_info()->DebugName()->ToCString().get());
379 } 326 }
380 return; 327 return;
381 } 328 }
382 329
383 if (FLAG_trace_turbo_inlining) { 330 if (FLAG_trace_turbo_inlining) {
384 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString(); 331 SmartArrayPointer<char> name = function->shared()->DebugName()->ToCString();
385 PrintF("Inlining %s into %s\n", name.get(), 332 PrintF("Inlining %s into %s\n", name.get(),
386 info_->shared_info()->DebugName()->ToCString().get()); 333 info_->shared_info()->DebugName()->ToCString().get());
387 } 334 }
388 335
389 Graph graph(info.zone()); 336 Graph inlinee_graph(info.zone());
390 JSGraph jsgraph(&graph, jsgraph_->common(), jsgraph_->javascript(), 337 JSGraph inlinee_jsgraph(&inlinee_graph, common(), javascript(), machine());
391 jsgraph_->machine());
392 338
393 AstGraphBuilder graph_builder(local_zone_, &info, &jsgraph); 339 AstGraphBuilder graph_builder(zone(), &info, &inlinee_jsgraph);
394 graph_builder.CreateGraph(); 340 graph_builder.CreateGraph();
395 Inlinee::UnifyReturn(&jsgraph); 341 Inlinee::UnifyReturn(&inlinee_jsgraph);
396 342
397 CopyVisitor visitor(&graph, jsgraph_->graph(), info.zone()); 343 CopyVisitor visitor(&inlinee_graph, graph(), info.zone());
398 visitor.CopyGraph(); 344 visitor.CopyGraph();
399 345
400 Inlinee inlinee(visitor.GetCopy(graph.start()), visitor.GetCopy(graph.end())); 346 Inlinee inlinee(visitor.GetCopy(inlinee_graph.start()),
347 visitor.GetCopy(inlinee_graph.end()));
401 348
402 if (FLAG_turbo_deoptimization) { 349 if (FLAG_turbo_deoptimization) {
403 Node* outer_frame_state = call.frame_state(); 350 Node* outer_frame_state = m.frame_state();
404 // Insert argument adaptor frame if required. 351 // Insert argument adaptor frame if required.
405 if (call.formal_arguments() != inlinee.formal_parameters()) { 352 if (m.size() != inlinee.formal_parameters()) {
406 outer_frame_state = 353 outer_frame_state = CreateArgumentsAdaptorFrameState(
407 CreateArgumentsAdaptorFrameState(&call, function, info.zone()); 354 function, m.begin(), m.end(), outer_frame_state);
408 } 355 }
409 356
410 for (NodeVectorConstIter it = visitor.copies().begin(); 357 for (auto frame_state : visitor.copies()) {
411 it != visitor.copies().end(); ++it) { 358 if (frame_state && frame_state->opcode() == IrOpcode::kFrameState) {
412 Node* node = *it; 359 FrameStateCallInfo info = OpParameter<FrameStateCallInfo>(frame_state);
413 if (node != NULL && node->opcode() == IrOpcode::kFrameState) { 360 frame_state->set_op(
414 AddClosureToFrameState(node, function); 361 common()->FrameState(FrameStateType::JS_FRAME, info.bailout_id(),
415 NodeProperties::ReplaceFrameStateInput(node, outer_frame_state); 362 info.state_combine(), function));
363 NodeProperties::ReplaceFrameStateInput(frame_state, outer_frame_state);
416 } 364 }
417 } 365 }
418 } 366 }
419 367
420 inlinee.InlineAtCall(jsgraph_, call_node); 368 inlinee.InlineAtCall(jsgraph(), node);
421 } 369 }
422 370
423 371
424 class JSCallRuntimeAccessor { 372 void JSInliner::TryInlineRuntimeCall(Node* node) {
425 public: 373 JSCallRuntimeMatcher m(node);
426 explicit JSCallRuntimeAccessor(Node* call) : call_(call) { 374 const Runtime::Function* f = m.function();
427 DCHECK_EQ(IrOpcode::kJSCallRuntime, call->opcode()); 375 if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) return;
428 }
429 376
430 Node* formal_argument(size_t index) { 377 JSIntrinsicBuilder intrinsic_builder(jsgraph());
431 DCHECK(index < formal_arguments());
432 return call_->InputAt(static_cast<int>(index));
433 }
434 378
435 size_t formal_arguments() { 379 // TODO(turbofan): Looks like no one is verifying these arguments in the
436 size_t value_inputs = call_->op()->ValueInputCount(); 380 // IntrinsicsBuilder? Do we plan to do it there, or should be add code to
437 return value_inputs; 381 // validate the arguments here?
438 } 382 NodeVector arguments(zone());
439 383 arguments.insert(arguments.begin(), node->inputs().begin(),
440 Node* frame_state() const { 384 node->inputs().end());
441 return NodeProperties::GetFrameStateInput(call_); 385 ResultAndEffect r =
442 } 386 intrinsic_builder.BuildGraphFor(f->function_id, arguments);
443 Node* context() const { return NodeProperties::GetContextInput(call_); } 387 if (r.first) {
444 Node* control() const { return NodeProperties::GetControlInput(call_); }
445 Node* effect() const { return NodeProperties::GetEffectInput(call_); }
446
447 const Runtime::Function* function() const {
448 return Runtime::FunctionForId(CallRuntimeParametersOf(call_->op()).id());
449 }
450
451 NodeVector inputs(Zone* zone) const {
452 NodeVector inputs(zone);
453 for (Node* const node : call_->inputs()) {
454 inputs.push_back(node);
455 }
456 return inputs;
457 }
458
459 private:
460 Node* call_;
461 };
462
463
464 void JSInliner::TryInlineRuntimeCall(Node* call_node) {
465 JSCallRuntimeAccessor call(call_node);
466 const Runtime::Function* f = call.function();
467
468 if (f->intrinsic_type != Runtime::IntrinsicType::INLINE) {
469 return;
470 }
471
472 JSIntrinsicBuilder intrinsic_builder(jsgraph_);
473
474 ResultAndEffect r = intrinsic_builder.BuildGraphFor(
475 f->function_id, call.inputs(jsgraph_->zone()));
476
477 if (r.first != NULL) {
478 if (FLAG_trace_turbo_inlining) { 388 if (FLAG_trace_turbo_inlining) {
479 PrintF("Inlining %s into %s\n", f->name, 389 PrintF("Inlining %s into %s\n", f->name,
480 info_->shared_info()->DebugName()->ToCString().get()); 390 info_->shared_info()->DebugName()->ToCString().get());
481 } 391 }
482 NodeProperties::ReplaceWithValue(call_node, r.first, r.second); 392 NodeProperties::ReplaceWithValue(node, r.first, r.second);
483 call_node->RemoveAllInputs(); 393 node->Kill();
484 DCHECK_EQ(0, call_node->UseCount());
485 } 394 }
486 } 395 }
396
397
398 Graph* JSInliner::graph() const { return jsgraph()->graph(); }
399
400
401 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); }
402
403
404 JSOperatorBuilder* JSInliner::javascript() const {
405 return jsgraph()->javascript();
487 } 406 }
407
408
409 MachineOperatorBuilder* JSInliner::machine() const {
410 return jsgraph()->machine();
488 } 411 }
489 } // namespace v8::internal::compiler 412
413 } // namespace compiler
414 } // namespace internal
415 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-inlining.h ('k') | src/compiler/node.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698