| 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" | 7 #include "src/ast/ast-numbering.h" |
| 8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
| 9 #include "src/compilation-info.h" | 9 #include "src/compilation-info.h" |
| 10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
| 11 #include "src/compiler/all-nodes.h" | 11 #include "src/compiler/all-nodes.h" |
| 12 #include "src/compiler/ast-graph-builder.h" | 12 #include "src/compiler/ast-graph-builder.h" |
| 13 #include "src/compiler/ast-loop-assignment-analyzer.h" | 13 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 14 #include "src/compiler/bytecode-graph-builder.h" |
| 14 #include "src/compiler/common-operator.h" | 15 #include "src/compiler/common-operator.h" |
| 15 #include "src/compiler/graph-reducer.h" | 16 #include "src/compiler/graph-reducer.h" |
| 16 #include "src/compiler/js-operator.h" | 17 #include "src/compiler/js-operator.h" |
| 17 #include "src/compiler/node-matchers.h" | 18 #include "src/compiler/node-matchers.h" |
| 18 #include "src/compiler/node-properties.h" | 19 #include "src/compiler/node-properties.h" |
| 19 #include "src/compiler/operator-properties.h" | 20 #include "src/compiler/operator-properties.h" |
| 20 #include "src/compiler/simplified-operator.h" | 21 #include "src/compiler/simplified-operator.h" |
| 21 #include "src/compiler/type-hint-analyzer.h" | 22 #include "src/compiler/type-hint-analyzer.h" |
| 22 #include "src/isolate-inl.h" | 23 #include "src/isolate-inl.h" |
| 23 #include "src/parsing/parse-info.h" | 24 #include "src/parsing/parse-info.h" |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 info_->shared_info()->DebugName()->ToCString().get(), | 469 info_->shared_info()->DebugName()->ToCString().get(), |
| 469 exception_target->id(), exception_target->op()->mnemonic()); | 470 exception_target->id(), exception_target->op()->mnemonic()); |
| 470 } | 471 } |
| 471 } | 472 } |
| 472 | 473 |
| 473 Zone zone(info_->isolate()->allocator()); | 474 Zone zone(info_->isolate()->allocator()); |
| 474 ParseInfo parse_info(&zone, function); | 475 ParseInfo parse_info(&zone, function); |
| 475 CompilationInfo info(&parse_info, function); | 476 CompilationInfo info(&parse_info, function); |
| 476 if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled(); | 477 if (info_->is_deoptimization_enabled()) info.MarkAsDeoptimizationEnabled(); |
| 477 if (info_->is_type_feedback_enabled()) info.MarkAsTypeFeedbackEnabled(); | 478 if (info_->is_type_feedback_enabled()) info.MarkAsTypeFeedbackEnabled(); |
| 479 if (info_->is_optimizing_from_bytecode()) info.MarkAsOptimizeFromBytecode(); |
| 478 | 480 |
| 479 if (!Compiler::ParseAndAnalyze(info.parse_info())) { | 481 if (info.is_optimizing_from_bytecode() && !Compiler::EnsureBytecode(&info)) { |
| 482 TRACE("Not inlining %s into %s because bytecode generation failed\n", |
| 483 shared_info->DebugName()->ToCString().get(), |
| 484 info_->shared_info()->DebugName()->ToCString().get()); |
| 485 DCHECK(!info_->isolate()->has_pending_exception()); |
| 486 return NoChange(); |
| 487 } |
| 488 |
| 489 if (!info.is_optimizing_from_bytecode() && |
| 490 !Compiler::ParseAndAnalyze(info.parse_info())) { |
| 480 TRACE("Not inlining %s into %s because parsing failed\n", | 491 TRACE("Not inlining %s into %s because parsing failed\n", |
| 481 shared_info->DebugName()->ToCString().get(), | 492 shared_info->DebugName()->ToCString().get(), |
| 482 info_->shared_info()->DebugName()->ToCString().get()); | 493 info_->shared_info()->DebugName()->ToCString().get()); |
| 483 if (info_->isolate()->has_pending_exception()) { | 494 if (info_->isolate()->has_pending_exception()) { |
| 484 info_->isolate()->clear_pending_exception(); | 495 info_->isolate()->clear_pending_exception(); |
| 485 } | 496 } |
| 486 return NoChange(); | 497 return NoChange(); |
| 487 } | 498 } |
| 488 | 499 |
| 489 if (!Compiler::EnsureDeoptimizationSupport(&info)) { | 500 if (!info.is_optimizing_from_bytecode() && |
| 501 !Compiler::EnsureDeoptimizationSupport(&info)) { |
| 490 TRACE("Not inlining %s into %s because deoptimization support failed\n", | 502 TRACE("Not inlining %s into %s because deoptimization support failed\n", |
| 491 shared_info->DebugName()->ToCString().get(), | 503 shared_info->DebugName()->ToCString().get(), |
| 492 info_->shared_info()->DebugName()->ToCString().get()); | 504 info_->shared_info()->DebugName()->ToCString().get()); |
| 493 return NoChange(); | 505 return NoChange(); |
| 494 } | 506 } |
| 495 | 507 |
| 496 // Remember that we inlined this function. This needs to be called right | 508 // Remember that we inlined this function. This needs to be called right |
| 497 // after we ensure deoptimization support so that the code flusher | 509 // after we ensure deoptimization support so that the code flusher |
| 498 // does not remove the code with the deoptimization support. | 510 // does not remove the code with the deoptimization support. |
| 499 info_->AddInlinedFunction(shared_info); | 511 info_->AddInlinedFunction(shared_info); |
| 500 | 512 |
| 501 // ---------------------------------------------------------------- | 513 // ---------------------------------------------------------------- |
| 502 // 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. |
| 503 // We shall not bailout from inlining if we got here. | 515 // We shall not bailout from inlining if we got here. |
| 504 | 516 |
| 505 TRACE("Inlining %s into %s\n", | 517 TRACE("Inlining %s into %s\n", |
| 506 shared_info->DebugName()->ToCString().get(), | 518 shared_info->DebugName()->ToCString().get(), |
| 507 info_->shared_info()->DebugName()->ToCString().get()); | 519 info_->shared_info()->DebugName()->ToCString().get()); |
| 508 | 520 |
| 509 // 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. |
| 510 JSFunction::EnsureLiterals(function); | 522 JSFunction::EnsureLiterals(function); |
| 511 | 523 |
| 512 // Create the subgraph for the inlinee. | 524 // Create the subgraph for the inlinee. |
| 513 Node* start; | 525 Node* start; |
| 514 Node* end; | 526 Node* end; |
| 515 { | 527 if (info.is_optimizing_from_bytecode()) { |
| 528 // Run the BytecodeGraphBuilder to create the subgraph. |
| 529 Graph::SubgraphScope scope(graph()); |
| 530 BytecodeGraphBuilder graph_builder(&zone, &info, jsgraph(), |
| 531 call.frequency()); |
| 532 graph_builder.CreateGraph(); |
| 533 |
| 534 // Extract the inlinee start/end nodes. |
| 535 start = graph()->start(); |
| 536 end = graph()->end(); |
| 537 } else { |
| 516 // Run the loop assignment analyzer on the inlinee. | 538 // Run the loop assignment analyzer on the inlinee. |
| 517 AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info); | 539 AstLoopAssignmentAnalyzer loop_assignment_analyzer(&zone, &info); |
| 518 LoopAssignmentAnalysis* loop_assignment = | 540 LoopAssignmentAnalysis* loop_assignment = |
| 519 loop_assignment_analyzer.Analyze(); | 541 loop_assignment_analyzer.Analyze(); |
| 520 | 542 |
| 521 // Run the type hint analyzer on the inlinee. | 543 // Run the type hint analyzer on the inlinee. |
| 522 TypeHintAnalyzer type_hint_analyzer(&zone); | 544 TypeHintAnalyzer type_hint_analyzer(&zone); |
| 523 TypeHintAnalysis* type_hint_analysis = | 545 TypeHintAnalysis* type_hint_analysis = |
| 524 type_hint_analyzer.Analyze(handle(shared_info->code(), info.isolate())); | 546 type_hint_analyzer.Analyze(handle(shared_info->code(), info.isolate())); |
| 525 | 547 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 // type feedback in the compiler. | 631 // type feedback in the compiler. |
| 610 Node* context = jsgraph()->Constant(handle(function->context())); | 632 Node* context = jsgraph()->Constant(handle(function->context())); |
| 611 | 633 |
| 612 // Insert a JSConvertReceiver node for sloppy callees. Note that the context | 634 // Insert a JSConvertReceiver node for sloppy callees. Note that the context |
| 613 // passed into this node has to be the callees context (loaded above). Note | 635 // passed into this node has to be the callees context (loaded above). Note |
| 614 // that the frame state passed to the JSConvertReceiver must be the frame | 636 // that the frame state passed to the JSConvertReceiver must be the frame |
| 615 // state _before_ the call; it is not necessary to fiddle with the receiver | 637 // state _before_ the call; it is not necessary to fiddle with the receiver |
| 616 // in that frame state tho, as the conversion of the receiver can be repeated | 638 // in that frame state tho, as the conversion of the receiver can be repeated |
| 617 // any number of times, it's not observable. | 639 // any number of times, it's not observable. |
| 618 if (node->opcode() == IrOpcode::kJSCallFunction && | 640 if (node->opcode() == IrOpcode::kJSCallFunction && |
| 619 is_sloppy(parse_info.language_mode()) && !shared_info->native()) { | 641 is_sloppy(shared_info->language_mode()) && !shared_info->native()) { |
| 620 Node* effect = NodeProperties::GetEffectInput(node); | 642 Node* effect = NodeProperties::GetEffectInput(node); |
| 621 if (NeedsConvertReceiver(call.receiver(), effect)) { | 643 if (NeedsConvertReceiver(call.receiver(), effect)) { |
| 622 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); | 644 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); |
| 623 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); | 645 Node* frame_state_before = NodeProperties::FindFrameStateBefore(node); |
| 624 Node* convert = effect = graph()->NewNode( | 646 Node* convert = effect = graph()->NewNode( |
| 625 javascript()->ConvertReceiver(p.convert_mode()), call.receiver(), | 647 javascript()->ConvertReceiver(p.convert_mode()), call.receiver(), |
| 626 context, frame_state_before, effect, start); | 648 context, frame_state_before, effect, start); |
| 627 NodeProperties::ReplaceValueInput(node, convert, 1); | 649 NodeProperties::ReplaceValueInput(node, convert, 1); |
| 628 NodeProperties::ReplaceEffectInput(node, effect); | 650 NodeProperties::ReplaceEffectInput(node, effect); |
| 629 } | 651 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 640 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); | 662 const CallFunctionParameters& p = CallFunctionParametersOf(node->op()); |
| 641 if (p.tail_call_mode() == TailCallMode::kAllow) { | 663 if (p.tail_call_mode() == TailCallMode::kAllow) { |
| 642 frame_state = CreateTailCallerFrameState(node, frame_state); | 664 frame_state = CreateTailCallerFrameState(node, frame_state); |
| 643 } | 665 } |
| 644 } | 666 } |
| 645 | 667 |
| 646 // Insert argument adaptor frame if required. The callees formal parameter | 668 // Insert argument adaptor frame if required. The callees formal parameter |
| 647 // count (i.e. value outputs of start node minus target, receiver, new target, | 669 // count (i.e. value outputs of start node minus target, receiver, new target, |
| 648 // arguments count and context) have to match the number of arguments passed | 670 // arguments count and context) have to match the number of arguments passed |
| 649 // to the call. | 671 // to the call. |
| 650 int parameter_count = info.literal()->parameter_count(); | 672 int parameter_count = shared_info->internal_formal_parameter_count(); |
| 651 DCHECK_EQ(parameter_count, start->op()->ValueOutputCount() - 5); | 673 DCHECK_EQ(parameter_count, start->op()->ValueOutputCount() - 5); |
| 652 if (call.formal_arguments() != parameter_count) { | 674 if (call.formal_arguments() != parameter_count) { |
| 653 frame_state = CreateArtificialFrameState( | 675 frame_state = CreateArtificialFrameState( |
| 654 node, frame_state, call.formal_arguments(), | 676 node, frame_state, call.formal_arguments(), |
| 655 FrameStateType::kArgumentsAdaptor, shared_info); | 677 FrameStateType::kArgumentsAdaptor, shared_info); |
| 656 } | 678 } |
| 657 | 679 |
| 658 return InlineCall(node, new_target, context, frame_state, start, end, | 680 return InlineCall(node, new_target, context, frame_state, start, end, |
| 659 exception_target, uncaught_subcalls); | 681 exception_target, uncaught_subcalls); |
| 660 } | 682 } |
| 661 | 683 |
| 662 Graph* JSInliner::graph() const { return jsgraph()->graph(); } | 684 Graph* JSInliner::graph() const { return jsgraph()->graph(); } |
| 663 | 685 |
| 664 JSOperatorBuilder* JSInliner::javascript() const { | 686 JSOperatorBuilder* JSInliner::javascript() const { |
| 665 return jsgraph()->javascript(); | 687 return jsgraph()->javascript(); |
| 666 } | 688 } |
| 667 | 689 |
| 668 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } | 690 CommonOperatorBuilder* JSInliner::common() const { return jsgraph()->common(); } |
| 669 | 691 |
| 670 SimplifiedOperatorBuilder* JSInliner::simplified() const { | 692 SimplifiedOperatorBuilder* JSInliner::simplified() const { |
| 671 return jsgraph()->simplified(); | 693 return jsgraph()->simplified(); |
| 672 } | 694 } |
| 673 | 695 |
| 674 } // namespace compiler | 696 } // namespace compiler |
| 675 } // namespace internal | 697 } // namespace internal |
| 676 } // namespace v8 | 698 } // namespace v8 |
| OLD | NEW |