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 |