Lazily compute the synthetic marker hash.

This CL attempts to remove the regression in b/227625392. Local
reproduction is not stable yet the only real change in the range
is the hash computation itself.

This also adds a version flag to run_benchmark.py

Bug: b/227625392
Change-Id: I99be7cb15e4a44ea2eb1c84079d28c94448f4ec3
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index 4354f06..bb94a8e 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -130,9 +130,7 @@
     }
     reader.accept(
         new CreateDexClassVisitor<>(origin, classKind, reader.b, application, classConsumer),
-        new Attribute[] {
-          SyntheticMarker.getMarkerAttributePrototype(application.getFactory().getSyntheticNaming())
-        },
+        getAttributePrototypes(),
         parsingOptions);
 
     // Read marker.
@@ -152,6 +150,15 @@
     }
   }
 
+  private Attribute[] getAttributePrototypes() {
+    if (classKind == ClassKind.PROGRAM) {
+      return new Attribute[] {
+        SyntheticMarker.getMarkerAttributePrototype(application.getFactory().getSyntheticNaming())
+      };
+    }
+    return new Attribute[0];
+  }
+
   private static int cleanAccessFlags(int access) {
     // Clear the "synthetic attribute" and "deprecated" attribute-flags if present.
     return access & ~ACC_SYNTHETIC_ATTRIBUTE & ~ACC_DEPRECATED;
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index 3559fe3..05ce2e9 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -84,18 +84,28 @@
   public final SyntheticKind ARRAY_CONVERSION = generator.forSingleMethod("$ArrayConversion");
   public final SyntheticKind API_MODEL_OUTLINE = generator.forSingleMethod("ApiModelOutline");
 
-  private final String versionHash;
   private final List<SyntheticKind> ALL_KINDS;
+  private String lazyVersionHash = null;
 
   public SyntheticNaming() {
-    generator.hasher.putString(Version.getVersionString(), StandardCharsets.UTF_8);
-    versionHash = generator.hasher.hash().toString();
     ALL_KINDS = generator.getAllKinds();
     generator = null;
   }
 
   public String getVersionHash() {
-    return versionHash;
+    if (lazyVersionHash == null) {
+      computeVersionHash();
+    }
+    return lazyVersionHash;
+  }
+
+  private void computeVersionHash() {
+    Hasher hasher = Hashing.sha256().newHasher();
+    hasher.putString(Version.getVersionString(), StandardCharsets.UTF_8);
+    for (SyntheticKind kind : ALL_KINDS) {
+      kind.hash(hasher);
+    }
+    lazyVersionHash = hasher.hash().toString();
   }
 
   public Collection<SyntheticKind> kinds() {
@@ -112,10 +122,8 @@
   private static class KindGenerator {
     private int nextId = 1;
     private List<SyntheticKind> kinds = new ArrayList<>();
-    private Hasher hasher = Hashing.sha256().newHasher();
 
     private SyntheticKind register(SyntheticKind kind) {
-      kind.hash(hasher);
       kinds.add(kind);
       if (kinds.size() != kind.getId()) {
         throw new Unreachable("Invalid synthetic kind id: " + kind.getId());
diff --git a/tools/compiledump.py b/tools/compiledump.py
index a7809ac..9f3d1b0 100755
--- a/tools/compiledump.py
+++ b/tools/compiledump.py
@@ -287,12 +287,12 @@
         args.append('-D' + name + '=' + value)
   return args
 
-def download_distribution(args, version, temp):
+def download_distribution(version, nolib, temp):
   if version == 'main':
-    return utils.R8_JAR if args.nolib else utils.R8LIB_JAR
+    return utils.R8_JAR if nolib else utils.R8LIB_JAR
   if version == 'source':
     return '%s:%s' % (utils.BUILD_JAVA_MAIN_DIR, utils.ALL_DEPS_JAR)
-  name = 'r8.jar' if args.nolib else 'r8lib.jar'
+  name = 'r8.jar' if nolib else 'r8lib.jar'
   source = archive.GetUploadDestination(version, name, is_hash(version))
   dest = os.path.join(temp, 'r8.jar')
   utils.download_file_from_cloud_storage(source, dest)
@@ -367,7 +367,7 @@
     out = determine_output(args, temp)
     min_api = determine_min_api(args, build_properties)
     classfile = determine_class_file(args, build_properties)
-    jar = args.r8_jar if args.r8_jar else download_distribution(args, version, temp)
+    jar = args.r8_jar if args.r8_jar else download_distribution(version, args.nolib, temp)
     if ':' not in jar and not os.path.exists(jar):
       error("Distribution does not exist: " + jar)
     wrapper_dir = prepare_wrapper(jar, temp, jdkhome)
diff --git a/tools/run_benchmark.py b/tools/run_benchmark.py
index 545ac5a..904b509 100755
--- a/tools/run_benchmark.py
+++ b/tools/run_benchmark.py
@@ -11,6 +11,7 @@
 import gradle
 import jdk
 import utils
+import compiledump
 
 NONLIB_BUILD_TARGET = 'R8WithRelocatedDeps'
 NONLIB_TEST_BUILD_TARGETS = [utils.R8_TESTS_TARGET, utils.R8_TESTS_DEPS_TARGET]
@@ -59,14 +60,20 @@
                       help='Print timing information from r8',
                       default=False,
                       action='store_true')
+  result.add_argument('--version', '-v',
+                      help='Use R8 version/hash for the run (default local build)',
+                      default=None)
   result.add_argument('--temp',
                       help='A directory to use for temporaries and outputs.',
                       default=None)
   return result.parse_known_args(argv)
 
-def main(argv):
+def main(argv, temp):
   (options, args) = parse_options(argv)
 
+  if options.temp:
+    temp = options.temp
+
   if options.golem:
     options.no_build = True
     if options.nolib:
@@ -74,14 +81,21 @@
       return 1
 
   if options.nolib:
+    testBuildTargets = NONLIB_TEST_BUILD_TARGETS
     buildTargets = [NONLIB_BUILD_TARGET] + NONLIB_TEST_BUILD_TARGETS
     r8jar = utils.R8_WITH_RELOCATED_DEPS_JAR
     testjars = [utils.R8_TESTS_DEPS_JAR, utils.R8_TESTS_JAR]
   else:
+    testBuildTargets = R8LIB_TEST_BUILD_TARGETS
     buildTargets = GOLEM_BUILD_TARGETS
     r8jar = utils.R8LIB_JAR
     testjars = [utils.R8LIB_TESTS_DEPS_JAR, utils.R8LIB_TESTS_JAR]
 
+  if options.version:
+    # r8 is downloaded so only test jar needs to be built.
+    buildTargets = testBuildTargets
+    r8jar = compiledump.download_distribution(options.version, options.nolib, temp)
+
   if not options.no_build:
     gradle.RunGradle(buildTargets + ['-Pno_internal'])
 
@@ -104,4 +118,5 @@
   return subprocess.check_call(cmd)
 
 if __name__ == '__main__':
-  sys.exit(main(sys.argv[1:]))
+  with utils.TempDir() as temp:
+    sys.exit(main(sys.argv[1:], temp))