[dart2js] Add tracing for codegen phases

Change-Id: Iace4d6037e7071d7642e510f0616c869cf30946b
Reviewed-on: https://dart-review.googlesource.com/c/93928
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 1252521..ebf05c2 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -31,6 +31,7 @@
 import '../native/behavior.dart';
 import '../native/enqueue.dart';
 import '../options.dart';
+import '../tracer.dart';
 import '../universe/call_structure.dart' show CallStructure;
 import '../universe/selector.dart' show Selector;
 import '../universe/use.dart'
@@ -40,6 +41,11 @@
 import 'nodes.dart';
 import 'variable_allocator.dart';
 
+abstract class CodegenPhase {
+  String get name => '$runtimeType';
+  void visitGraph(HGraph graph);
+}
+
 class SsaCodeGeneratorTask extends CompilerTask {
   final JavaScriptBackend backend;
   final SourceInformationStrategy sourceInformationFactory;
@@ -89,6 +95,7 @@
           .createBuilderForContext(work.element)
           .buildDeclaration(work.element);
       SsaCodeGenerator codegen = new SsaCodeGenerator(
+          this,
           backend.compiler.options,
           backend.emitter,
           backend.nativeCodegenEnqueuer,
@@ -98,6 +105,7 @@
           backend.rtiEncoder,
           backend.namer,
           backend.superMemberData,
+          backend.tracer,
           closedWorld,
           work);
       codegen.visitGraph(graph);
@@ -114,6 +122,7 @@
         work.registry.registerAsyncMarker(element.asyncMarker);
       }
       SsaCodeGenerator codegen = new SsaCodeGenerator(
+          this,
           backend.compiler.options,
           backend.emitter,
           backend.nativeCodegenEnqueuer,
@@ -123,6 +132,7 @@
           backend.rtiEncoder,
           backend.namer,
           backend.superMemberData,
+          backend.tracer,
           closedWorld,
           work);
       codegen.visitGraph(graph);
@@ -152,6 +162,7 @@
   /// This includes declarations, which are generated as expressions.
   bool isGeneratingExpression = false;
 
+  final CompilerTask _codegenTask;
   final CompilerOptions _options;
   final CodeEmitterTask _emitter;
   final NativeCodegenEnqueuer _nativeEnqueuer;
@@ -161,6 +172,7 @@
   final RuntimeTypesEncoder _rtiEncoder;
   final Namer _namer;
   final SuperMemberData _superMemberData;
+  final Tracer _tracer;
   final JClosedWorld _closedWorld;
   final CodegenWorkItem _work;
 
@@ -207,6 +219,7 @@
   Queue<HBasicBlock> blockQueue;
 
   SsaCodeGenerator(
+      this._codegenTask,
       this._options,
       this._emitter,
       this._nativeEnqueuer,
@@ -216,6 +229,7 @@
       this._rtiEncoder,
       this._namer,
       this._superMemberData,
+      this._tracer,
       this._closedWorld,
       this._work,
       {SourceInformation sourceInformation})
@@ -352,27 +366,34 @@
   }
 
   void preGenerateMethod(HGraph graph) {
-    new SsaInstructionSelection(_options, _closedWorld, _interceptorData)
-        .visitGraph(graph);
-    new SsaTypeKnownRemover().visitGraph(graph);
-    new SsaTrustedCheckRemover(_options).visitGraph(graph);
+    void runPhase(CodegenPhase phase, {bool traceGraph = true}) {
+      _codegenTask.measureSubtask(phase.name, () => phase.visitGraph(graph));
+      if (traceGraph) {
+        _tracer.traceGraph(phase.name, graph);
+      }
+      assert(graph.isValid(), 'Graph not valid after ${phase.name}');
+    }
+
+    runPhase(
+        new SsaInstructionSelection(_options, _closedWorld, _interceptorData));
+    runPhase(new SsaTypeKnownRemover());
+    runPhase(new SsaTrustedCheckRemover(_options));
     // TODO(sra): Re-enable chaining.
-    //     new SsaAssignmentChaining(_options, _closedWorld).visitGraph(graph);
-    new SsaInstructionMerger(
-            _abstractValueDomain, generateAtUseSite, _superMemberData)
-        .visitGraph(graph);
-    new SsaConditionMerger(generateAtUseSite, controlFlowOperators)
-        .visitGraph(graph);
-    new SsaShareRegionConstants(_options).visitGraph(graph);
+    // runPhase(new SsaAssignmentChaining(_options, _closedWorld));
+    runPhase(new SsaInstructionMerger(
+        _abstractValueDomain, generateAtUseSite, _superMemberData));
+    runPhase(new SsaConditionMerger(generateAtUseSite, controlFlowOperators));
+    runPhase(new SsaShareRegionConstants(_options));
+
     SsaLiveIntervalBuilder intervalBuilder =
         new SsaLiveIntervalBuilder(generateAtUseSite, controlFlowOperators);
-    intervalBuilder.visitGraph(graph);
+    runPhase(intervalBuilder, traceGraph: false);
     SsaVariableAllocator allocator = new SsaVariableAllocator(
         _namer,
         intervalBuilder.liveInstructions,
         intervalBuilder.liveIntervals,
         generateAtUseSite);
-    allocator.visitGraph(graph);
+    runPhase(allocator, traceGraph: false);
     variableNames = allocator.names;
     shouldGroupVarDeclarations = allocator.names.numberOfVariables > 1;
   }
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index ab2684b..082f46a 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -10,11 +10,12 @@
 import '../options.dart';
 import '../universe/selector.dart' show Selector;
 import '../world.dart' show JClosedWorld;
