| Index: runtime/vm/precompiler.cc
|
| diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
|
| index ebaa9e2b2b2667080ac463bf48b971924c61e986..30fb89034e694df1a7ef7779a18b65e6757b3544 100644
|
| --- a/runtime/vm/precompiler.cc
|
| +++ b/runtime/vm/precompiler.cc
|
| @@ -59,8 +59,6 @@ DEFINE_FLAG(int, max_speculative_inlining_attempts, 1,
|
| DECLARE_FLAG(bool, allocation_sinking);
|
| DECLARE_FLAG(bool, common_subexpression_elimination);
|
| DECLARE_FLAG(bool, constant_propagation);
|
| -DECLARE_FLAG(bool, disassemble);
|
| -DECLARE_FLAG(bool, disassemble_optimized);
|
| DECLARE_FLAG(bool, loop_invariant_code_motion);
|
| DECLARE_FLAG(bool, print_flow_graph);
|
| DECLARE_FLAG(bool, print_flow_graph_optimized);
|
| @@ -744,7 +742,7 @@ RawObject* Precompiler::ExecuteOnce(SequenceNode* fragment) {
|
| LongJumpScope jump;
|
| if (setjmp(*jump.Set()) == 0) {
|
| Thread* const thread = Thread::Current();
|
| - if (FLAG_trace_compiler) {
|
| + if (FLAG_support_ast_printer && FLAG_trace_compiler) {
|
| THR_Print("compiling expression: ");
|
| AstPrinter::PrintNode(fragment);
|
| }
|
| @@ -1627,7 +1625,9 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| }
|
| bool is_compiled = false;
|
| Zone* const zone = thread()->zone();
|
| +#ifndef PRODUCT
|
| TimelineStream* compiler_timeline = isolate()->GetCompilerStream();
|
| +#endif // !PRODUCT
|
| CSTAT_TIMER_SCOPE(thread(), codegen_timer);
|
| HANDLESCOPE(thread());
|
|
|
| @@ -1662,9 +1662,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| CSTAT_TIMER_SCOPE(thread(), graphbuilder_timer);
|
| ZoneGrowableArray<const ICData*>* ic_data_array =
|
| new(zone) ZoneGrowableArray<const ICData*>();
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds(thread(),
|
| compiler_timeline,
|
| "BuildFlowGraph");
|
| +#endif // !PRODUCT
|
| flow_graph = pipeline->BuildFlowGraph(zone,
|
| parsed_function(),
|
| *ic_data_array,
|
| @@ -1681,9 +1683,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| }
|
|
|
| if (optimized()) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds(thread(),
|
| compiler_timeline,
|
| "ComputeSSA");
|
| +#endif // !PRODUCT
|
| CSTAT_TIMER_SCOPE(thread(), ssa_timer);
|
| // Transform to SSA (virtual register 0 and no inlining arguments).
|
| flow_graph->ComputeSSA(0, NULL);
|
| @@ -1702,9 +1706,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| // have non-generic type feedback attached to them that can
|
| // potentially affect optimizations.
|
| if (optimized()) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds(thread(),
|
| compiler_timeline,
|
| "OptimizationPasses");
|
| +#endif // !PRODUCT
|
| inline_id_to_function.Add(&function);
|
| // Top scope function has no caller (-1).
|
| caller_inline_id.Add(-1);
|
| @@ -1733,9 +1739,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
|
|
| // Inlining (mutates the flow graph)
|
| if (FLAG_use_inlining) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "Inlining");
|
| +#endif // !PRODUCT
|
| CSTAT_TIMER_SCOPE(thread(), graphinliner_timer);
|
| // Propagate types to create more inlining opportunities.
|
| FlowGraphTypePropagator::Propagate(flow_graph);
|
| @@ -1760,9 +1768,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "ApplyClassIds");
|
| +#endif // !PRODUCT
|
| // Use propagated class-ids to optimize further.
|
| optimizer.ApplyClassIds();
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
| @@ -1782,9 +1792,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "BranchSimplifier");
|
| +#endif // !PRODUCT
|
| BranchSimplifier::Simplify(flow_graph);
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
|
|
| @@ -1793,9 +1805,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| }
|
|
|
| if (FLAG_constant_propagation) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "ConstantPropagation");
|
| +#endif // !PRODUCT
|
| ConstantPropagator::Optimize(flow_graph);
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
| // A canonicalization pass to remove e.g. smi checks on smi constants.
|
| @@ -1822,9 +1836,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "SelectRepresentations");
|
| +#endif // !PRODUCT
|
| // Where beneficial convert Smi operations into Int32 operations.
|
| // Only meanigful for 32bit platforms right now.
|
| optimizer.WidenSmiToInt32();
|
| @@ -1837,9 +1853,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| }
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "CommonSubexpressionElinination");
|
| +#endif // !PRODUCT
|
| if (FLAG_common_subexpression_elimination ||
|
| FLAG_loop_invariant_code_motion) {
|
| flow_graph->ComputeBlockEffects();
|
| @@ -1877,16 +1895,20 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "DeadStoreElimination");
|
| +#endif // !PRODUCT
|
| DeadStoreElimination::Optimize(flow_graph);
|
| }
|
|
|
| if (FLAG_range_analysis) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "RangeAnalysis");
|
| +#endif // !PRODUCT
|
| // Propagate types after store-load-forwarding. Some phis may have
|
| // become smi phis that can be processed by range analysis.
|
| FlowGraphTypePropagator::Propagate(flow_graph);
|
| @@ -1900,9 +1922,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| }
|
|
|
| if (FLAG_constant_propagation) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "ConstantPropagator::OptimizeBranches");
|
| +#endif // !PRODUCT
|
| // Constant propagation can use information from range analysis to
|
| // find unreachable branch targets and eliminate branches that have
|
| // the same true- and false-target.
|
| @@ -1916,9 +1940,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "TryCatchAnalyzer::Optimize");
|
| +#endif // !PRODUCT
|
| // Optimize try-blocks.
|
| TryCatchAnalyzer::Optimize(flow_graph);
|
| }
|
| @@ -1929,9 +1955,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| optimizer.EliminateEnvironments();
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "EliminateDeadPhis");
|
| +#endif // !PRODUCT
|
| DeadCodeElimination::EliminateDeadPhis(flow_graph);
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
| }
|
| @@ -1945,9 +1973,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| AllocationSinking* sinking = NULL;
|
| if (FLAG_allocation_sinking &&
|
| (flow_graph->graph_entry()->SuccessorCount() == 1)) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "AllocationSinking::Optimize");
|
| +#endif // !PRODUCT
|
| // TODO(fschneider): Support allocation sinking with try-catch.
|
| sinking = new AllocationSinking(flow_graph);
|
| sinking->Optimize();
|
| @@ -1961,9 +1991,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "SelectRepresentations");
|
| +#endif // !PRODUCT
|
| // Ensure that all phis inserted by optimization passes have
|
| // consistent representations.
|
| optimizer.SelectRepresentations();
|
| @@ -1980,10 +2012,12 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
|
|
| if (sinking != NULL) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(
|
| thread(),
|
| compiler_timeline,
|
| "AllocationSinking::DetachMaterializations");
|
| +#endif // !PRODUCT
|
| // Remove all MaterializeObject instructions inserted by allocation
|
| // sinking from the flow graph and let them float on the side
|
| // referenced only from environments. Register allocator will consider
|
| @@ -1996,9 +2030,11 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| FlowGraphInliner::CollectGraphInfo(flow_graph, true);
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "AllocateRegisters");
|
| +#endif // !PRODUCT
|
| // Perform register allocation on the SSA graph.
|
| FlowGraphAllocator allocator(*flow_graph);
|
| allocator.AllocateRegisters();
|
| @@ -2017,16 +2053,20 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| caller_inline_id);
|
| {
|
| CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer);
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds(thread(),
|
| compiler_timeline,
|
| "CompileGraph");
|
| +#endif // !PRODUCT
|
| graph_compiler.CompileGraph();
|
| pipeline->FinalizeCompilation();
|
| }
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds(thread(),
|
| compiler_timeline,
|
| "FinalizeCompilation");
|
| +#endif // !PRODUCT
|
| ASSERT(thread()->IsMutatorThread());
|
| FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
|
| }
|
|
|