OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/compiler.h" | 5 #include "vm/compiler.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 | 8 |
9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
10 #include "vm/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 bool optimized, | 407 bool optimized, |
408 intptr_t osr_id) { | 408 intptr_t osr_id) { |
409 const Function& function = parsed_function->function(); | 409 const Function& function = parsed_function->function(); |
410 if (optimized && !function.IsOptimizable()) { | 410 if (optimized && !function.IsOptimizable()) { |
411 return false; | 411 return false; |
412 } | 412 } |
413 bool is_compiled = false; | 413 bool is_compiled = false; |
414 Thread* const thread = Thread::Current(); | 414 Thread* const thread = Thread::Current(); |
415 Zone* const zone = thread->zone(); | 415 Zone* const zone = thread->zone(); |
416 Isolate* const isolate = thread->isolate(); | 416 Isolate* const isolate = thread->isolate(); |
| 417 TimelineStream* compiler_timeline = isolate->GetCompilerStream(); |
417 CSTAT_TIMER_SCOPE(thread, codegen_timer); | 418 CSTAT_TIMER_SCOPE(thread, codegen_timer); |
418 HANDLESCOPE(thread); | 419 HANDLESCOPE(thread); |
419 | 420 |
420 // Get current generation count so that we can check and ensure that the code | 421 // Get current generation count so that we can check and ensure that the code |
421 // was not invalidated while we were compiling in the background. | 422 // was not invalidated while we were compiling in the background. |
422 uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen(); | 423 uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen(); |
423 uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen(); | 424 uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen(); |
424 uint32_t prefix_invalidation_gen_at_start = | 425 uint32_t prefix_invalidation_gen_at_start = |
425 isolate->prefix_invalidation_gen(); | 426 isolate->prefix_invalidation_gen(); |
426 | 427 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 if (FLAG_print_ic_data_map) { | 469 if (FLAG_print_ic_data_map) { |
469 for (intptr_t i = 0; i < ic_data_array->length(); i++) { | 470 for (intptr_t i = 0; i < ic_data_array->length(); i++) { |
470 if ((*ic_data_array)[i] != NULL) { | 471 if ((*ic_data_array)[i] != NULL) { |
471 THR_Print("%" Pd " ", i); | 472 THR_Print("%" Pd " ", i); |
472 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); | 473 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); |
473 } | 474 } |
474 } | 475 } |
475 } | 476 } |
476 } | 477 } |
477 | 478 |
| 479 TimelineDurationScope tds(thread, |
| 480 compiler_timeline, |
| 481 "BuildFlowGraph"); |
478 flow_graph = pipeline->BuildFlowGraph(zone, | 482 flow_graph = pipeline->BuildFlowGraph(zone, |
479 parsed_function, | 483 parsed_function, |
480 *ic_data_array, | 484 *ic_data_array, |
481 osr_id); | 485 osr_id); |
482 } | 486 } |
483 | 487 |
484 const bool print_flow_graph = | 488 const bool print_flow_graph = |
485 (FLAG_print_flow_graph || | 489 (FLAG_print_flow_graph || |
486 (optimized && FLAG_print_flow_graph_optimized)) && | 490 (optimized && FLAG_print_flow_graph_optimized)) && |
487 FlowGraphPrinter::ShouldPrint(function); | 491 FlowGraphPrinter::ShouldPrint(function); |
488 | 492 |
489 if (print_flow_graph) { | 493 if (print_flow_graph) { |
490 if (osr_id == Compiler::kNoOSRDeoptId) { | 494 if (osr_id == Compiler::kNoOSRDeoptId) { |
491 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | 495 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
492 } else { | 496 } else { |
493 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); | 497 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); |
494 } | 498 } |
495 } | 499 } |
496 | 500 |
497 BlockScheduler block_scheduler(flow_graph); | 501 BlockScheduler block_scheduler(flow_graph); |
498 const bool reorder_blocks = | 502 const bool reorder_blocks = |
499 FlowGraph::ShouldReorderBlocks(function, optimized); | 503 FlowGraph::ShouldReorderBlocks(function, optimized); |
500 if (reorder_blocks) { | 504 if (reorder_blocks) { |
| 505 TimelineDurationScope tds(thread, |
| 506 compiler_timeline, |
| 507 "BlockScheduler::AssignEdgeWeights"); |
501 block_scheduler.AssignEdgeWeights(); | 508 block_scheduler.AssignEdgeWeights(); |
502 } | 509 } |
503 | 510 |
504 if (optimized) { | 511 if (optimized) { |
| 512 TimelineDurationScope tds(thread, |
| 513 compiler_timeline, |
| 514 "ComputeSSA"); |
505 CSTAT_TIMER_SCOPE(thread, ssa_timer); | 515 CSTAT_TIMER_SCOPE(thread, ssa_timer); |
506 // Transform to SSA (virtual register 0 and no inlining arguments). | 516 // Transform to SSA (virtual register 0 and no inlining arguments). |
507 flow_graph->ComputeSSA(0, NULL); | 517 flow_graph->ComputeSSA(0, NULL); |
508 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 518 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
509 if (print_flow_graph) { | 519 if (print_flow_graph) { |
510 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); | 520 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); |
511 } | 521 } |
512 } | 522 } |
513 | 523 |
514 // Maps inline_id_to_function[inline_id] -> function. Top scope | 524 // Maps inline_id_to_function[inline_id] -> function. Top scope |
515 // function has inline_id 0. The map is populated by the inliner. | 525 // function has inline_id 0. The map is populated by the inliner. |
516 GrowableArray<const Function*> inline_id_to_function; | 526 GrowableArray<const Function*> inline_id_to_function; |
517 // For a given inlining-id(index) specifies the caller's inlining-id. | 527 // For a given inlining-id(index) specifies the caller's inlining-id. |
518 GrowableArray<intptr_t> caller_inline_id; | 528 GrowableArray<intptr_t> caller_inline_id; |
519 // Collect all instance fields that are loaded in the graph and | 529 // Collect all instance fields that are loaded in the graph and |
520 // have non-generic type feedback attached to them that can | 530 // have non-generic type feedback attached to them that can |
521 // potentially affect optimizations. | 531 // potentially affect optimizations. |
522 if (optimized) { | 532 if (optimized) { |
| 533 TimelineDurationScope tds(thread, |
| 534 compiler_timeline, |
| 535 "OptimizationPasses"); |
523 inline_id_to_function.Add(&function); | 536 inline_id_to_function.Add(&function); |
524 // Top scope function has no caller (-1). | 537 // Top scope function has no caller (-1). |
525 caller_inline_id.Add(-1); | 538 caller_inline_id.Add(-1); |
526 CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer); | 539 CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer); |
527 | 540 |
528 FlowGraphOptimizer optimizer(flow_graph, | 541 FlowGraphOptimizer optimizer(flow_graph, |
529 use_speculative_inlining, | 542 use_speculative_inlining, |
530 &inlining_black_list); | 543 &inlining_black_list); |
531 if (Compiler::always_optimize()) { | 544 if (Compiler::always_optimize()) { |
532 optimizer.PopulateWithICData(); | 545 optimizer.PopulateWithICData(); |
533 | 546 |
534 optimizer.ApplyClassIds(); | 547 optimizer.ApplyClassIds(); |
535 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 548 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
536 | 549 |
537 FlowGraphTypePropagator::Propagate(flow_graph); | 550 FlowGraphTypePropagator::Propagate(flow_graph); |
538 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 551 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
539 } | 552 } |
540 optimizer.ApplyICData(); | 553 optimizer.ApplyICData(); |
541 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 554 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
542 | 555 |
543 // Optimize (a << b) & c patterns, merge operations. | 556 // Optimize (a << b) & c patterns, merge operations. |
544 // Run early in order to have more opportunity to optimize left shifts. | 557 // Run early in order to have more opportunity to optimize left shifts. |
545 optimizer.TryOptimizePatterns(); | 558 optimizer.TryOptimizePatterns(); |
546 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 559 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
547 | 560 |
548 FlowGraphInliner::SetInliningId(flow_graph, 0); | 561 FlowGraphInliner::SetInliningId(flow_graph, 0); |
549 | 562 |
550 // Inlining (mutates the flow graph) | 563 // Inlining (mutates the flow graph) |
551 if (FLAG_use_inlining) { | 564 if (FLAG_use_inlining) { |
| 565 TimelineDurationScope tds2(thread, |
| 566 compiler_timeline, |
| 567 "Inlining"); |
552 CSTAT_TIMER_SCOPE(thread, graphinliner_timer); | 568 CSTAT_TIMER_SCOPE(thread, graphinliner_timer); |
553 // Propagate types to create more inlining opportunities. | 569 // Propagate types to create more inlining opportunities. |
554 FlowGraphTypePropagator::Propagate(flow_graph); | 570 FlowGraphTypePropagator::Propagate(flow_graph); |
555 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 571 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
556 | 572 |
557 // Use propagated class-ids to create more inlining opportunities. | 573 // Use propagated class-ids to create more inlining opportunities. |
558 optimizer.ApplyClassIds(); | 574 optimizer.ApplyClassIds(); |
559 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 575 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
560 | 576 |
561 FlowGraphInliner inliner(flow_graph, | 577 FlowGraphInliner inliner(flow_graph, |
562 &inline_id_to_function, | 578 &inline_id_to_function, |
563 &caller_inline_id, | 579 &caller_inline_id, |
564 use_speculative_inlining, | 580 use_speculative_inlining, |
565 &inlining_black_list); | 581 &inlining_black_list); |
566 inliner.Inline(); | 582 inliner.Inline(); |
567 // Use lists are maintained and validated by the inliner. | 583 // Use lists are maintained and validated by the inliner. |
568 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 584 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
569 } | 585 } |
570 | 586 |
571 // Propagate types and eliminate more type tests. | 587 // Propagate types and eliminate more type tests. |
572 FlowGraphTypePropagator::Propagate(flow_graph); | 588 FlowGraphTypePropagator::Propagate(flow_graph); |
573 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 589 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
574 | 590 |
575 // Use propagated class-ids to optimize further. | 591 { |
576 optimizer.ApplyClassIds(); | 592 TimelineDurationScope tds2(thread, |
577 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 593 compiler_timeline, |
| 594 "ApplyClassIds"); |
| 595 // Use propagated class-ids to optimize further. |
| 596 optimizer.ApplyClassIds(); |
| 597 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 598 } |
578 | 599 |
579 // Propagate types for potentially newly added instructions by | 600 // Propagate types for potentially newly added instructions by |
580 // ApplyClassIds(). Must occur before canonicalization. | 601 // ApplyClassIds(). Must occur before canonicalization. |
581 FlowGraphTypePropagator::Propagate(flow_graph); | 602 FlowGraphTypePropagator::Propagate(flow_graph); |
582 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 603 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
583 | 604 |
584 // Do optimizations that depend on the propagated type information. | 605 // Do optimizations that depend on the propagated type information. |
585 if (optimizer.Canonicalize()) { | 606 if (optimizer.Canonicalize()) { |
586 // Invoke Canonicalize twice in order to fully canonicalize patterns | 607 // Invoke Canonicalize twice in order to fully canonicalize patterns |
587 // like "if (a & const == 0) { }". | 608 // like "if (a & const == 0) { }". |
588 optimizer.Canonicalize(); | 609 optimizer.Canonicalize(); |
589 } | 610 } |
590 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 611 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
591 | 612 |
592 BranchSimplifier::Simplify(flow_graph); | 613 { |
593 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 614 TimelineDurationScope tds2(thread, |
| 615 compiler_timeline, |
| 616 "BranchSimplifier"); |
| 617 BranchSimplifier::Simplify(flow_graph); |
| 618 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
594 | 619 |
595 IfConverter::Simplify(flow_graph); | 620 IfConverter::Simplify(flow_graph); |
596 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 621 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 622 } |
597 | 623 |
598 if (FLAG_constant_propagation) { | 624 if (FLAG_constant_propagation) { |
| 625 TimelineDurationScope tds2(thread, |
| 626 compiler_timeline, |
| 627 "ConstantPropagation"); |
599 ConstantPropagator::Optimize(flow_graph); | 628 ConstantPropagator::Optimize(flow_graph); |
600 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 629 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
601 // A canonicalization pass to remove e.g. smi checks on smi constants. | 630 // A canonicalization pass to remove e.g. smi checks on smi constants. |
602 optimizer.Canonicalize(); | 631 optimizer.Canonicalize(); |
603 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 632 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
604 // Canonicalization introduced more opportunities for constant | 633 // Canonicalization introduced more opportunities for constant |
605 // propagation. | 634 // propagation. |
606 ConstantPropagator::Optimize(flow_graph); | 635 ConstantPropagator::Optimize(flow_graph); |
607 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 636 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
608 } | 637 } |
609 | 638 |
610 // Optimistically convert loop phis that have a single non-smi input | 639 // Optimistically convert loop phis that have a single non-smi input |
611 // coming from the loop pre-header into smi-phis. | 640 // coming from the loop pre-header into smi-phis. |
612 if (FLAG_loop_invariant_code_motion) { | 641 if (FLAG_loop_invariant_code_motion) { |
613 LICM licm(flow_graph); | 642 LICM licm(flow_graph); |
614 licm.OptimisticallySpecializeSmiPhis(); | 643 licm.OptimisticallySpecializeSmiPhis(); |
615 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 644 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
616 } | 645 } |
617 | 646 |
618 // Propagate types and eliminate even more type tests. | 647 // Propagate types and eliminate even more type tests. |
619 // Recompute types after constant propagation to infer more precise | 648 // Recompute types after constant propagation to infer more precise |
620 // types for uses that were previously reached by now eliminated phis. | 649 // types for uses that were previously reached by now eliminated phis. |
621 FlowGraphTypePropagator::Propagate(flow_graph); | 650 FlowGraphTypePropagator::Propagate(flow_graph); |
622 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 651 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
623 | 652 |
624 // Where beneficial convert Smi operations into Int32 operations. | 653 { |
625 // Only meanigful for 32bit platforms right now. | 654 TimelineDurationScope tds2(thread, |
626 optimizer.WidenSmiToInt32(); | 655 compiler_timeline, |
| 656 "SelectRepresentations"); |
| 657 // Where beneficial convert Smi operations into Int32 operations. |
| 658 // Only meanigful for 32bit platforms right now. |
| 659 optimizer.WidenSmiToInt32(); |
627 | 660 |
628 // Unbox doubles. Performed after constant propagation to minimize | 661 // Unbox doubles. Performed after constant propagation to minimize |
629 // interference from phis merging double values and tagged | 662 // interference from phis merging double values and tagged |
630 // values coming from dead paths. | 663 // values coming from dead paths. |
631 optimizer.SelectRepresentations(); | 664 optimizer.SelectRepresentations(); |
632 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 665 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
633 | |
634 if (FLAG_common_subexpression_elimination || | |
635 FLAG_loop_invariant_code_motion) { | |
636 flow_graph->ComputeBlockEffects(); | |
637 } | 666 } |
638 | 667 |
639 if (FLAG_common_subexpression_elimination) { | 668 { |
640 if (DominatorBasedCSE::Optimize(flow_graph)) { | 669 TimelineDurationScope tds2(thread, |
641 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 670 compiler_timeline, |
642 optimizer.Canonicalize(); | 671 "CommonSubexpressionElinination"); |
643 // Do another round of CSE to take secondary effects into account: | 672 if (FLAG_common_subexpression_elimination || |
644 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) | 673 FLAG_loop_invariant_code_motion) { |
645 // TODO(fschneider): Change to a one-pass optimization pass. | 674 flow_graph->ComputeBlockEffects(); |
| 675 } |
| 676 |
| 677 if (FLAG_common_subexpression_elimination) { |
646 if (DominatorBasedCSE::Optimize(flow_graph)) { | 678 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 679 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
647 optimizer.Canonicalize(); | 680 optimizer.Canonicalize(); |
| 681 // Do another round of CSE to take secondary effects into account: |
| 682 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) |
| 683 // TODO(fschneider): Change to a one-pass optimization pass. |
| 684 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 685 optimizer.Canonicalize(); |
| 686 } |
| 687 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
648 } | 688 } |
| 689 } |
| 690 |
| 691 // Run loop-invariant code motion right after load elimination since |
| 692 // it depends on the numbering of loads from the previous |
| 693 // load-elimination. |
| 694 if (FLAG_loop_invariant_code_motion) { |
| 695 LICM licm(flow_graph); |
| 696 licm.Optimize(); |
649 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 697 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
650 } | 698 } |
| 699 flow_graph->RemoveRedefinitions(); |
651 } | 700 } |
652 | 701 |
653 // Run loop-invariant code motion right after load elimination since it | |
654 // depends on the numbering of loads from the previous load-elimination. | |
655 if (FLAG_loop_invariant_code_motion) { | |
656 LICM licm(flow_graph); | |
657 licm.Optimize(); | |
658 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
659 } | |
660 flow_graph->RemoveRedefinitions(); | |
661 | |
662 // Optimize (a << b) & c patterns, merge operations. | 702 // Optimize (a << b) & c patterns, merge operations. |
663 // Run after CSE in order to have more opportunity to merge | 703 // Run after CSE in order to have more opportunity to merge |
664 // instructions that have same inputs. | 704 // instructions that have same inputs. |
665 optimizer.TryOptimizePatterns(); | 705 optimizer.TryOptimizePatterns(); |
666 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 706 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
667 | 707 |
668 DeadStoreElimination::Optimize(flow_graph); | 708 { |
| 709 TimelineDurationScope tds2(thread, |
| 710 compiler_timeline, |
| 711 "DeadStoreElimination"); |
| 712 DeadStoreElimination::Optimize(flow_graph); |
| 713 } |
669 | 714 |
670 if (FLAG_range_analysis) { | 715 if (FLAG_range_analysis) { |
| 716 TimelineDurationScope tds2(thread, |
| 717 compiler_timeline, |
| 718 "RangeAnalysis"); |
671 // Propagate types after store-load-forwarding. Some phis may have | 719 // Propagate types after store-load-forwarding. Some phis may have |
672 // become smi phis that can be processed by range analysis. | 720 // become smi phis that can be processed by range analysis. |
673 FlowGraphTypePropagator::Propagate(flow_graph); | 721 FlowGraphTypePropagator::Propagate(flow_graph); |
674 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 722 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
675 | 723 |
676 // We have to perform range analysis after LICM because it | 724 // We have to perform range analysis after LICM because it |
677 // optimistically moves CheckSmi through phis into loop preheaders | 725 // optimistically moves CheckSmi through phis into loop preheaders |
678 // making some phis smi. | 726 // making some phis smi. |
679 optimizer.InferIntRanges(); | 727 optimizer.InferIntRanges(); |
680 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 728 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
681 } | 729 } |
682 | 730 |
683 if (FLAG_constant_propagation) { | 731 if (FLAG_constant_propagation) { |
| 732 TimelineDurationScope tds2(thread, |
| 733 compiler_timeline, |
| 734 "ConstantPropagator::OptimizeBranches"); |
684 // Constant propagation can use information from range analysis to | 735 // Constant propagation can use information from range analysis to |
685 // find unreachable branch targets and eliminate branches that have | 736 // find unreachable branch targets and eliminate branches that have |
686 // the same true- and false-target. | 737 // the same true- and false-target. |
687 ConstantPropagator::OptimizeBranches(flow_graph); | 738 ConstantPropagator::OptimizeBranches(flow_graph); |
688 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 739 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
689 } | 740 } |
690 | 741 |
691 // Recompute types after code movement was done to ensure correct | 742 // Recompute types after code movement was done to ensure correct |
692 // reaching types for hoisted values. | 743 // reaching types for hoisted values. |
693 FlowGraphTypePropagator::Propagate(flow_graph); | 744 FlowGraphTypePropagator::Propagate(flow_graph); |
694 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 745 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
695 | 746 |
696 // Optimize try-blocks. | 747 { |
697 TryCatchAnalyzer::Optimize(flow_graph); | 748 TimelineDurationScope tds2(thread, |
| 749 compiler_timeline, |
| 750 "TryCatchAnalyzer::Optimize"); |
| 751 // Optimize try-blocks. |
| 752 TryCatchAnalyzer::Optimize(flow_graph); |
| 753 } |
698 | 754 |
699 // Detach environments from the instructions that can't deoptimize. | 755 // Detach environments from the instructions that can't deoptimize. |
700 // Do it before we attempt to perform allocation sinking to minimize | 756 // Do it before we attempt to perform allocation sinking to minimize |
701 // amount of materializations it has to perform. | 757 // amount of materializations it has to perform. |
702 optimizer.EliminateEnvironments(); | 758 optimizer.EliminateEnvironments(); |
703 | 759 |
704 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 760 { |
705 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 761 TimelineDurationScope tds2(thread, |
| 762 compiler_timeline, |
| 763 "EliminateDeadPhis"); |
| 764 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
| 765 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 766 } |
706 | 767 |
707 if (optimizer.Canonicalize()) { | 768 if (optimizer.Canonicalize()) { |
708 optimizer.Canonicalize(); | 769 optimizer.Canonicalize(); |
709 } | 770 } |
710 | 771 |
711 // Attempt to sink allocations of temporary non-escaping objects to | 772 // Attempt to sink allocations of temporary non-escaping objects to |
712 // the deoptimization path. | 773 // the deoptimization path. |
713 AllocationSinking* sinking = NULL; | 774 AllocationSinking* sinking = NULL; |
714 if (FLAG_allocation_sinking && | 775 if (FLAG_allocation_sinking && |
715 (flow_graph->graph_entry()->SuccessorCount() == 1)) { | 776 (flow_graph->graph_entry()->SuccessorCount() == 1)) { |
| 777 TimelineDurationScope tds2(thread, |
| 778 compiler_timeline, |
| 779 "AllocationSinking::Optimize"); |
716 // TODO(fschneider): Support allocation sinking with try-catch. | 780 // TODO(fschneider): Support allocation sinking with try-catch. |
717 sinking = new AllocationSinking(flow_graph); | 781 sinking = new AllocationSinking(flow_graph); |
718 sinking->Optimize(); | 782 sinking->Optimize(); |
719 } | 783 } |
720 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 784 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
721 | 785 |
722 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 786 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
723 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 787 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
724 | 788 |
725 FlowGraphTypePropagator::Propagate(flow_graph); | 789 FlowGraphTypePropagator::Propagate(flow_graph); |
726 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 790 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
727 | 791 |
728 // Ensure that all phis inserted by optimization passes have consistent | 792 { |
729 // representations. | 793 TimelineDurationScope tds2(thread, |
730 optimizer.SelectRepresentations(); | 794 compiler_timeline, |
| 795 "SelectRepresentations"); |
| 796 // Ensure that all phis inserted by optimization passes have |
| 797 // consistent representations. |
| 798 optimizer.SelectRepresentations(); |
| 799 } |
731 | 800 |
732 if (optimizer.Canonicalize()) { | 801 if (optimizer.Canonicalize()) { |
733 // To fully remove redundant boxing (e.g. BoxDouble used only in | 802 // To fully remove redundant boxing (e.g. BoxDouble used only in |
734 // environments and UnboxDouble instructions) instruction we | 803 // environments and UnboxDouble instructions) instruction we |
735 // first need to replace all their uses and then fold them away. | 804 // first need to replace all their uses and then fold them away. |
736 // For now we just repeat Canonicalize twice to do that. | 805 // For now we just repeat Canonicalize twice to do that. |
737 // TODO(vegorov): implement a separate representation folding pass. | 806 // TODO(vegorov): implement a separate representation folding pass. |
738 optimizer.Canonicalize(); | 807 optimizer.Canonicalize(); |
739 } | 808 } |
740 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 809 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
741 | 810 |
742 if (sinking != NULL) { | 811 if (sinking != NULL) { |
| 812 TimelineDurationScope tds2( |
| 813 thread, |
| 814 compiler_timeline, |
| 815 "AllocationSinking::DetachMaterializations"); |
743 // Remove all MaterializeObject instructions inserted by allocation | 816 // Remove all MaterializeObject instructions inserted by allocation |
744 // sinking from the flow graph and let them float on the side | 817 // sinking from the flow graph and let them float on the side |
745 // referenced only from environments. Register allocator will consider | 818 // referenced only from environments. Register allocator will consider |
746 // them as part of a deoptimization environment. | 819 // them as part of a deoptimization environment. |
747 sinking->DetachMaterializations(); | 820 sinking->DetachMaterializations(); |
748 } | 821 } |
749 | 822 |
750 // Compute and store graph informations (call & instruction counts) | 823 // Compute and store graph informations (call & instruction counts) |
751 // to be later used by the inliner. | 824 // to be later used by the inliner. |
752 FlowGraphInliner::CollectGraphInfo(flow_graph, true); | 825 FlowGraphInliner::CollectGraphInfo(flow_graph, true); |
753 | 826 |
754 // Perform register allocation on the SSA graph. | 827 { |
755 FlowGraphAllocator allocator(*flow_graph); | 828 TimelineDurationScope tds2(thread, |
756 allocator.AllocateRegisters(); | 829 compiler_timeline, |
757 if (reorder_blocks) block_scheduler.ReorderBlocks(); | 830 "AllocateRegisters"); |
| 831 // Perform register allocation on the SSA graph. |
| 832 FlowGraphAllocator allocator(*flow_graph); |
| 833 allocator.AllocateRegisters(); |
| 834 } |
| 835 |
| 836 if (reorder_blocks) { |
| 837 TimelineDurationScope tds(thread, |
| 838 compiler_timeline, |
| 839 "BlockScheduler::ReorderBlocks"); |
| 840 block_scheduler.ReorderBlocks(); |
| 841 } |
758 | 842 |
759 if (print_flow_graph) { | 843 if (print_flow_graph) { |
760 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); | 844 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); |
761 } | 845 } |
762 } | 846 } |
763 | 847 |
764 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); | 848 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); |
765 Assembler assembler(use_far_branches); | 849 Assembler assembler(use_far_branches); |
766 FlowGraphCompiler graph_compiler(&assembler, flow_graph, | 850 FlowGraphCompiler graph_compiler(&assembler, flow_graph, |
767 *parsed_function, optimized, | 851 *parsed_function, optimized, |
768 inline_id_to_function, | 852 inline_id_to_function, |
769 caller_inline_id); | 853 caller_inline_id); |
770 { | 854 { |
771 CSTAT_TIMER_SCOPE(thread, graphcompiler_timer); | 855 CSTAT_TIMER_SCOPE(thread, graphcompiler_timer); |
| 856 TimelineDurationScope tds(thread, |
| 857 compiler_timeline, |
| 858 "CompileGraph"); |
772 graph_compiler.CompileGraph(); | 859 graph_compiler.CompileGraph(); |
773 pipeline->FinalizeCompilation(); | 860 pipeline->FinalizeCompilation(); |
774 } | 861 } |
775 { | 862 { |
| 863 TimelineDurationScope tds(thread, |
| 864 compiler_timeline, |
| 865 "FinalizeCompilation"); |
776 // This part of compilation must be at a safepoint. | 866 // This part of compilation must be at a safepoint. |
777 if (!Thread::Current()->IsMutatorThread()) { | 867 if (!Thread::Current()->IsMutatorThread()) { |
778 // Stop mutator thread before creating the instruction object and | 868 // Stop mutator thread before creating the instruction object and |
779 // installing code. | 869 // installing code. |
780 // Mutator thread may not run code while we are creating the | 870 // Mutator thread may not run code while we are creating the |
781 // instruction object, since the creation of instruction object | 871 // instruction object, since the creation of instruction object |
782 // changes code page access permissions (makes them temporary not | 872 // changes code page access permissions (makes them temporary not |
783 // executable). | 873 // executable). |
784 isolate->thread_registry()->SafepointThreads(); | 874 isolate->thread_registry()->SafepointThreads(); |
785 } | 875 } |
(...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1888 } | 1978 } |
1889 | 1979 |
1890 | 1980 |
1891 void BackgroundCompiler::EnsureInit(Thread* thread) { | 1981 void BackgroundCompiler::EnsureInit(Thread* thread) { |
1892 UNREACHABLE(); | 1982 UNREACHABLE(); |
1893 } | 1983 } |
1894 | 1984 |
1895 #endif // DART_PRECOMPILED | 1985 #endif // DART_PRECOMPILED |
1896 | 1986 |
1897 } // namespace dart | 1987 } // namespace dart |
OLD | NEW |