+import 'codegen.dart' show CodegenPhase;
 import 'nodes.dart';
 
 /// Replaces some instructions with specialized versions to make codegen easier.
 /// Caches codegen information on nodes.
-class SsaInstructionSelection extends HBaseVisitor {
+class SsaInstructionSelection extends HBaseVisitor with CodegenPhase {
   final JClosedWorld _closedWorld;
   final InterceptorData _interceptorData;
   final CompilerOptions _options;
@@ -341,7 +342,7 @@
 
 /// Remove [HTypeKnown] instructions from the graph, to make codegen
 /// analysis easier.
-class SsaTypeKnownRemover extends HBaseVisitor {
+class SsaTypeKnownRemover extends HBaseVisitor with CodegenPhase {
   void visitGraph(HGraph graph) {
     visitDominatorTree(graph);
   }
@@ -368,7 +369,7 @@
 
 /// Remove [HTypeConversion] instructions from the graph in '--trust-primitives'
 /// mode.
-class SsaTrustedCheckRemover extends HBaseVisitor {
+class SsaTrustedCheckRemover extends HBaseVisitor with CodegenPhase {
   final CompilerOptions _options;
 
   SsaTrustedCheckRemover(this._options);
@@ -402,7 +403,7 @@
 ///     b.y = v;
 /// -->
 ///     b.y = a.x = v;
-class SsaAssignmentChaining extends HBaseVisitor {
+class SsaAssignmentChaining extends HBaseVisitor with CodegenPhase {
   final JClosedWorld _closedWorld;
   final CompilerOptions _options;
   //HGraph graph;
@@ -566,7 +567,7 @@
 ///   t2 = add(t0, t1);
 /// t0 and t1 would be marked and the resulting code would then be:
 ///   t2 = add(4, 3);
-class SsaInstructionMerger extends HBaseVisitor {
+class SsaInstructionMerger extends HBaseVisitor with CodegenPhase {
   final AbstractValueDomain _abstractValueDomain;
   final SuperMemberData _superMemberData;
 
@@ -866,7 +867,7 @@
 ///  Detect control flow arising from short-circuit logical and
 ///  conditional operators, and prepare the program to be generated
 ///  using these operators instead of nested ifs and boolean variables.
-class SsaConditionMerger extends HGraphVisitor {
+class SsaConditionMerger extends HGraphVisitor with CodegenPhase {
   Set<HInstruction> generateAtUseSite;
   Set<HInstruction> controlFlowOperators;
 
@@ -1040,7 +1041,7 @@
 /// Insert 'caches' for whole-function region-constants when the local minified
 /// name would be shorter than repeated references.  These are caches for 'this'
 /// and constant values.
-class SsaShareRegionConstants extends HBaseVisitor {
+class SsaShareRegionConstants extends HBaseVisitor with CodegenPhase {
   final CompilerOptions _options;
 
   SsaShareRegionConstants(this._options);
diff --git a/pkg/compiler/lib/src/ssa/variable_allocator.dart b/pkg/compiler/lib/src/ssa/variable_allocator.dart
index 6837537..aca7c88 100644
--- a/pkg/compiler/lib/src/ssa/variable_allocator.dart
+++ b/pkg/compiler/lib/src/ssa/variable_allocator.dart
@@ -4,6 +4,7 @@
 
 import '../common.dart';
 import '../js_backend/js_backend.dart';
+import 'codegen.dart' show CodegenPhase;
 import 'nodes.dart';
 
 /// The [LiveRange] class covers a range where an instruction is live.
@@ -153,7 +154,7 @@
 /// Builds the live intervals of each instruction. The algorithm visits
 /// the graph post-dominator tree to find the last uses of an
 /// instruction, and computes the liveIns of each basic block.
-class SsaLiveIntervalBuilder extends HBaseVisitor {
+class SsaLiveIntervalBuilder extends HBaseVisitor with CodegenPhase {
   final Set<HInstruction> generateAtUseSite;
   final Set<HInstruction> controlFlowOperators;
 
@@ -561,7 +562,7 @@
 /// instruction, it frees the names of the inputs that die at that
 /// instruction, and allocates a name to the instruction. For each phi,
 /// it adds a copy to the CopyHandler of the corresponding predecessor.
-class SsaVariableAllocator extends HBaseVisitor {
+class SsaVariableAllocator extends HBaseVisitor with CodegenPhase {
   final Namer _namer;
   final Map<HBasicBlock, LiveEnvironment> liveInstructions;
   final Map<HInstruction, LiveInterval> liveIntervals;