Merge "test.py: Add option for persistent test artifact directory (for debugging)."
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index f30ee0a..da90e82 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -434,7 +434,7 @@
             options.proguardConfiguration.getPrintMappingFile(),
             System.out,
             StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
-        outputApp.writeProguardMap(closer, mapOut);
+        outputApp.writeProguardMap(mapOut);
       }
     }
     if (options.proguardConfiguration.isPrintSeeds()) {
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
index 2553650..aa32b12 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationReader.java
@@ -75,7 +75,7 @@
       throws IOException, ExecutionException {
     timing.begin("DexApplication.read");
     final DexApplication.Builder builder = new DexApplication.Builder(itemFactory, timing);
-    try (Closer closer = Closer.create()) {
+    try {
       List<Future<?>> futures = new ArrayList<>();
       // Still preload some of the classes, primarily for two reasons:
       // (a) class lazy loading is not supported for DEX files
@@ -84,9 +84,9 @@
       // (b) some of the class file resources don't provide information
       //     about class descriptor.
       // TODO: try and preload less classes.
-      readProguardMap(builder, executorService, futures, closer);
-      readMainDexList(builder, executorService, futures, closer);
-      ClassReader classReader = new ClassReader(executorService, futures, closer);
+      readProguardMap(builder, executorService, futures);
+      readMainDexList(builder, executorService, futures);
+      ClassReader classReader = new ClassReader(executorService, futures);
       classReader.readSources();
       ThreadUtils.awaitFutures(futures);
       classReader.initializeLazyClassCollection(builder);
@@ -130,13 +130,12 @@
   }
 
   private void readProguardMap(DexApplication.Builder builder, ExecutorService executorService,
-      List<Future<?>> futures, Closer closer)
+      List<Future<?>> futures)
       throws IOException {
     // Read the Proguard mapping file in parallel with DexCode and DexProgramClass items.
     if (inputApp.hasProguardMap()) {
       futures.add(executorService.submit(() -> {
-        try {
-          InputStream map = inputApp.getProguardMap(closer);
+        try (InputStream map = inputApp.getProguardMap()) {
           builder.setProguardMap(ProguardMapReader.mapperFromInputStream(map));
         } catch (IOException e) {
           throw new RuntimeException(e);
@@ -146,18 +145,18 @@
   }
 
   private void readMainDexList(DexApplication.Builder builder, ExecutorService executorService,
-      List<Future<?>> futures, Closer closer)
+      List<Future<?>> futures)
       throws IOException {
     if (inputApp.hasMainDexList()) {
       futures.add(executorService.submit(() -> {
-        try {
-          for (Resource resource : inputApp.getMainDexListResources()) {
-            InputStream input = closer.register(resource.getStream());
+        for (Resource resource : inputApp.getMainDexListResources()) {
+          try (InputStream input = resource.getStream()) {
             builder.addToMainDexList(MainDexList.parse(input, itemFactory));
+          } catch (IOException e) {
+            throw new RuntimeException(e);
           }
-        } catch (IOException e) {
-          throw new RuntimeException(e);
         }
+
         builder.addToMainDexList(
             inputApp.getMainDexClasses()
                 .stream()
@@ -170,7 +169,6 @@
   private final class ClassReader {
     private final ExecutorService executorService;
     private final List<Future<?>> futures;
-    private final Closer closer;
 
     // We use concurrent queues to collect classes
     // since the classes can be collected concurrently.
@@ -180,10 +178,9 @@
     // Jar application reader to share across all class readers.
     private final JarApplicationReader application = new JarApplicationReader(options);
 
-    ClassReader(ExecutorService executorService, List<Future<?>> futures, Closer closer) {
+    ClassReader(ExecutorService executorService, List<Future<?>> futures) {
       this.executorService = executorService;
       this.futures = futures;
-      this.closer = closer;
     }
 
     private <T extends DexClass> void readDexSources(List<Resource> dexSources,
@@ -192,9 +189,11 @@
         List<DexFileReader> fileReaders = new ArrayList<>(dexSources.size());
         int computedMinApiLevel = options.minApiLevel;
         for (Resource input : dexSources) {
-          DexFile file = new DexFile(closer.register(input.getStream()));
-          computedMinApiLevel = verifyOrComputeMinApiLevel(computedMinApiLevel, file);
-          fileReaders.add(new DexFileReader(file, classKind, itemFactory));
+          try (InputStream is = input.getStream()) {
+            DexFile file = new DexFile(is);
+            computedMinApiLevel = verifyOrComputeMinApiLevel(computedMinApiLevel, file);
+            fileReaders.add(new DexFileReader(file, classKind, itemFactory));
+          }
         }
         options.minApiLevel = computedMinApiLevel;
         for (DexFileReader reader : fileReaders) {
@@ -216,7 +215,9 @@
       JarClassFileReader reader = new JarClassFileReader(
           application, classKind.bridgeConsumer(classes::add));
       for (Resource input : classSources) {
-        reader.read(DEFAULT_DEX_FILENAME, classKind, closer.register(input.getStream()));
+        try (InputStream is = input.getStream()) {
+          reader.read(DEFAULT_DEX_FILENAME, classKind, is);
+        }
       }
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
index a6b1f2c..2a3e431 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarState.java
@@ -339,12 +339,19 @@
   }
 
   private Local setLocalInfo(int index, Type type, DebugLocalInfo info) {
-    return setLocalInfoForRegister(getLocalRegister(index, type), type, info);
+    return setLocalInfoForRegister(getLocalRegister(index, type), info);
   }
 
-  private Local setLocalInfoForRegister(int register, Type type, DebugLocalInfo info) {
+  private Local setLocalInfoForRegister(int register, DebugLocalInfo info) {
     Local existingLocal = getLocalForRegister(register);
-    Local local = new Local(existingLocal.slot, info);
+    // TODO(ager, zerny): Kotlin debug information contains locals that are not referenced.
+    // That seems broken and we currently do not retain that debug information because
+    // we do not let locals debug information influence code generation. Debug information can
+    // be completely malformed, so we shouldn't let it influence code generation. However, we
+    // need to deal with these unused locals in the debug information. For now we
+    // use a null type for the slot, but we should reconsider that.
+    Slot slot = existingLocal != null ? existingLocal.slot : new Slot(register, null);
+    Local local = new Local(slot, info);
     locals[register] = local;
     return local;
   }
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApp.java b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
index 2480417..006dc1a 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApp.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApp.java
@@ -212,8 +212,8 @@
   /**
    * Get the input stream of the proguard-map resource if it exists.
    */
-  public InputStream getProguardMap(Closer closer) throws IOException {
-    return proguardMap == null ? null : closer.register(proguardMap.getStream());
+  public InputStream getProguardMap() throws IOException {
+    return proguardMap == null ? null : proguardMap.getStream();
   }
 
   /**
@@ -382,10 +382,11 @@
     }
   }
 
-  public void writeProguardMap(Closer closer, OutputStream out) throws IOException {
-    InputStream input = getProguardMap(closer);
-    assert input != null;
-    out.write(ByteStreams.toByteArray(input));
+  public void writeProguardMap(OutputStream out) throws IOException {
+    try (InputStream input = getProguardMap()) {
+      assert input != null;
+      out.write(ByteStreams.toByteArray(input));
+    }
   }
 
   public void writeProguardSeeds(Closer closer, OutputStream out) throws IOException {
diff --git a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
index 66137df..d5f9c6a 100644
--- a/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
+++ b/src/test/java/com/android/tools/r8/jsr45/JSR45Tests.java
@@ -70,10 +70,8 @@
                 .addProguardConfigurationFiles(keepRulesPath)
                 .build());
     if (androidApp.hasProguardMap()) {
-      try (Closer closer = Closer.create()) {
-        androidApp.writeProguardMap(closer, new FileOutputStream(
+        androidApp.writeProguardMap(new FileOutputStream(
             Paths.get(tmpOutputDir.getRoot().getCanonicalPath(), DEFAULT_MAP_FILENAME).toFile()));
-      }
     }
   }
 
diff --git a/src/test/java/com/android/tools/r8/optimize/R8DebugStrippingTest.java b/src/test/java/com/android/tools/r8/optimize/R8DebugStrippingTest.java
index 72b452f..1426a0f 100644
--- a/src/test/java/com/android/tools/r8/optimize/R8DebugStrippingTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/R8DebugStrippingTest.java
@@ -30,6 +30,7 @@
 import com.google.common.collect.Maps;
 import com.google.common.io.Closer;
 import java.io.IOException;
+import java.io.InputStream;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.HashMap;
@@ -115,8 +116,8 @@
         ToolHelper.runR8(command, (options) -> options.skipDebugLineNumberOpt = !compressRanges);
 
     ClassNameMapper classNameMapper;
-    try (Closer closer = Closer.create()) {
-      classNameMapper = ProguardMapReader.mapperFromInputStream(result.getProguardMap(closer));
+    try (InputStream is = result.getProguardMap()) {
+      classNameMapper = ProguardMapReader.mapperFromInputStream(is);
     }
     if (compressRanges) {
       classNameMapper.forAllClassNamings(this::ensureRangesAreUniquePerClass);