| 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 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |