Merge "Timing for collision detection in class merger"
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index a34f1b9..6f935ee 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1154,7 +1154,7 @@
     }
   }
 
-  private static class CollisionDetector {
+  private class CollisionDetector {
 
     private static final int NOT_FOUND = 1 << (Integer.SIZE - 1);
 
@@ -1179,27 +1179,30 @@
     }
 
     boolean mayCollide() {
+      timing.begin("collision detection");
       fillSeenPositions(invokes);
+      boolean result = false;
       // If the type is not used in methods at all, there cannot be any conflict.
-      if (seenPositions.isEmpty()) {
-        return false;
-      }
-      for (DexMethod method : invokes) {
-        Int2IntMap positionsMap = seenPositions.get(method.name);
-        if (positionsMap != null) {
-          int arity = method.getArity();
-          int previous = positionsMap.get(arity);
-          if (previous != NOT_FOUND) {
-            assert previous != 0;
-            int positions = computePositionsFor(method.proto, source, sourceProtoCache,
-                substituions);
-            if ((positions & previous) != 0) {
-              return true;
+      if (!seenPositions.isEmpty()) {
+        for (DexMethod method : invokes) {
+          Int2IntMap positionsMap = seenPositions.get(method.name);
+          if (positionsMap != null) {
+            int arity = method.getArity();
+            int previous = positionsMap.get(arity);
+            if (previous != NOT_FOUND) {
+              assert previous != 0;
+              int positions =
+                  computePositionsFor(method.proto, source, sourceProtoCache, substituions);
+              if ((positions & previous) != 0) {
+                result = true;
+                break;
+              }
             }
           }
         }
       }
-      return false;
+      timing.end();
+      return result;
     }
 
     private void fillSeenPositions(Collection<DexMethod> invokes) {
diff --git a/src/main/java/com/android/tools/r8/utils/Timing.java b/src/main/java/com/android/tools/r8/utils/Timing.java
index ff2aa68..e8cf59b 100644
--- a/src/main/java/com/android/tools/r8/utils/Timing.java
+++ b/src/main/java/com/android/tools/r8/utils/Timing.java
@@ -13,6 +13,8 @@
 // Finally a report is printed by:
 //     t.report();
 
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Stack;
 
 public class Timing {
@@ -27,23 +29,28 @@
   static class Node {
     final String title;
 
-    final Stack<Node> sons = new Stack<>();
-    final long start_time;
-    long stop_time;
+    final Map<String, Node> children = new LinkedHashMap<>();
+    long duration = 0;
+    long start_time;
 
     Node(String title) {
       this.title = title;
       this.start_time = System.nanoTime();
-      this.stop_time = -1;
+    }
+
+    void restart() {
+      assert start_time == -1;
+      start_time = System.nanoTime();
     }
 
     void end() {
-      stop_time = System.nanoTime();
+      duration += System.nanoTime() - start_time;
+      start_time = -1;
       assert duration() >= 0;
     }
 
     long duration() {
-      return stop_time - start_time;
+      return duration;
     }
 
     @Override
@@ -66,15 +73,22 @@
         System.out.print("- ");
       }
       System.out.println(toString(top));
-      sons.forEach(p -> { p.report(depth + 1, top); });
+      children.values().forEach(p -> p.report(depth + 1, top));
     }
   }
 
 
   public void begin(String title) {
-    Node n = new Node(title);
-    stack.peek().sons.add(n);
-    stack.push(n);
+    Node parent = stack.peek();
+    Node child;
+    if (parent.children.containsKey(title)) {
+      child = parent.children.get(title);
+      child.restart();
+    } else {
+      child = new Node(title);
+      parent.children.put(title, child);
+    }
+    stack.push(child);
   }
 
   public void end() {