| OLD | NEW |
| 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" | 5 #include "src/compiler/js-inlining.h" |
| 6 | 6 |
| 7 #include "src/ast/ast-numbering.h" | |
| 8 #include "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
| 9 #include "src/compilation-info.h" | 8 #include "src/compilation-info.h" |
| 10 #include "src/compiler.h" | 9 #include "src/compiler.h" |
| 11 #include "src/compiler/all-nodes.h" | 10 #include "src/compiler/all-nodes.h" |
| 12 #include "src/compiler/ast-graph-builder.h" | |
| 13 #include "src/compiler/ast-loop-assignment-analyzer.h" | |
| 14 #include "src/compiler/bytecode-graph-builder.h" | 11 #include "src/compiler/bytecode-graph-builder.h" |
| 15 #include "src/compiler/common-operator.h" | 12 #include "src/compiler/common-operator.h" |
| 13 #include "src/compiler/compiler-source-position-table.h" |
| 16 #include "src/compiler/graph-reducer.h" | 14 #include "src/compiler/graph-reducer.h" |
| 17 #include "src/compiler/js-operator.h" | 15 #include "src/compiler/js-operator.h" |
| 18 #include "src/compiler/node-matchers.h" | 16 #include "src/compiler/node-matchers.h" |
| 19 #include "src/compiler/node-properties.h" | 17 #include "src/compiler/node-properties.h" |
| 20 #include "src/compiler/operator-properties.h" | 18 #include "src/compiler/operator-properties.h" |
| 21 #include "src/compiler/simplified-operator.h" | 19 #include "src/compiler/simplified-operator.h" |
| 22 #include "src/isolate-inl.h" | 20 #include "src/isolate-inl.h" |
| 23 #include "src/parsing/parse-info.h" | 21 #include "src/parsing/parse-info.h" |
| 24 #include "src/parsing/rewriter.h" | |
| 25 | 22 |
| 26 namespace v8 { | 23 namespace v8 { |
| 27 namespace internal { | 24 namespace internal { |
| 28 namespace compiler { | 25 namespace compiler { |
| 29 | 26 |
| 30 #define TRACE(...) \ | 27 #define TRACE(...) \ |
| 31 do { \ | 28 do { \ |
| 32 if (FLAG_trace_turbo_inlining) PrintF(__VA_ARGS__); \ | 29 if (FLAG_trace_turbo_inlining) PrintF(__VA_ARGS__); \ |
| 33 } while (false) | 30 } while (false) |
| 34 | 31 |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value()); | 374 Handle<JSFunction> function = Handle<JSFunction>::cast(match.Value()); |
| 378 | 375 |
| 379 return ReduceJSCall(node, function); | 376 return ReduceJSCall(node, function); |
| 380 } | 377 } |
| 381 | 378 |
| 382 Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) { | 379 Reduction JSInliner::ReduceJSCall(Node* node, Handle<JSFunction> function) { |
| 383 DCHECK(IrOpcode::IsInlineeOpcode(node->opcode())); | 380 DCHECK(IrOpcode::IsInlineeOpcode(node->opcode())); |
| 384 JSCallAccessor call(node); | 381 JSCallAccessor call(node); |
| 385 Handle<SharedFunctionInfo> shared_info(function->shared()); | 382 Handle<SharedFunctionInfo> shared_info(function->shared()); |
| 386 | 383 |
| 384 // Inlining is only supported in the bytecode pipeline. |
| 385 if (!info_->is_optimizing_from_bytecode()) { |
| 386 TRACE("Inlining %s into %s is not supported in the deprecated pipeline\n", |
| 387 shared_info->DebugName()->ToCString().get(), |
| 388 info_->shared_info()->DebugName()->ToCString().get()); |
| 389 return NoChange(); |
| 390 } |
| 391 |
| 387 // Function must be inlineable. | 392 // Function must be inlineable. |
| 388 if (!shared_info->IsInlineable()) { | 393 if (!shared_info->IsInlineable()) { |
| 389 TRACE("Not inlining %s into %s because callee is not inlineable\n", | 394 TRACE("Not inlining %s into %s because callee is not inlineable\n", |
| 390 shared_info->DebugName()->ToCString().get(), | 395 shared_info->DebugName()->ToCString().get(), |
| 391 info_->shared_info()->DebugName()->ToCString().get()); | 396 info_->shared_info()->DebugName()->ToCString().get()); |
| 392 return NoChange(); | 397 return NoChange(); |
| 393 } | 398 } |
| 394 | 399 |
| 395 // Constructor must be constructable. | 400 // Constructor must be constructable. |
| 396 if (node->opcode() == IrOpcode::kJSCallConstruct && | 401 if (node->opcode() == IrOpcode::kJSCallConstruct && |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 shared_info->DebugName()->ToCString().get(), | 485 shared_info->DebugName()->ToCString().get(), |
| 481 info_->shared_info()->DebugName()->ToCString().get(), | 486 info_->shared_info()->DebugName()->ToCString().get(), |
| 482 exception_target->id(), exception_target->op()->mnemonic()); | 487 exception_target->id(), exception_target->op()->mnemonic()); |
| 483 } | 488 } |
| 484 } | 489 } |
| 485 | 490 |
| 486 Zone zone(info_->isolate()->allocator(), ZONE_NAME); | 491 Zone zone(info_->isolate()->allocator(), ZONE_NAME); |
| 487 ParseInfo parse_info(&zone, shared_info); | 492 ParseInfo parse_info(&zone, shared_info); |
| 488 CompilationInfo info(&parse_info, function); | 493 CompilationInfo info(&parse_info, function); |
| 489 if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled(); | 494 if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled(); |
| 490 if (info_->is_optimizing_from_bytecode()) info.MarkAsOptimizeFromBytecode(); | 495 info.MarkAsOptimizeFromBytecode(); |
| 491 | 496 |
| 492 if (info.is_optimizing_from_bytecode() && !Compiler::EnsureBytecode(&info)) { | 497 if (!Compiler::EnsureBytecode(&info)) { |
| 493 TRACE("Not inlining %s into %s because bytecode generation failed\n", | 498 TRACE("Not inlining %s into %s because bytecode generation failed\n", |
| 494 shared_info->DebugName()->ToCString().get(), | 499 shared_info->DebugName()->ToCString().get(), |
| 495 info_->shared_info()->DebugName()->ToCString().get()); | 500 info_->shared_info()->DebugName()->ToCString().get()); |
| 496 if (info_->isolate()->has_pending_exception()) { | 501 if (info_->isolate()->has_pending_exception()) { |
| 497 info_->isolate()->clear_pending_exception(); | 502 info_->isolate()->clear_pending_exception(); |
| 498 } | 503 } |
| 499 return NoChange(); | 504 return NoChange(); |
| 500 } | 505 } |
| 501 | 506 |
| 502 if (!info.is_optimizing_from_bytecode() && | |
| 503 !Compiler::ParseAndAnalyze(info.parse_info())) { | |
| 504 TRACE("Not inlining %s into %s because parsing failed\n", | |
| 505 shared_info->DebugName()->ToCString().get(), | |
| 506 info_->shared_info()->DebugName()->ToCString().get()); | |
| 507 if (info_->isolate()->has_pending_exception()) { | |
| 508 info_->isolate()->clear_pending_exception(); | |
| 509 } | |
| 510 return NoChange(); | |
| 511 } | |
| 512 | |
| 513 if (!info.is_optimizing_from_bytecode() && | |
| 514 !Compiler::EnsureDeoptimizationSupport(&info)) { | |
| 515 TRACE("Not inlining %s into %s because deoptimization support failed\n", | |
| 516 shared_info->DebugName()->ToCString().get(), | |
| 517 info_->shared_info()->DebugName()->ToCString().get()); | |
| 518 return NoChange(); | |
| 519 } | |
| 520 | |
| 521 // Remember that we inlined this function. This needs to be called right | 507 // Remember that we inlined this function. This needs to be called right |
| 522 // after we ensure deoptimization support so that the code flusher | 508 // after we ensure deoptimization support so that the code flusher |
| 523 // does not remove the code with the deoptimization support. | 509 // does not remove the code with the deoptimization support. |
| 524 int inlining_id = info_->AddInlinedFunction( | 510 int inlining_id = info_->AddInlinedFunction( |
| 525 shared_info, source_positions_->GetSourcePosition(node)); | 511 shared_info, source_positions_->GetSourcePosition(node)); |
| 526 | 512 |
| 527 // ---------------------------------------------------------------- | 513 // ---------------------------------------------------------------- |
| 528 // After this point, we've made a decision to inline this function. | 514 // After this point, we've made a decision to inline this function. |
| 529 // We shall not bailout from inlining if we got here. | 515 // We shall not bailout from inlining if we got here. |
| 530 | 516 |
| 531 TRACE("Inlining %s into %s\n", | 517 TRACE("Inlining %s into %s\n", |
| 532 shared_info->DebugName()->ToCString().get(), | 518 shared_info->DebugName()->ToCString().get(), |
| 533 info_->shared_info()->DebugName()->ToCString().get()); | 519 info_->shared_info()->DebugName()->ToCString().get()); |
| 534 | 520 |
| 535 // If function was lazily compiled, its literals array may not yet be set up. | 521 // If function was lazily compiled, its literals array may not yet be set up. |
| 536 JSFunction::EnsureLiterals(function); | 522 JSFunction::EnsureLiterals(function); |
| 537 | 523 |
| 538 // Create the subgraph for the inlinee. | 524 // Create the subgraph for the inlinee. |
| 539 Node* start; | 525 Node* start; |
| 540 Node* end; | 526 Node* end; |
| 541 if (info.is_optimizing_from_bytecode()) { | 527 { |
| 542 // Run the BytecodeGraphBuilder to create the subgraph. | 528 // Run the BytecodeGraphBuilder to create the subgraph. |
| 543 Graph::SubgraphScope scope(graph()); | 529 Graph::SubgraphScope scope(graph()); |
| 544 BytecodeGraphBuilder graph_builder(&zone, &info, jsgraph(), | 530 BytecodeGraphBuilder graph_builder(&zone, &info, jsgraph(), |
| 545 call.frequency(), source_positions_, | 531 call.frequency(), source_positions_, |
| 546 inlining_id); | 532 inlining_id); |
| 547 graph_builder.CreateGraph(false); | 533 graph_builder.CreateGraph(false); |
| 548 | 534 |
| 549 // Extract the inlinee start/end nodes. | 535 // Extract the inlinee start/end nodes. |
| 550 start = graph()->start(); | 536 start = graph()->start(); |
| 551 end = graph()->end(); | 537 end = graph()->end(); |
| 552 } else { | |
| 553 // Run the loop assignment analyzer on the inlinee. | |
| 554 AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info); | |
| 555 LoopAssignmentAnalysis* loop_assignment = | |
| 556 loop_assignment_analyzer.Analyze(); | |
| 557 | |
| 558 // Run the AstGraphBuilder to create the subgraph. | |
| 559 Graph::SubgraphScope scope(graph()); | |
| 560 AstGraphBuilderWithPositions graph_builder( | |
| 561 &zone, &info, jsgraph(), call.frequency(), loop_assignment, | |
| 562 source_positions_, inlining_id); | |
| 563 graph_builder.CreateGraph(false); | |
| 564 | |
| 565 // Extract the inlinee start/end nodes. | |
| 566 start = graph()->start(); | |
| 567 end = graph()->end(); | |
| 568 } | 538 } |
| 569 | 539 |
| 570 if (exception_target != nullptr) { | 540 if (exception_target != nullptr) { |
| 571 // Find all uncaught 'calls' in the inlinee. | 541 // Find all uncaught 'calls' in the inlinee. |
| 572 AllNodes inlined_nodes(local_zone_, end, graph()); | 542 AllNodes inlined_nodes(local_zone_, end, graph()); |
| 573 for (Node* subnode : inlined_nodes.reachable) { | 543 for (Node* subnode : inlined_nodes.reachable) { |
| 574 // Every possibly throwing node with an IfSuccess should get an | 544 // Every possibly throwing node with an IfSuccess should get an |
| 575 // IfException. | 545 // IfException. |
| 576 if (subnode->op()->HasProperty(Operator::kNoThrow)) { | 546 if (subnode->op()->HasProperty(Operator::kNoThrow)) { |
| 577 continue; | 547 continue; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 | 670 |
| 701 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } | 671 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } |
| 702 | 672 |
| 703 SimplifiedOperatorBuilder* JSInliner::simplified() const { | 673 SimplifiedOperatorBuilder* JSInliner::simplified() const { |
| 704 return jsgraph()->simplified(); | 674 return jsgraph()->simplified(); |
| 705 } | 675 } |
| 706 | 676 |
| 707 } // namespace compiler | 677 } // namespace compiler |
| 708 } // namespace internal | 678 } // namespace internal |
| 709 } // namespace v8 | 679 } // namespace v8 |
| OLD | NEW |