Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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/precompiler.h" | 5 #include "vm/precompiler.h" |
| 6 | 6 |
| 7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
| 10 #include "vm/branch_optimizer.h" | 10 #include "vm/branch_optimizer.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 | 47 |
| 48 #define T (thread()) | 48 #define T (thread()) |
| 49 #define I (isolate()) | 49 #define I (isolate()) |
| 50 #define Z (zone()) | 50 #define Z (zone()) |
| 51 | 51 |
| 52 | 52 |
| 53 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); | 53 DEFINE_FLAG(bool, print_unique_targets, false, "Print unique dynaic targets"); |
| 54 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); | 54 DEFINE_FLAG(bool, trace_precompiler, false, "Trace precompiler."); |
| 55 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, | 55 DEFINE_FLAG(int, max_speculative_inlining_attempts, 1, |
| 56 "Max number of attempts with speculative inlining (precompilation only)"); | 56 "Max number of attempts with speculative inlining (precompilation only)"); |
| 57 DEFINE_FLAG(int, precompiler_rounds, 1, "Number of precompiler iterations"); | 57 DEFINE_FLAG(int, precompiler_rounds, 2, "Number of precompiler iterations"); |
|
Vyacheslav Egorov (Google)
2016/05/12 11:18:55
We should check that this does not slow down Flutt
Florian Schneider
2016/05/12 11:37:17
Agree.
Current measurements shows 60% increase in
| |
| 58 | 58 |
| 59 DECLARE_FLAG(bool, allocation_sinking); | 59 DECLARE_FLAG(bool, allocation_sinking); |
| 60 DECLARE_FLAG(bool, common_subexpression_elimination); | 60 DECLARE_FLAG(bool, common_subexpression_elimination); |
| 61 DECLARE_FLAG(bool, constant_propagation); | 61 DECLARE_FLAG(bool, constant_propagation); |
| 62 DECLARE_FLAG(bool, loop_invariant_code_motion); | 62 DECLARE_FLAG(bool, loop_invariant_code_motion); |
| 63 DECLARE_FLAG(bool, print_flow_graph); | 63 DECLARE_FLAG(bool, print_flow_graph); |
| 64 DECLARE_FLAG(bool, print_flow_graph_optimized); | 64 DECLARE_FLAG(bool, print_flow_graph_optimized); |
| 65 DECLARE_FLAG(bool, range_analysis); | 65 DECLARE_FLAG(bool, range_analysis); |
| 66 DECLARE_FLAG(bool, trace_compiler); | 66 DECLARE_FLAG(bool, trace_compiler); |
| 67 DECLARE_FLAG(bool, trace_optimizing_compiler); | 67 DECLARE_FLAG(bool, trace_optimizing_compiler); |
| 68 DECLARE_FLAG(bool, trace_bailout); | 68 DECLARE_FLAG(bool, trace_bailout); |
| 69 DECLARE_FLAG(bool, use_inlining); | 69 DECLARE_FLAG(bool, use_inlining); |
| 70 DECLARE_FLAG(bool, verify_compiler); | 70 DECLARE_FLAG(bool, verify_compiler); |
| 71 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); | 71 DECLARE_FLAG(bool, huge_method_cutoff_in_code_size); |
| 72 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 72 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
| 73 DECLARE_FLAG(bool, trace_inlining_intervals); | 73 DECLARE_FLAG(bool, trace_inlining_intervals); |
| 74 DECLARE_FLAG(bool, trace_irregexp); | 74 DECLARE_FLAG(bool, trace_irregexp); |
| 75 | 75 |
| 76 #ifdef DART_PRECOMPILER | 76 #ifdef DART_PRECOMPILER |
| 77 | 77 |
| 78 class DartPrecompilationPipeline : public DartCompilationPipeline { | |
| 79 public: | |
| 80 DartPrecompilationPipeline() : result_type_(CompileType::None()) { } | |
| 81 | |
| 82 virtual void FinalizeCompilation(FlowGraph* flow_graph) { | |
| 83 CompileType result_type = CompileType::None(); | |
| 84 for (BlockIterator block_it = flow_graph->reverse_postorder_iterator(); | |
| 85 !block_it.Done(); | |
| 86 block_it.Advance()) { | |
| 87 ForwardInstructionIterator it(block_it.Current()); | |
| 88 for (; !it.Done(); it.Advance()) { | |
| 89 ReturnInstr* return_instr = it.Current()->AsReturn(); | |
| 90 if (return_instr != NULL) { | |
| 91 result_type.Union(return_instr->InputAt(0)->Type()); | |
| 92 } | |
| 93 } | |
| 94 } | |
| 95 result_type_ = result_type; | |
| 96 } | |
| 97 | |
| 98 CompileType result_type() { return result_type_; } | |
| 99 | |
| 100 private: | |
| 101 CompileType result_type_; | |
| 102 }; | |
| 103 | |
| 104 | |
| 78 class PrecompileParsedFunctionHelper : public ValueObject { | 105 class PrecompileParsedFunctionHelper : public ValueObject { |
| 79 public: | 106 public: |
| 80 PrecompileParsedFunctionHelper(ParsedFunction* parsed_function, | 107 PrecompileParsedFunctionHelper(ParsedFunction* parsed_function, |
| 81 bool optimized) | 108 bool optimized) |
| 82 : parsed_function_(parsed_function), | 109 : parsed_function_(parsed_function), |
| 83 optimized_(optimized), | 110 optimized_(optimized), |
| 84 thread_(Thread::Current()) { | 111 thread_(Thread::Current()) { |
| 85 } | 112 } |
| 86 | 113 |
| 87 bool Compile(CompilationPipeline* pipeline); | 114 bool Compile(CompilationPipeline* pipeline); |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 761 | 788 |
| 762 const bool is_initialized = value.raw() != Object::sentinel().raw(); | 789 const bool is_initialized = value.raw() != Object::sentinel().raw(); |
| 763 if (is_initialized && !reset_fields_) return; | 790 if (is_initialized && !reset_fields_) return; |
| 764 | 791 |
| 765 if (!field.HasPrecompiledInitializer() || | 792 if (!field.HasPrecompiledInitializer() || |
| 766 !Function::Handle(Z, field.PrecompiledInitializer()).HasCode()) { | 793 !Function::Handle(Z, field.PrecompiledInitializer()).HasCode()) { |
| 767 if (FLAG_trace_precompiler) { | 794 if (FLAG_trace_precompiler) { |
| 768 THR_Print("Precompiling initializer for %s\n", field.ToCString()); | 795 THR_Print("Precompiling initializer for %s\n", field.ToCString()); |
| 769 } | 796 } |
| 770 ASSERT(Dart::snapshot_kind() != Snapshot::kAppNoJIT); | 797 ASSERT(Dart::snapshot_kind() != Snapshot::kAppNoJIT); |
| 771 const Function& initializer = | 798 const Function& initializer = Function::Handle(Z, |
| 772 Function::Handle(Z, CompileStaticInitializer(field)); | 799 CompileStaticInitializer(field, /* compute_type = */ true)); |
| 773 ASSERT(!initializer.IsNull()); | 800 ASSERT(!initializer.IsNull()); |
| 774 field.SetPrecompiledInitializer(initializer); | 801 field.SetPrecompiledInitializer(initializer); |
| 775 AddCalleesOf(initializer); | 802 AddCalleesOf(initializer); |
| 776 } | 803 } |
| 777 } | 804 } |
| 778 } | 805 } |
| 779 } | 806 } |
| 780 | 807 |
| 781 | 808 |
| 782 RawFunction* Precompiler::CompileStaticInitializer(const Field& field) { | 809 RawFunction* Precompiler::CompileStaticInitializer(const Field& field, |
| 810 bool compute_type) { | |
| 783 ASSERT(field.is_static()); | 811 ASSERT(field.is_static()); |
| 784 Thread* thread = Thread::Current(); | 812 Thread* thread = Thread::Current(); |
| 785 StackZone zone(thread); | 813 StackZone zone(thread); |
| 786 | 814 |
| 787 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); | 815 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); |
| 788 | 816 |
| 789 parsed_function->AllocateVariables(); | 817 parsed_function->AllocateVariables(); |
| 790 DartCompilationPipeline pipeline; | 818 DartPrecompilationPipeline pipeline; |
| 791 PrecompileParsedFunctionHelper helper(parsed_function, | 819 PrecompileParsedFunctionHelper helper(parsed_function, |
| 792 /* optimized = */ true); | 820 /* optimized = */ true); |
| 793 bool success = helper.Compile(&pipeline); | 821 bool success = helper.Compile(&pipeline); |
| 794 ASSERT(success); | 822 ASSERT(success); |
| 795 | 823 |
| 824 if (compute_type && field.is_final()) { | |
| 825 intptr_t result_cid = pipeline.result_type().ToCid(); | |
| 826 if (result_cid != kDynamicCid) { | |
| 827 if (FLAG_trace_precompiler) { | |
| 828 THR_Print("Setting guarded_cid of %s to %s\n", field.ToCString(), | |
| 829 pipeline.result_type().ToCString()); | |
| 830 } | |
| 831 field.set_guarded_cid(result_cid); | |
| 832 } | |
| 833 } | |
| 834 | |
| 796 if ((FLAG_disassemble || FLAG_disassemble_optimized) && | 835 if ((FLAG_disassemble || FLAG_disassemble_optimized) && |
| 797 FlowGraphPrinter::ShouldPrint(parsed_function->function())) { | 836 FlowGraphPrinter::ShouldPrint(parsed_function->function())) { |
| 798 Disassembler::DisassembleCode(parsed_function->function(), | 837 Disassembler::DisassembleCode(parsed_function->function(), |
| 799 /* optimized = */ true); | 838 /* optimized = */ true); |
| 800 } | 839 } |
| 801 return parsed_function->function().raw(); | 840 return parsed_function->function().raw(); |
| 802 } | 841 } |
| 803 | 842 |
| 804 | 843 |
| 805 RawObject* Precompiler::EvaluateStaticInitializer(const Field& field) { | 844 RawObject* Precompiler::EvaluateStaticInitializer(const Field& field) { |
| 806 ASSERT(field.is_static()); | 845 ASSERT(field.is_static()); |
| 807 // The VM sets the field's value to transiton_sentinel prior to | 846 // The VM sets the field's value to transiton_sentinel prior to |
| 808 // evaluating the initializer value. | 847 // evaluating the initializer value. |
| 809 ASSERT(field.StaticValue() == Object::transition_sentinel().raw()); | 848 ASSERT(field.StaticValue() == Object::transition_sentinel().raw()); |
| 810 LongJumpScope jump; | 849 LongJumpScope jump; |
| 811 if (setjmp(*jump.Set()) == 0) { | 850 if (setjmp(*jump.Set()) == 0) { |
| 812 // Under precompilation, the initializer may have already been compiled, in | 851 // Under precompilation, the initializer may have already been compiled, in |
| 813 // which case use it. Under lazy compilation or early in precompilation, the | 852 // which case use it. Under lazy compilation or early in precompilation, the |
| 814 // initializer has not yet been created, so create it now, but don't bother | 853 // initializer has not yet been created, so create it now, but don't bother |
| 815 // remembering it because it won't be used again. | 854 // remembering it because it won't be used again. |
| 816 Function& initializer = Function::Handle(); | 855 Function& initializer = Function::Handle(); |
| 817 if (!field.HasPrecompiledInitializer()) { | 856 if (!field.HasPrecompiledInitializer()) { |
| 818 initializer = CompileStaticInitializer(field); | 857 initializer = CompileStaticInitializer(field, /* compute_type = */ false); |
| 819 } else { | 858 } else { |
| 820 initializer ^= field.PrecompiledInitializer(); | 859 initializer ^= field.PrecompiledInitializer(); |
| 821 } | 860 } |
| 822 // Invoke the function to evaluate the expression. | 861 // Invoke the function to evaluate the expression. |
| 823 return DartEntry::InvokeFunction(initializer, Object::empty_array()); | 862 return DartEntry::InvokeFunction(initializer, Object::empty_array()); |
| 824 } else { | 863 } else { |
| 825 Thread* const thread = Thread::Current(); | 864 Thread* const thread = Thread::Current(); |
| 826 StackZone zone(thread); | 865 StackZone zone(thread); |
| 827 const Error& error = | 866 const Error& error = |
| 828 Error::Handle(thread->zone(), thread->sticky_error()); | 867 Error::Handle(thread->zone(), thread->sticky_error()); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 869 // would compile func automatically. We are checking fewer invariants | 908 // would compile func automatically. We are checking fewer invariants |
| 870 // here. | 909 // here. |
| 871 ParsedFunction* parsed_function = new ParsedFunction(thread, func); | 910 ParsedFunction* parsed_function = new ParsedFunction(thread, func); |
| 872 parsed_function->SetNodeSequence(fragment); | 911 parsed_function->SetNodeSequence(fragment); |
| 873 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); | 912 fragment->scope()->AddVariable(parsed_function->EnsureExpressionTemp()); |
| 874 fragment->scope()->AddVariable( | 913 fragment->scope()->AddVariable( |
| 875 parsed_function->current_context_var()); | 914 parsed_function->current_context_var()); |
| 876 parsed_function->AllocateVariables(); | 915 parsed_function->AllocateVariables(); |
| 877 | 916 |
| 878 // Non-optimized code generator. | 917 // Non-optimized code generator. |
| 879 DartCompilationPipeline pipeline; | 918 DartPrecompilationPipeline pipeline; |
| 880 PrecompileParsedFunctionHelper helper(parsed_function, | 919 PrecompileParsedFunctionHelper helper(parsed_function, |
| 881 /* optimized = */ false); | 920 /* optimized = */ false); |
| 882 helper.Compile(&pipeline); | 921 helper.Compile(&pipeline); |
| 883 Code::Handle(func.unoptimized_code()).set_var_descriptors( | 922 Code::Handle(func.unoptimized_code()).set_var_descriptors( |
| 884 Object::empty_var_descriptors()); | 923 Object::empty_var_descriptors()); |
| 885 | 924 |
| 886 const Object& result = PassiveObject::Handle( | 925 const Object& result = PassiveObject::Handle( |
| 887 DartEntry::InvokeFunction(func, Object::empty_array())); | 926 DartEntry::InvokeFunction(func, Object::empty_array())); |
| 888 return result.raw(); | 927 return result.raw(); |
| 889 } else { | 928 } else { |
| (...skipping 1682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2572 inline_id_to_token_pos, | 2611 inline_id_to_token_pos, |
| 2573 caller_inline_id); | 2612 caller_inline_id); |
| 2574 { | 2613 { |
| 2575 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); | 2614 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); |
| 2576 #ifndef PRODUCT | 2615 #ifndef PRODUCT |
| 2577 TimelineDurationScope tds(thread(), | 2616 TimelineDurationScope tds(thread(), |
| 2578 compiler_timeline, | 2617 compiler_timeline, |
| 2579 "CompileGraph"); | 2618 "CompileGraph"); |
| 2580 #endif // !PRODUCT | 2619 #endif // !PRODUCT |
| 2581 graph_compiler.CompileGraph(); | 2620 graph_compiler.CompileGraph(); |
| 2582 pipeline->FinalizeCompilation(); | 2621 pipeline->FinalizeCompilation(flow_graph); |
| 2583 } | 2622 } |
| 2584 { | 2623 { |
| 2585 #ifndef PRODUCT | 2624 #ifndef PRODUCT |
| 2586 TimelineDurationScope tds(thread(), | 2625 TimelineDurationScope tds(thread(), |
| 2587 compiler_timeline, | 2626 compiler_timeline, |
| 2588 "FinalizeCompilation"); | 2627 "FinalizeCompilation"); |
| 2589 #endif // !PRODUCT | 2628 #endif // !PRODUCT |
| 2590 ASSERT(thread()->IsMutatorThread()); | 2629 ASSERT(thread()->IsMutatorThread()); |
| 2591 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); | 2630 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); |
| 2592 } | 2631 } |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2747 CompilationPipeline::New(thread->zone(), function); | 2786 CompilationPipeline::New(thread->zone(), function); |
| 2748 | 2787 |
| 2749 ASSERT(FLAG_precompiled_mode); | 2788 ASSERT(FLAG_precompiled_mode); |
| 2750 const bool optimized = function.IsOptimizable(); // False for natives. | 2789 const bool optimized = function.IsOptimizable(); // False for natives. |
| 2751 return PrecompileFunctionHelper(pipeline, function, optimized); | 2790 return PrecompileFunctionHelper(pipeline, function, optimized); |
| 2752 } | 2791 } |
| 2753 | 2792 |
| 2754 #endif // DART_PRECOMPILER | 2793 #endif // DART_PRECOMPILER |
| 2755 | 2794 |
| 2756 } // namespace dart | 2795 } // namespace dart |
| OLD | NEW |