Support for startup instrumentating using Log.i

Change-Id: I9a2728211ab283a4853386afab9eff8ab55f13b0
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/StartupInstrumentation.java b/src/main/java/com/android/tools/r8/experimental/startup/StartupInstrumentation.java
index cb5389d..8995dbc 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/StartupInstrumentation.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/StartupInstrumentation.java
@@ -10,6 +10,8 @@
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.cf.code.CfReturnVoid;
+import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
 import com.android.tools.r8.cf.code.CfStaticFieldRead;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.CfCode;
@@ -31,10 +33,12 @@
 
   private final AppView<?> appView;
   private final DexItemFactory dexItemFactory;
+  private final StartupOptions options;
 
   public StartupInstrumentation(AppView<?> appView) {
     this.appView = appView;
     this.dexItemFactory = appView.dexItemFactory();
+    this.options = appView.options().getStartupOptions();
   }
 
   public void instrumentClasses(ExecutorService executorService) throws ExecutionException {
@@ -87,14 +91,25 @@
     }
 
     CfCode cfCode = code.asCfCode();
-    List<CfInstruction> instructions = new ArrayList<>(3 + cfCode.getInstructions().size());
-    instructions.add(new CfStaticFieldRead(dexItemFactory.javaLangSystemMembers.out));
-    instructions.add(new CfConstString(classInitializer.getHolderType().getDescriptor()));
-    instructions.add(
-        new CfInvoke(
-            Opcodes.INVOKEVIRTUAL,
-            dexItemFactory.javaIoPrintStreamMembers.printlnWithString,
-            false));
+    List<CfInstruction> instructions;
+    if (options.hasStartupInstrumentationTag()) {
+      instructions = new ArrayList<>(4 + cfCode.getInstructions().size());
+      instructions.add(
+          new CfConstString(dexItemFactory.createString(options.getStartupInstrumentationTag())));
+      instructions.add(new CfConstString(classInitializer.getHolderType().getDescriptor()));
+      instructions.add(
+          new CfInvoke(Opcodes.INVOKESTATIC, dexItemFactory.androidUtilLogMembers.i, false));
+      instructions.add(new CfStackInstruction(Opcode.Pop));
+    } else {
+      instructions = new ArrayList<>(3 + cfCode.getInstructions().size());
+      instructions.add(new CfStaticFieldRead(dexItemFactory.javaLangSystemMembers.out));
+      instructions.add(new CfConstString(classInitializer.getHolderType().getDescriptor()));
+      instructions.add(
+          new CfInvoke(
+              Opcodes.INVOKEVIRTUAL,
+              dexItemFactory.javaIoPrintStreamMembers.printlnWithString,
+              false));
+    }
     instructions.addAll(cfCode.getInstructions());
     classInitializer.setCode(
         new CfCode(
diff --git a/src/main/java/com/android/tools/r8/experimental/startup/StartupOptions.java b/src/main/java/com/android/tools/r8/experimental/startup/StartupOptions.java
index 0ebce64..7fad730 100644
--- a/src/main/java/com/android/tools/r8/experimental/startup/StartupOptions.java
+++ b/src/main/java/com/android/tools/r8/experimental/startup/StartupOptions.java
@@ -4,6 +4,7 @@
 
 package com.android.tools.r8.experimental.startup;
 
+import static com.android.tools.r8.utils.InternalOptions.getSystemPropertyForDevelopmentOrDefault;
 import static com.android.tools.r8.utils.InternalOptions.isSystemPropertyForDevelopmentSet;
 
 public class StartupOptions {
@@ -14,9 +15,20 @@
       isSystemPropertyForDevelopmentSet("com.android.tools.r8.startup.completenesscheck");
   private boolean enableStartupInstrumentation =
       isSystemPropertyForDevelopmentSet("com.android.tools.r8.startup.instrument");
+  private String startupInstrumentationTag =
+      getSystemPropertyForDevelopmentOrDefault(
+          "com.android.tools.r8.startup.instrumentationtag", null);
 
   private StartupConfiguration startupConfiguration;
 
+  public boolean hasStartupInstrumentationTag() {
+    return startupInstrumentationTag != null;
+  }
+
+  public String getStartupInstrumentationTag() {
+    return startupInstrumentationTag;
+  }
+
   public boolean isMinimalStartupDexEnabled() {
     return enableMinimalStartupDex;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 1d5a3a0..7c0e5d2 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -547,6 +547,7 @@
   public final ClassMethods classMethods = new ClassMethods();
   public final ConstructorMethods constructorMethods = new ConstructorMethods();
   public final EnumMembers enumMembers = new EnumMembers();
+  public final AndroidUtilLogMembers androidUtilLogMembers = new AndroidUtilLogMembers();
   public final JavaLangReflectArrayMembers javaLangReflectArrayMembers =
       new JavaLangReflectArrayMembers();
   public final JavaLangAnnotationRetentionPolicyMembers javaLangAnnotationRetentionPolicyMembers =
@@ -1703,6 +1704,14 @@
     }
   }
 
+  public class AndroidUtilLogMembers {
+
+    public final DexMethod i =
+        createMethod(androidUtilLogType, createProto(intType, stringType, stringType), "i");
+
+    private AndroidUtilLogMembers() {}
+  }
+
   public class JavaLangAnnotationRetentionPolicyMembers {
 
     public final DexField CLASS =
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 3839809..8942e41 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -873,6 +873,17 @@
     return false;
   }
 
+  public static String getSystemPropertyForDevelopmentOrDefault(
+      String propertyName, String defaultValue) {
+    if (Version.isDevelopmentVersion()) {
+      String propertyValue = System.getProperty(propertyName);
+      if (propertyValue != null) {
+        return propertyValue;
+      }
+    }
+    return defaultValue;
+  }
+
   private static int parseSystemPropertyForDevelopmentOrDefault(
       String propertyName, int defaultValue) {
     if (Version.isDevelopmentVersion()) {