Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(658)

Side by Side Diff: runtime/vm/precompiler.cc

Issue 1958913003: VM precompiler: Allow optimizing static initializers. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/parser.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 752 matching lines...) Expand 10 before | Expand all | Expand 10 after
763 if (FLAG_trace_precompiler) { 763 if (FLAG_trace_precompiler) {
764 THR_Print("Precompiling initializer for %s\n", field.ToCString()); 764 THR_Print("Precompiling initializer for %s\n", field.ToCString());
765 } 765 }
766 ASSERT(Dart::snapshot_kind() != Snapshot::kAppNoJIT); 766 ASSERT(Dart::snapshot_kind() != Snapshot::kAppNoJIT);
767 field.SetStaticValue(Instance::Handle(field.SavedInitialStaticValue())); 767 field.SetStaticValue(Instance::Handle(field.SavedInitialStaticValue()));
768 const Function& initializer = 768 const Function& initializer =
769 Function::Handle(CompileStaticInitializer(field)); 769 Function::Handle(CompileStaticInitializer(field));
770 if (!initializer.IsNull()) { 770 if (!initializer.IsNull()) {
771 field.SetPrecompiledInitializer(initializer); 771 field.SetPrecompiledInitializer(initializer);
772 } 772 }
773 ASSERT(field.HasPrecompiledInitializer());
774 const Function& function =
775 Function::Handle(Z, field.PrecompiledInitializer());
776 AddCalleesOf(function);
773 } 777 }
774
775 const Function& function =
776 Function::Handle(Z, field.PrecompiledInitializer());
777 AddCalleesOf(function);
778 } 778 }
779 } 779 }
780 } 780 }
781 781
782 782
783 RawFunction* Precompiler::CompileStaticInitializer(const Field& field) { 783 RawFunction* Precompiler::CompileStaticInitializer(const Field& field) {
784 ASSERT(field.is_static()); 784 ASSERT(field.is_static());
785 if (field.HasPrecompiledInitializer()) { 785 ASSERT(!field.HasPrecompiledInitializer());
786 // TODO(rmacnak): Investigate why this happens for _enum_names.
787 THR_Print("Warning: Ignoring repeated request for initializer for %s\n",
788 field.ToCString());
789 return Function::null();
790 }
791 Thread* thread = Thread::Current(); 786 Thread* thread = Thread::Current();
792 StackZone zone(thread); 787 StackZone zone(thread);
793 788
794 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field); 789 ParsedFunction* parsed_function = Parser::ParseStaticFieldInitializer(field);
795 790
796 parsed_function->AllocateVariables(); 791 parsed_function->AllocateVariables();
797 // Non-optimized code generator.
798 DartCompilationPipeline pipeline; 792 DartCompilationPipeline pipeline;
799 PrecompileParsedFunctionHelper helper(parsed_function, 793 PrecompileParsedFunctionHelper helper(parsed_function,
800 /* optimized = */ false); 794 /* optimized = */ true);
801 helper.Compile(&pipeline); 795 bool success = helper.Compile(&pipeline);
796 ASSERT(success);
797
798 if ((FLAG_disassemble || FLAG_disassemble_optimized) &&
799 FlowGraphPrinter::ShouldPrint(parsed_function->function())) {
800 Disassembler::DisassembleCode(parsed_function->function(),
801 /* optimized = */ true);
802 }
802 return parsed_function->function().raw(); 803 return parsed_function->function().raw();
803 } 804 }
804 805
805 806
806 RawObject* Precompiler::EvaluateStaticInitializer(const Field& field) { 807 RawObject* Precompiler::EvaluateStaticInitializer(const Field& field) {
807 ASSERT(field.is_static()); 808 ASSERT(field.is_static());
808 // The VM sets the field's value to transiton_sentinel prior to 809 // The VM sets the field's value to transiton_sentinel prior to
809 // evaluating the initializer value. 810 // evaluating the initializer value.
810 ASSERT(field.StaticValue() == Object::transition_sentinel().raw()); 811 ASSERT(field.StaticValue() == Object::transition_sentinel().raw());
811 LongJumpScope jump; 812 LongJumpScope jump;
812 if (setjmp(*jump.Set()) == 0) { 813 if (setjmp(*jump.Set()) == 0) {
813 // Under precompilation, the initializer may have already been compiled, in 814 // Under precompilation, the initializer may have already been compiled, in
814 // which case use it. Under lazy compilation or early in precompilation, the 815 // which case use it. Under lazy compilation or early in precompilation, the
815 // initializer has not yet been created, so create it now, but don't bother 816 // initializer has not yet been created, so create it now, but don't bother
816 // remembering it because it won't be used again. 817 // remembering it because it won't be used again.
817 Function& initializer = Function::Handle(); 818 Function& initializer = Function::Handle();
818 if (!field.HasPrecompiledInitializer()) { 819 if (!field.HasPrecompiledInitializer()) {
819 initializer = CompileStaticInitializer(field); 820 initializer = CompileStaticInitializer(field);
820 Code::Handle(initializer.unoptimized_code()).set_var_descriptors(
821 Object::empty_var_descriptors());
822 } else { 821 } else {
823 initializer ^= field.PrecompiledInitializer(); 822 initializer ^= field.PrecompiledInitializer();
824 } 823 }
825 // Invoke the function to evaluate the expression. 824 // Invoke the function to evaluate the expression.
826 return DartEntry::InvokeFunction(initializer, Object::empty_array()); 825 return DartEntry::InvokeFunction(initializer, Object::empty_array());
827 } else { 826 } else {
828 Thread* const thread = Thread::Current(); 827 Thread* const thread = Thread::Current();
829 StackZone zone(thread); 828 StackZone zone(thread);
830 const Error& error = 829 const Error& error =
831 Error::Handle(thread->zone(), thread->sticky_error()); 830 Error::Handle(thread->zone(), thread->sticky_error());
(...skipping 1120 matching lines...) Expand 10 before | Expand all | Expand 10 after
1952 }; 1951 };
1953 1952
1954 DedupInstructionsVisitor visitor(Z); 1953 DedupInstructionsVisitor visitor(Z);
1955 VisitFunctions(&visitor); 1954 VisitFunctions(&visitor);
1956 } 1955 }
1957 1956
1958 void Precompiler::VisitFunctions(FunctionVisitor* visitor) { 1957 void Precompiler::VisitFunctions(FunctionVisitor* visitor) {
1959 Library& lib = Library::Handle(Z); 1958 Library& lib = Library::Handle(Z);
1960 Class& cls = Class::Handle(Z); 1959 Class& cls = Class::Handle(Z);
1961 Array& functions = Array::Handle(Z); 1960 Array& functions = Array::Handle(Z);
1961 Array& fields = Array::Handle(Z);
1962 Field& field = Field::Handle(Z);
1962 Object& object = Object::Handle(Z); 1963 Object& object = Object::Handle(Z);
1963 Function& function = Function::Handle(Z); 1964 Function& function = Function::Handle(Z);
1964 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z); 1965 GrowableObjectArray& closures = GrowableObjectArray::Handle(Z);
1965 1966
1966 for (intptr_t i = 0; i < libraries_.Length(); i++) { 1967 for (intptr_t i = 0; i < libraries_.Length(); i++) {
1967 lib ^= libraries_.At(i); 1968 lib ^= libraries_.At(i);
1968 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); 1969 ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
1969 while (it.HasNext()) { 1970 while (it.HasNext()) {
1970 cls = it.GetNextClass(); 1971 cls = it.GetNextClass();
1971 if (cls.IsDynamicClass()) { 1972 if (cls.IsDynamicClass()) {
(...skipping 11 matching lines...) Expand all
1983 } 1984 }
1984 1985
1985 functions = cls.invocation_dispatcher_cache(); 1986 functions = cls.invocation_dispatcher_cache();
1986 for (intptr_t j = 0; j < functions.Length(); j++) { 1987 for (intptr_t j = 0; j < functions.Length(); j++) {
1987 object = functions.At(j); 1988 object = functions.At(j);
1988 if (object.IsFunction()) { 1989 if (object.IsFunction()) {
1989 function ^= functions.At(j); 1990 function ^= functions.At(j);
1990 visitor->VisitFunction(function); 1991 visitor->VisitFunction(function);
1991 } 1992 }
1992 } 1993 }
1994 fields = cls.fields();
1995 for (intptr_t j = 0; j < fields.Length(); j++) {
1996 field ^= fields.At(j);
1997 if (field.is_static() && field.HasPrecompiledInitializer()) {
1998 function ^= field.PrecompiledInitializer();
1999 visitor->VisitFunction(function);
2000 }
2001 }
1993 } 2002 }
1994 } 2003 }
1995 closures = isolate()->object_store()->closure_functions(); 2004 closures = isolate()->object_store()->closure_functions();
1996 for (intptr_t j = 0; j < closures.Length(); j++) { 2005 for (intptr_t j = 0; j < closures.Length(); j++) {
1997 function ^= closures.At(j); 2006 function ^= closures.At(j);
1998 visitor->VisitFunction(function); 2007 visitor->VisitFunction(function);
1999 ASSERT(!function.HasImplicitClosureFunction()); 2008 ASSERT(!function.HasImplicitClosureFunction());
2000 } 2009 }
2001 } 2010 }
2002 2011
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
2123 } 2132 }
2124 2133
2125 2134
2126 // Return false if bailed out. 2135 // Return false if bailed out.
2127 // If optimized_result_code is not NULL then it is caller's responsibility 2136 // If optimized_result_code is not NULL then it is caller's responsibility
2128 // to install code. 2137 // to install code.
2129 bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { 2138 bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
2130 ASSERT(FLAG_precompiled_mode); 2139 ASSERT(FLAG_precompiled_mode);
2131 const Function& function = parsed_function()->function(); 2140 const Function& function = parsed_function()->function();
2132 if (optimized() && !function.IsOptimizable()) { 2141 if (optimized() && !function.IsOptimizable()) {
2142 // All functions compiled by precompiler must be optimizable.
2143 UNREACHABLE();
2133 return false; 2144 return false;
2134 } 2145 }
2135 bool is_compiled = false; 2146 bool is_compiled = false;
2136 Zone* const zone = thread()->zone(); 2147 Zone* const zone = thread()->zone();
2137 #ifndef PRODUCT 2148 #ifndef PRODUCT
2138 TimelineStream* compiler_timeline = Timeline::GetCompilerStream(); 2149 TimelineStream* compiler_timeline = Timeline::GetCompilerStream();
2139 #endif // !PRODUCT 2150 #endif // !PRODUCT
2140 CSTAT_TIMER_SCOPE(thread(), codegen_timer); 2151 CSTAT_TIMER_SCOPE(thread(), codegen_timer);
2141 HANDLESCOPE(thread()); 2152 HANDLESCOPE(thread());
2142 2153
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after
2698 // We got an error during compilation. 2709 // We got an error during compilation.
2699 error = thread->sticky_error(); 2710 error = thread->sticky_error();
2700 thread->clear_sticky_error(); 2711 thread->clear_sticky_error();
2701 ASSERT(error.IsLanguageError() && 2712 ASSERT(error.IsLanguageError() &&
2702 LanguageError::Cast(error).kind() != Report::kBailout); 2713 LanguageError::Cast(error).kind() != Report::kBailout);
2703 return error.raw(); 2714 return error.raw();
2704 } 2715 }
2705 2716
2706 per_compile_timer.Stop(); 2717 per_compile_timer.Stop();
2707 2718
2708 if (trace_compiler && success) { 2719 if (trace_compiler) {
2709 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n", 2720 THR_Print("--> '%s' entry: %#" Px " size: %" Pd " time: %" Pd64 " us\n",
2710 function.ToFullyQualifiedCString(), 2721 function.ToFullyQualifiedCString(),
2711 Code::Handle(function.CurrentCode()).EntryPoint(), 2722 Code::Handle(function.CurrentCode()).EntryPoint(),
2712 Code::Handle(function.CurrentCode()).Size(), 2723 Code::Handle(function.CurrentCode()).Size(),
2713 per_compile_timer.TotalElapsedTime()); 2724 per_compile_timer.TotalElapsedTime());
2714 } 2725 }
2715 2726
2716 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { 2727 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
2717 Disassembler::DisassembleCode(function, optimized); 2728 Disassembler::DisassembleCode(function, optimized);
2718 } else if (FLAG_disassemble_optimized && 2729 } else if (FLAG_disassemble_optimized &&
2719 optimized && 2730 optimized &&
2720 FlowGraphPrinter::ShouldPrint(function)) { 2731 FlowGraphPrinter::ShouldPrint(function)) {
2721 // TODO(fschneider): Print unoptimized code along with the optimized code.
2722 THR_Print("*** BEGIN CODE\n");
2723 Disassembler::DisassembleCode(function, true); 2732 Disassembler::DisassembleCode(function, true);
2724 THR_Print("*** END CODE\n");
2725 } 2733 }
2726 return Error::null(); 2734 return Error::null();
2727 } else { 2735 } else {
2728 Thread* const thread = Thread::Current(); 2736 Thread* const thread = Thread::Current();
2729 StackZone stack_zone(thread); 2737 StackZone stack_zone(thread);
2730 Error& error = Error::Handle(); 2738 Error& error = Error::Handle();
2731 // We got an error during compilation. 2739 // We got an error during compilation.
2732 error = thread->sticky_error(); 2740 error = thread->sticky_error();
2733 thread->clear_sticky_error(); 2741 thread->clear_sticky_error();
2734 // Precompilation may encounter compile-time errors. 2742 // Precompilation may encounter compile-time errors.
(...skipping 15 matching lines...) Expand all
2750 CompilationPipeline::New(thread->zone(), function); 2758 CompilationPipeline::New(thread->zone(), function);
2751 2759
2752 ASSERT(FLAG_precompiled_mode); 2760 ASSERT(FLAG_precompiled_mode);
2753 const bool optimized = function.IsOptimizable(); // False for natives. 2761 const bool optimized = function.IsOptimizable(); // False for natives.
2754 return PrecompileFunctionHelper(pipeline, function, optimized); 2762 return PrecompileFunctionHelper(pipeline, function, optimized);
2755 } 2763 }
2756 2764
2757 #endif // DART_PRECOMPILER 2765 #endif // DART_PRECOMPILER
2758 2766
2759 } // namespace dart 2767 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/parser.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698