Version 3.0.41-sc05

Includes minimal patches to archive and run tests with Python 3.

Test: tools/gradle.py downloadDeps
Test: tools/archive.py --dry-run --dry-run-output /tmp/ooo
Test: tools/test.py 'com.android.tools.r8.naming.methodparameters.*'

Uploaded with `git cl upload --bypass-hooks` as the Java formatter
script on this branch required Python 2.7.

Bug: b/281536562
Change-Id: Icae367ffb8f223aa852a32e59f42e121d7a63d31
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index faa8808..fb290e7 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -91,6 +91,7 @@
 def CheckChange(input_api, output_api):
   branch = (
       check_output(['git', 'cl', 'upstream'])
+          .decode('utf-8')
           .strip()
           .replace('refs/heads/', ''))
   results = []
diff --git a/build.gradle b/build.gradle
index 6a56724..3c8efb3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1009,7 +1009,7 @@
     inputs.file script
     outputs.dir outputDir
     dependsOn downloadDeps
-    commandLine "python", script
+    commandLine "python3", script
     workingDir = projectDir
 }
 
@@ -1122,7 +1122,7 @@
     inputs.files files("tests/2017-10-04/art.tar.gz", createArtTestsScript)
     outputs.dir outputDir
     dependsOn downloadDeps
-    commandLine "python", createArtTestsScript
+    commandLine "python3", createArtTestsScript
     workingDir = projectDir
 }
 
@@ -1132,7 +1132,7 @@
     inputs.file script
     outputs.dir outputDir
     dependsOn downloadDeps
-    commandLine "python", script
+    commandLine "python3", script
     workingDir = projectDir
 }
 
@@ -1863,7 +1863,7 @@
 def retrace(Throwable exception) {
     def out = new StringBuffer()
     def err = new StringBuffer()
-    def command = "python tools/retrace.py --quiet"
+    def command = "python3 tools/retrace.py --quiet"
     def header = "RETRACED STACKTRACE";
     if (System.getenv('BUILDBOT_BUILDERNAME') != null
             && !System.getenv('BUILDBOT_BUILDERNAME').endsWith("_release")) {
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 0119c0c..f48ca54 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "3.0.41-sc04";
+  public static final String LABEL = "3.0.41-sc05";
 
   private Version() {
   }
diff --git a/src/test/java/com/android/tools/r8/naming/methodparameters/MethodParametersNullValueTest.java b/src/test/java/com/android/tools/r8/naming/methodparameters/MethodParametersNullValueTest.java
index e6a1197..a5674e7 100644
--- a/src/test/java/com/android/tools/r8/naming/methodparameters/MethodParametersNullValueTest.java
+++ b/src/test/java/com/android/tools/r8/naming/methodparameters/MethodParametersNullValueTest.java
@@ -39,8 +39,8 @@
 
   @Test
   public void testJvm() throws Exception {
-    parameters.assumeJvmTestParameters();
-    testForJvm(parameters)
+    assumeTrue(parameters.getRuntime().isCf());
+    testForJvm()
         .addProgramClassFileData(getTransformedTestClass())
         .run(parameters.getRuntime(), TestClass.class)
         .apply(this::checkExpected);
@@ -50,14 +50,13 @@
   public void testD8() throws Exception {
     testForD8(parameters.getBackend())
         .addProgramClassFileData(getTransformedTestClass())
-        .setMinApi(parameters)
+        .setMinApi(parameters.getApiLevel())
         .run(parameters.getRuntime(), TestClass.class)
         .apply(this::checkExpected);
   }
 
   @Test
   public void testR8() throws Exception {
-    parameters.assumeR8TestParameters();
     // Don't run on old API as that build is "ill configured" and triggers missing type refs.
     assumeTrue(
         parameters.isCfRuntime()
@@ -66,7 +65,7 @@
                 .isGreaterThanOrEqualTo(apiLevelWithMethodParametersSupport()));
     testForR8(parameters.getBackend())
         .addProgramClassFileData(getTransformedTestClass())
-        .setMinApi(parameters)
+        .setMinApi(parameters.getApiLevel())
         .addKeepClassAndMembersRules(TestClass.class)
         .addKeepAllAttributes()
         .run(parameters.getRuntime(), TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index a8f646c..fdd1abc 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -602,7 +602,7 @@
               for (String parameterName : parameterNames) {
                 mv.visitParameter(parameterName, 0);
               }
-              return new MethodVisitor(ASM_VERSION, mv) {
+              return new MethodVisitor(ASM7, mv) {
                 @Override
                 public void visitParameter(String name, int access) {
                   // Ignore all existing method parameter.
diff --git a/tools/archive.py b/tools/archive.py
index 24e8e0a..a7e169c 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
@@ -37,7 +37,7 @@
   # TODO(mkroghj) This would not work for r8-lib, maybe use utils.getR8Version.
   output = subprocess.check_output([
     jdk.GetJavaExecutable(), '-jar', jar_path, '--version'
-  ])
+  ]).decode('utf-8')
   return output.splitlines()[0].strip()
 
 def GetVersion():
@@ -51,14 +51,14 @@
   return d8_version.split()[1]
 
 def GetGitBranches():
-  return subprocess.check_output(['git', 'show', '-s', '--pretty=%d', 'HEAD'])
+  return subprocess.check_output(['git', 'show', '-s', '--pretty=%d', 'HEAD']).decode('utf-8')
 
 def GetGitHash():
-  return subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip()
+  return subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode('utf-8').strip()
 
 def IsMain(version):
   branches = subprocess.check_output(['git', 'branch', '-r', '--contains',
-                                      'HEAD'])
+                                      'HEAD']).decode('utf-8')
   # CL runs from gerrit does not have a branch, we always treat them as main
   # commits to archive these to the hash based location
   if len(branches) == 0:
diff --git a/tools/create_art_tests.py b/tools/create_art_tests.py
index 978b086..e4549fb 100755
--- a/tools/create_art_tests.py
+++ b/tools/create_art_tests.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
diff --git a/tools/create_jctf_tests.py b/tools/create_jctf_tests.py
index bc065d9..38e1f9c 100755
--- a/tools/create_jctf_tests.py
+++ b/tools/create_jctf_tests.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
@@ -9,7 +9,7 @@
 from os import makedirs
 from os.path import exists, join, dirname
 from shutil import rmtree
-from string import Template, upper
+from string import Template
 import os
 import re
 import sys
diff --git a/tools/download_from_x20.py b/tools/download_from_x20.py
index 5f64684..5796823 100755
--- a/tools/download_from_x20.py
+++ b/tools/download_from_x20.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
@@ -20,7 +20,7 @@
   return optparse.OptionParser().parse_args()
 
 def download(src, dest):
-  print 'Downloading %s to %s' % (src, dest)
+  print('Downloading %s to %s' % (src, dest))
   shutil.copyfile(src, dest)
   utils.unpack_archive(dest)
 
@@ -29,21 +29,21 @@
   assert len(args) == 1
   sha1_file = args[0]
   dest = sha1_file[:-5]
-  print 'Ensuring %s' % dest
+  print('Ensuring %s' % dest)
   with open(sha1_file, 'r') as input_sha:
     sha1 = input_sha.readline()
   if os.path.exists(dest) and utils.get_sha1(dest) == sha1:
-    print 'sha1 matches, not downloading'
+    print('sha1 matches, not downloading')
     dest_dir = utils.extract_dir(dest)
     if os.path.exists(dest_dir):
-      print 'destination directory exists, no extraction'
+      print('destination directory exists, no extraction')
     else:
       utils.unpack_archive(dest)
     return
   src = os.path.join(GMSCORE_DEPS, sha1)
   if not os.path.exists(src):
-    print 'File (%s) does not exist on x20' % src
-    print 'Maybe pass -Pno_internal to your gradle invocation'
+    print('File (%s) does not exist on x20' % src)
+    print('Maybe pass -Pno_internal to your gradle invocation')
     return 42
   download(src, dest)
 
diff --git a/tools/gradle.py b/tools/gradle.py
index 63c92b5..19fa773 100755
--- a/tools/gradle.py
+++ b/tools/gradle.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
@@ -96,7 +96,7 @@
   cmd.extend(args)
   utils.PrintCmd(cmd)
   with utils.ChangedWorkingDirectory(cwd):
-    return subprocess.check_output(cmd, env=GetJavaEnv(env))
+    return subprocess.check_output(cmd, env=GetJavaEnv(env)).decode('utf-8')
 
 def RunGradleWrapperInGetOutput(args, cwd, env=None):
   return RunGradleInGetOutput('./gradlew', args, cwd, env=env)
diff --git a/tools/test.py b/tools/test.py
index 157bd28..53270d6 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
@@ -14,7 +14,7 @@
 import shutil
 import subprocess
 import sys
-import thread
+import threading
 import time
 import uuid
 
@@ -190,8 +190,8 @@
   destination = 'gs://%s/%s' % (BUCKET, u_dir)
   utils.upload_dir_to_cloud_storage(upload_dir, destination, is_html=True)
   url = 'https://storage.googleapis.com/%s/%s/test/index.html' % (BUCKET, u_dir)
-  print 'Test results available at: %s' % url
-  print '@@@STEP_LINK@Test failures@%s@@@' % url
+  print('Test results available at: %s' % url)
+  print('@@@STEP_LINK@Test failures@%s@@@' % url)
 
 def Main():
   (options, args) = ParseOptions()
@@ -341,7 +341,7 @@
     if args is None:
       return 1
     if len(args) == 0:
-      print "No failing tests"
+      print("No failing tests")
       return 0
   # Test filtering. Must always follow the 'test' task.
   for testFilter in args:
@@ -368,7 +368,10 @@
     print_stacks_timeout = (print_stacks_timeout
                             if print_stacks_timeout != -1
                             else TIMEOUT_HANDLER_PERIOD)
-    thread.start_new_thread(timeout_handler, (timestamp_file, print_stacks_timeout,))
+    # thread.start_new_thread(timeout_handler, (timestamp_file, print_stacks_timeout,))
+    threading.Thread(target=timeout_handler,
+                             args=(timestamp_file, print_stacks_timeout),
+                             daemon=True).start()
   rotate_test_reports()
 
   if options.only_jctf:
@@ -379,7 +382,7 @@
   # Now run tests on selected runtime(s).
   if options.runtimes:
     if options.dex_vm != 'default':
-      print 'Unexpected runtimes and dex_vm argument: ' + options.dex_vm
+      print('Unexpected runtimes and dex_vm argument: ' + options.dex_vm)
       sys.exit(1)
     if options.runtimes == 'empty':
       # Set runtimes with no content will configure no runtimes.
@@ -393,9 +396,9 @@
       for prefix in prefixes:
         matches = [ rt for rt in VALID_RUNTIMES if rt.startswith(prefix) ]
         if len(matches) == 0:
-          print "Invalid runtime prefix '%s'." % prefix
-          print "Must be just 'all', 'empty'," \
-                " or a prefix of %s" % ', '.join(VALID_RUNTIMES)
+          print("Invalid runtime prefix '%s'." % prefix)
+          print("Must be just 'all', 'empty'," \
+                " or a prefix of %s" % ', '.join(VALID_RUNTIMES))
           sys.exit(1)
         runtimes.extend(matches)
       gradle_args.append('-Pruntimes=%s' % ':'.join(runtimes))
@@ -472,7 +475,7 @@
     last_timestamp = new_timestamp
 
 def report_dir_path(index):
-  if index is 0:
+  if index == 0:
     return REPORTS_PATH
   return '%s%d' % (REPORTS_PATH, index)
 
@@ -494,7 +497,7 @@
 
 def compute_failed_tests(args):
   if len(args) > 1:
-    print "Running with --failed can take an optional path to a report index (or report number)."
+    print("Running with --failed can take an optional path to a report index (or report number).")
     return None
   report = report_index_path(0)
   # If the default report does not exist, fall back to the previous report as it may be a failed
@@ -512,9 +515,9 @@
       # if integer parsing failed assume it is a report file path.
       report = args[0]
   if not os.path.exists(report):
-    print "Can't re-run failing, no report at:", report
+    print("Can't re-run failing, no report at:", report)
     return None
-  print "Reading failed tests in", report
+  print("Reading failed tests in", report)
   failing = set()
   inFailedSection = False
   for line in file(report):