| Index: runtime/vm/compiler.cc
|
| diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
|
| index a0f01ac3b62f97618d0b08c754ed0fdd5604eb01..5be03d6162e6d5fc406066bf8431e6b7bb97b0d1 100644
|
| --- a/runtime/vm/compiler.cc
|
| +++ b/runtime/vm/compiler.cc
|
| @@ -302,9 +302,7 @@ RawError* Compiler::CompileClass(const Class& cls) {
|
|
|
| Thread* const thread = Thread::Current();
|
| StackZone zone(thread);
|
| - // We remember all the classes that are being compiled in these lists. This
|
| - // also allows us to reset the marked_for_parsing state in case we see an
|
| - // error.
|
| +#ifndef PRODUCT
|
| VMTagScope tagScope(thread, VMTag::kCompileClassTagId);
|
| TimelineDurationScope tds(thread,
|
| thread->isolate()->GetCompilerStream(),
|
| @@ -313,7 +311,11 @@ RawError* Compiler::CompileClass(const Class& cls) {
|
| tds.SetNumArguments(1);
|
| tds.CopyArgument(0, "class", cls.ToCString());
|
| }
|
| +#endif // !PRODUCT
|
|
|
| + // We remember all the classes that are being compiled in these lists. This
|
| + // also allows us to reset the marked_for_parsing state in case we see an
|
| + // error.
|
| GrowableHandlePtrArray<const Class> parse_list(thread->zone(), 4);
|
| GrowableHandlePtrArray<const Class> patch_list(thread->zone(), 4);
|
|
|
| @@ -600,7 +602,9 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| }
|
| bool is_compiled = false;
|
| Zone* const zone = thread()->zone();
|
| +#ifndef PRODUCT
|
| TimelineStream* compiler_timeline = isolate()->GetCompilerStream();
|
| +#endif
|
| CSTAT_TIMER_SCOPE(thread(), codegen_timer);
|
| HANDLESCOPE(thread());
|
|
|
| @@ -660,9 +664,11 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| }
|
| }
|
|
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds(thread(),
|
| compiler_timeline,
|
| "BuildFlowGraph");
|
| +#endif // !PRODUCT
|
| flow_graph = pipeline->BuildFlowGraph(zone,
|
| parsed_function(),
|
| *ic_data_array,
|
| @@ -686,16 +692,20 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| const bool reorder_blocks =
|
| FlowGraph::ShouldReorderBlocks(function, optimized());
|
| if (reorder_blocks) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds(thread(),
|
| compiler_timeline,
|
| "BlockScheduler::AssignEdgeWeights");
|
| +#endif // !PRODUCT
|
| block_scheduler.AssignEdgeWeights();
|
| }
|
|
|
| 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);
|
| @@ -714,9 +724,11 @@ bool CompileParsedFunctionHelper::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);
|
| @@ -746,9 +758,11 @@ bool CompileParsedFunctionHelper::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);
|
| @@ -773,9 +787,11 @@ bool CompileParsedFunctionHelper::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());
|
| @@ -795,9 +811,11 @@ bool CompileParsedFunctionHelper::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());
|
|
|
| @@ -806,9 +824,11 @@ bool CompileParsedFunctionHelper::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.
|
| @@ -835,9 +855,11 @@ bool CompileParsedFunctionHelper::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();
|
| @@ -850,9 +872,11 @@ bool CompileParsedFunctionHelper::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();
|
| @@ -890,16 +914,20 @@ bool CompileParsedFunctionHelper::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);
|
| @@ -913,9 +941,11 @@ bool CompileParsedFunctionHelper::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.
|
| @@ -929,9 +959,11 @@ bool CompileParsedFunctionHelper::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);
|
| }
|
| @@ -942,9 +974,11 @@ bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
|
| optimizer.EliminateEnvironments();
|
|
|
| {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds2(thread(),
|
| compiler_timeline,
|
| "EliminateDeadPhis");
|
| +#endif // !PRODUCT
|
| DeadCodeElimination::EliminateDeadPhis(flow_graph);
|
| DEBUG_ASSERT(flow_graph->VerifyUseLists());
|
| }
|
| @@ -958,9 +992,11 @@ bool CompileParsedFunctionHelper::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();
|
| @@ -974,9 +1010,11 @@ bool CompileParsedFunctionHelper::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();
|
| @@ -993,10 +1031,12 @@ bool CompileParsedFunctionHelper::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
|
| @@ -1009,18 +1049,22 @@ bool CompileParsedFunctionHelper::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();
|
| }
|
|
|
| if (reorder_blocks) {
|
| +#ifndef PRODUCT
|
| TimelineDurationScope tds(thread(),
|
| compiler_timeline,
|
| "BlockScheduler::ReorderBlocks");
|
| +#endif // !PRODUCT
|
| block_scheduler.ReorderBlocks();
|
| }
|
|
|
| @@ -1037,16 +1081,20 @@ bool CompileParsedFunctionHelper::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
|
| if (thread()->IsMutatorThread()) {
|
| FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
|
| } else {
|
| @@ -1639,7 +1687,9 @@ RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
|
| Thread* const thread = Thread::Current();
|
| if (FLAG_trace_compiler) {
|
| THR_Print("compiling expression: ");
|
| - AstPrinter::PrintNode(fragment);
|
| + if (FLAG_support_ast_printer) {
|
| + AstPrinter::PrintNode(fragment);
|
| + }
|
| }
|
|
|
| // Create a dummy function object for the code generator.
|
|
|