Merge "Separate interface method minification from class method minification"
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 734e421..4f472c6 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -63,7 +63,6 @@
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.android.tools.r8.utils.LineNumberOptimizer;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.SelfRetraceTest;
@@ -634,12 +633,7 @@
       // When line number optimization is turned off the identity mapping for line numbers is
       // used. We still run the line number optimizer to collect line numbers and inline frame
       // information for the mapping file.
-      ClassNameMapper classNameMapper =
-          LineNumberOptimizer.run(
-              application,
-              appView.graphLense(),
-              namingLens,
-              options.lineNumberOptimization == LineNumberOptimization.OFF);
+      ClassNameMapper classNameMapper = LineNumberOptimizer.run(appView, application, namingLens);
       timing.end();
       proguardMapSupplier = ProguardMapSupplier.fromClassNameMapper(classNameMapper, options);
 
diff --git a/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphEdgeInfo.java b/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphEdgeInfo.java
index e3fa01b..88b3b4b 100644
--- a/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphEdgeInfo.java
+++ b/src/main/java/com/android/tools/r8/experimental/graphinfo/GraphEdgeInfo.java
@@ -15,6 +15,7 @@
     TargetedBySuper,
     InvokedFrom,
     InvokedFromLambdaCreatedIn,
+    AnnotatedOn,
     ReferencedFrom,
     ReflectiveUseFrom,
     ReachableFromLiveType,
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index a51ca83..f011931 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -177,10 +177,10 @@
    * for these.
    */
   private final Set<DexType> liveTypes = Sets.newIdentityHashSet();
-  /**
-   * Set of annotation types that are instantiated.
-   */
-  private final Set<DexType> instantiatedAnnotations = Sets.newIdentityHashSet();
+
+  /** Set of annotation types that are instantiated. */
+  private final SetWithReason<DexAnnotation> instantiatedAnnotations =
+      new SetWithReason<>(this::registerAnnotation);
   /** Set of types that are actually instantiated. These cannot be abstract. */
   private final SetWithReason<DexType> instantiatedTypes = new SetWithReason<>(this::registerType);
   /**
@@ -803,9 +803,6 @@
           }
         }
       }
-      if (!holder.annotations.isEmpty()) {
-        processAnnotations(holder.annotations.annotations);
-      }
       // We also need to add the corresponding <clinit> to the set of live methods, as otherwise
       // static field initialization (and other class-load-time sideeffects) will not happen.
       KeepReason reason = KeepReason.reachableFromLiveType(type);
@@ -821,10 +818,15 @@
         enqueueFirstNonSerializableClassInitializer(holder, reason);
       }
 
-      // If this type has deferred annotations, we have to process those now, too.
-      Set<DexAnnotation> annotations = deferredAnnotations.remove(type);
-      if (annotations != null) {
-        annotations.forEach(this::handleAnnotationOfLiveType);
+      if (!holder.isLibraryClass()) {
+        if (!holder.annotations.isEmpty()) {
+          processAnnotations(holder, holder.annotations.annotations);
+        }
+        // If this type has deferred annotations, we have to process those now, too.
+        Set<DexAnnotation> annotations = deferredAnnotations.remove(type);
+        if (annotations != null) {
+          annotations.forEach(annotation -> handleAnnotationOfLiveType(holder, annotation));
+        }
       }
 
       Map<DexReference, Set<ProguardKeepRule>> dependentItems = rootSet.getDependentItems(holder);
@@ -834,36 +836,33 @@
     }
   }
 
-  private void handleAnnotationOfLiveType(DexAnnotation annotation) {
-    DexType type = annotation.annotation.type;
-    // Record that it is instantiated if it should be kept when its type is live.
-    if (shouldKeepAnnotation(annotation, true, appInfo.dexItemFactory, options)) {
-      instantiatedAnnotations.add(type);
-    }
-    AnnotationReferenceMarker referenceMarker = new AnnotationReferenceMarker(
-        annotation.annotation.type, appInfo.dexItemFactory);
-    annotation.annotation.collectIndexedItems(referenceMarker);
+  private void handleAnnotationOfLiveType(DexDefinition holder, DexAnnotation annotation) {
+    handleAnnotation(holder, annotation, true);
   }
 
-  private void processAnnotations(DexAnnotation[] annotations) {
+  private void processAnnotations(DexDefinition holder, DexAnnotation[] annotations) {
     for (DexAnnotation annotation : annotations) {
-      processAnnotation(annotation);
+      processAnnotation(holder, annotation);
     }
   }
 
-  private void processAnnotation(DexAnnotation annotation) {
+  private void processAnnotation(DexDefinition holder, DexAnnotation annotation) {
+    handleAnnotation(holder, annotation, false);
+  }
+
+  private void handleAnnotation(DexDefinition holder, DexAnnotation annotation, boolean forceLive) {
+    assert !holder.isDexClass() || !holder.asDexClass().isLibraryClass();
     DexType type = annotation.annotation.type;
-    if (liveTypes.contains(type)) {
-      // The type of this annotation is already live, so pick up its dependencies.
-      handleAnnotationOfLiveType(annotation);
-    } else {
-      // Record that it is instantiated if it should be kept although its type is not live.
-      if (shouldKeepAnnotation(annotation, false, appInfo.dexItemFactory, options)) {
-        instantiatedAnnotations.add(type);
-      }
+    boolean isLive = forceLive || liveTypes.contains(type);
+    if (!shouldKeepAnnotation(annotation, isLive, appInfo.dexItemFactory, options)) {
       // Remember this annotation for later.
       deferredAnnotations.computeIfAbsent(type, ignore -> new HashSet<>()).add(annotation);
+      return;
     }
+    instantiatedAnnotations.add(annotation, KeepReason.annotatedOn(holder));
+    AnnotationReferenceMarker referenceMarker =
+        new AnnotationReferenceMarker(annotation.annotation.type, appInfo.dexItemFactory);
+    annotation.annotation.collectIndexedItems(referenceMarker);
   }
 
   private void handleInvokeOfStaticTarget(DexMethod method, KeepReason reason) {
@@ -956,8 +955,11 @@
     }
     markTypeAsLive(method.method.holder);
     markParameterAndReturnTypesAsLive(method);
-    processAnnotations(method.annotations.annotations);
-    method.parameterAnnotationsList.forEachAnnotation(this::processAnnotation);
+    if (!appInfo.definitionFor(method.method.holder).isLibraryClass()) {
+      processAnnotations(method, method.annotations.annotations);
+      method.parameterAnnotationsList.forEachAnnotation(
+          annotation -> processAnnotation(method, annotation));
+    }
     if (Log.ENABLED) {
       Log.verbose(getClass(), "Method `%s` is targeted.", method.method);
     }
@@ -1614,8 +1616,11 @@
         }
       }
       markParameterAndReturnTypesAsLive(method);
-      processAnnotations(method.annotations.annotations);
-      method.parameterAnnotationsList.forEachAnnotation(this::processAnnotation);
+      if (!appInfo.definitionFor(method.method.holder).isLibraryClass()) {
+        processAnnotations(method, method.annotations.annotations);
+        method.parameterAnnotationsList.forEachAnnotation(
+            annotation -> processAnnotation(method, annotation));
+      }
       method.registerCodeReferences(new UseRegistry(options.itemFactory, method));
       // Add all dependent members to the workqueue.
       enqueueRootItems(rootSet.getDependentItems(method));
@@ -2013,8 +2018,11 @@
       super(appInfo);
       this.liveTypes = ImmutableSortedSet.copyOf(
           PresortedComparable<DexType>::slowCompareTo, enqueuer.liveTypes);
-      this.instantiatedAnnotations = ImmutableSortedSet.copyOf(
-          PresortedComparable<DexType>::slowCompareTo, enqueuer.instantiatedAnnotations);
+      ImmutableSortedSet.Builder<DexType> builder =
+          ImmutableSortedSet.orderedBy(PresortedComparable<DexType>::slowCompareTo);
+      enqueuer.instantiatedAnnotations.items.forEach(
+          annotation -> builder.add(annotation.annotation.type));
+      this.instantiatedAnnotations = builder.build();
       this.instantiatedTypes = ImmutableSortedSet.copyOf(
           PresortedComparable<DexType>::slowCompareTo, enqueuer.instantiatedTypes.getItems());
       this.instantiatedLambdas =
@@ -2795,6 +2803,14 @@
     registerEdge(getClassGraphNode(type), reason);
   }
 
+  private void registerAnnotation(DexAnnotation annotation, KeepReason reason) {
+    assert getSourceNode(reason) != null;
+    if (keptGraphConsumer == null) {
+      return;
+    }
+    registerEdge(getAnnotationGraphNode(annotation.annotation.type), reason);
+  }
+
   private void registerMethod(DexEncodedMethod method, KeepReason reason) {
     if (reason.edgeKind() == EdgeKind.IsLibraryMethod) {
       // Don't report edges to actual library methods.
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepReason.java b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
index a797742..2dd52eb 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepReason.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo;
 import com.android.tools.r8.experimental.graphinfo.GraphEdgeInfo.EdgeKind;
 import com.android.tools.r8.experimental.graphinfo.GraphNode;
+import com.android.tools.r8.graph.DexDefinition;
 import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexType;
@@ -17,6 +18,10 @@
 
   public abstract GraphNode getSourceNode(Enqueuer enqueuer);
 
+  static KeepReason annotatedOn(DexDefinition definition) {
+    return new AnnotatedOn(definition);
+  }
+
   static KeepReason dueToKeepRule(ProguardKeepRule rule) {
     return new DueToKeepRule(rule);
   }
@@ -302,6 +307,32 @@
     }
   }
 
+  private static class AnnotatedOn extends KeepReason {
+
+    private final DexDefinition holder;
+
+    private AnnotatedOn(DexDefinition holder) {
+      this.holder = holder;
+    }
+
+    @Override
+    public EdgeKind edgeKind() {
+      return EdgeKind.AnnotatedOn;
+    }
+
+    @Override
+    public GraphNode getSourceNode(Enqueuer enqueuer) {
+      if (holder.isDexClass()) {
+        return enqueuer.getClassGraphNode(holder.asDexClass().type);
+      } else if (holder.isDexEncodedField()) {
+        return enqueuer.getFieldGraphNode(holder.asDexEncodedField().field);
+      } else {
+        assert holder.isDexEncodedMethod();
+        return enqueuer.getMethodGraphNode(holder.asDexEncodedMethod().method);
+      }
+    }
+  }
+
   private static class ReflectiveUseFrom extends BasedOnOtherMethod {
 
     private ReflectiveUseFrom(DexEncodedMethod method) {
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index f5a4b81..427341f 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -5,6 +5,8 @@
 
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfPosition;
+import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.CfCode;
 import com.android.tools.r8.graph.Code;
 import com.android.tools.r8.graph.DexApplication;
@@ -39,6 +41,7 @@
 import com.android.tools.r8.naming.MemberNaming.MethodSignature;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.naming.Range;
+import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
 import com.google.common.base.Suppliers;
 import java.util.ArrayList;
 import java.util.IdentityHashMap;
@@ -66,13 +69,33 @@
   }
 
   private static class OptimizingPositionRemapper implements PositionRemapper {
-    private int nextLineNumber = 1;
+    private final int maxLineDelta;
+    private DexMethod previousMethod = null;
+    private int previousSourceLine = -1;
+    private int nextOptimizedLineNumber = 1;
+
+    OptimizingPositionRemapper(InternalOptions options) {
+      // TODO(113198295): For dex using "Constants.DBG_LINE_RANGE + Constants.DBG_LINE_BASE"
+      // instead of 1 creates a ~30% smaller map file but the dex files gets larger due to reduced
+      // debug info canonicalization.
+      maxLineDelta = options.isGeneratingClassFiles() ? Integer.MAX_VALUE : 1;
+    }
 
     @Override
     public Position createRemappedPosition(
         int line, DexString file, DexMethod method, Position callerPosition) {
-      Position newPosition = new Position(nextLineNumber, file, method, null);
-      ++nextLineNumber;
+      assert method != null;
+      if (previousMethod == method) {
+        assert previousSourceLine >= 0;
+        if (line > previousSourceLine && line - previousSourceLine <= maxLineDelta) {
+            nextOptimizedLineNumber += (line - previousSourceLine) - 1;
+        }
+      }
+
+      Position newPosition = new Position(nextOptimizedLineNumber, file, method, null);
+      ++nextOptimizedLineNumber;
+      previousSourceLine = line;
+      previousMethod = method;
       return newPosition;
     }
   }
@@ -138,10 +161,9 @@
   }
 
   public static ClassNameMapper run(
+      AppView<AppInfoWithSubtyping> appView,
       DexApplication application,
-      GraphLense graphLense,
-      NamingLens namingLens,
-      boolean identityMapping) {
+      NamingLens namingLens) {
     ClassNameMapper.Builder classNameMapperBuilder = ClassNameMapper.builder();
     // Collect which files contain which classes that need to have their line numbers optimized.
     for (DexProgramClass clazz : application.classes()) {
@@ -151,7 +173,7 @@
       // At this point we don't know if we really need to add this class to the builder.
       // It depends on whether any methods/fields are renamed or some methods contain positions.
       // Create a supplier which creates a new, cached ClassNaming.Builder on-demand.
-      DexType originalType = graphLense.getOriginalType(clazz.type);
+      DexType originalType = appView.graphLense().getOriginalType(clazz.type);
       DexString renamedClassName = namingLens.lookupDescriptor(clazz.getType());
       Supplier<ClassNaming.Builder> onDemandClassNamingBuilder =
           Suppliers.memoize(
@@ -164,7 +186,7 @@
       addClassToClassNaming(originalType, renamedClassName, onDemandClassNamingBuilder);
 
       // First transfer renamed fields to classNamingBuilder.
-      addFieldsToClassNaming(graphLense, namingLens, clazz, onDemandClassNamingBuilder);
+      addFieldsToClassNaming(appView.graphLense(), namingLens, clazz, onDemandClassNamingBuilder);
 
       // Then process the methods, ordered by renamed name.
       List<DexString> renamedMethodNames = new ArrayList<>(methodsByRenamedName.keySet());
@@ -179,8 +201,12 @@
           sortMethods(methods);
         }
 
+        boolean identityMapping =
+            appView.options().lineNumberOptimization == LineNumberOptimization.OFF;
         PositionRemapper positionRemapper =
-            identityMapping ? new IdentityPositionRemapper() : new OptimizingPositionRemapper();
+            identityMapping
+                ? new IdentityPositionRemapper()
+                : new OptimizingPositionRemapper(appView.options());
 
         for (DexEncodedMethod method : methods) {
           List<MappedPosition> mappedPositions = new ArrayList<>();
@@ -194,7 +220,7 @@
             }
           }
 
-          DexMethod originalMethod = graphLense.getOriginalMethodSignature(method.method);
+          DexMethod originalMethod = appView.graphLense().getOriginalMethodSignature(method.method);
           MethodSignature originalSignature =
               MethodSignature.fromDexMethod(originalMethod, originalMethod.holder != clazz.type);
 
@@ -217,7 +243,7 @@
           signatures.put(originalMethod, originalSignature);
           Function<DexMethod, MethodSignature> getOriginalMethodSignature =
               m -> {
-                DexMethod original = graphLense.getOriginalMethodSignature(m);
+                DexMethod original = appView.graphLense().getOriginalMethodSignature(m);
                 return signatures.computeIfAbsent(
                     original,
                     key ->
diff --git a/src/test/java/com/android/tools/r8/naming/retrace/LineDeltaTest.java b/src/test/java/com/android/tools/r8/naming/retrace/LineDeltaTest.java
new file mode 100644
index 0000000..4e64e7e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/naming/retrace/LineDeltaTest.java
@@ -0,0 +1,102 @@
+// Copyright (c) 2019, 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.
+
+package com.android.tools.r8.naming.retrace;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.ForceInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+
+public class LineDeltaTest extends TestBase {
+  public String runTest(Backend backend) throws Exception {
+    return testForR8(backend)
+        .enableInliningAnnotations()
+        .addProgramClasses(LineDeltaTestClass.class)
+        .addKeepMainRule(LineDeltaTestClass.class)
+        .addKeepRules("-keepattributes LineNumberTable")
+        .run(LineDeltaTestClass.class)
+        .assertSuccessWithOutput(StringUtils.lines(
+            "In test1() - 1",
+            "In test1() - 2",
+            "In test1() - 3",
+            "In test1() - 4",
+            "In test2() - 1",
+            "In test2() - 2",
+            "In test2() - 3",
+            "In test2() - 4"
+        ))
+        .proguardMap();
+  }
+
+  private long mapLines(String map) {
+    return StringUtils.splitLines(map).stream().filter(line -> !line.startsWith("#")).count();
+  }
+
+  @Test
+  public void testDex() throws Exception {
+    assertEquals(17, mapLines(runTest(Backend.DEX)));
+  }
+
+  @Test
+  public void testCf() throws Exception {
+    assertEquals(5, mapLines(runTest(Backend.CF)));
+  }
+}
+
+class LineDeltaTestClass {
+  @ForceInline
+  static void test1() {
+    System.out.println("In test1() - 1");
+    // One line comment.
+    System.out.println("In test1() - 2");
+    // Two line comments.
+    //
+    System.out.println("In test1() - 3");
+    // Four line comments.
+    //
+    //
+    //
+    System.out.println("In test1() - 4");
+  }
+
+  @ForceInline
+  static void test2() {
+    System.out.println("In test2() - 1");
+    // Seven line comments.
+    //
+    //
+    //
+    //
+    //
+    //
+    System.out.println("In test2() - 2");
+    // Eight line comments.
+    //
+    //
+    //
+    //
+    //
+    //
+    //
+    System.out.println("In test2() - 3");
+    // Nine line comments.
+    //
+    //
+    //
+    //
+    //
+    //
+    //
+    //
+    System.out.println("In test2() - 4");
+  }
+
+  public static void main(String[] args) {
+    test1();
+    test2();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/UnusedTypeInThrowingTest.java b/src/test/java/com/android/tools/r8/shaking/UnusedTypeInThrowingTest.java
index 6a03a43..d199f57 100644
--- a/src/test/java/com/android/tools/r8/shaking/UnusedTypeInThrowingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/UnusedTypeInThrowingTest.java
@@ -4,16 +4,21 @@
 
 package com.android.tools.r8.shaking;
 
+import static junit.framework.TestCase.assertTrue;
+
 import com.android.tools.r8.CompilationFailedException;
 import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import java.io.IOException;
-import org.junit.Ignore;
+import java.util.concurrent.ExecutionException;
 import org.junit.Test;
 
 class UnusedTypeInThrowing {
 
+  public static final String EXPECTED = "42";
+
   public static void main(String[] args) throws UnusedTypeInThrowingThrowable {
-    System.out.print("42");
+    System.out.print(EXPECTED);
   }
 }
 
@@ -25,14 +30,20 @@
   static final Class MAIN_CLASS = UnusedTypeInThrowing.class;
 
   @Test
-  @Ignore("b/124019003")
-  public void testTypeIsMarkedAsLive() throws IOException, CompilationFailedException {
-    testForR8(Backend.CF)
-        .addProgramClasses(MAIN_CLASS)
-        .addProgramClasses(THROWABLE_CLASS)
-        .addKeepMainRule(MAIN_CLASS)
-        .addKeepRules("-keepattributes Exceptions")
-        .run(MAIN_CLASS)
-        .assertSuccessWithOutput("42");
+  public void testTypeIsMarkedAsLive()
+      throws IOException, CompilationFailedException, ExecutionException, NoSuchMethodException {
+    CodeInspector inspector =
+        testForR8(Backend.CF)
+            .enableGraphInspector()
+            .addProgramClasses(MAIN_CLASS)
+            .addProgramClasses(THROWABLE_CLASS)
+            .addKeepMainRule(MAIN_CLASS)
+            .addKeepRules("-keepattributes Exceptions")
+            .run(MAIN_CLASS)
+            .assertSuccessWithOutput(UnusedTypeInThrowing.EXPECTED)
+            .inspector();
+
+    assertTrue(inspector.clazz(THROWABLE_CLASS).isPresent());
+    // TODO(b/124217402) When done check that THROWABLE_CLASS is kept by the throwing annotation.
   }
 }
diff --git a/src/test/java/com/android/tools/r8/shaking/UnusedTypeInThrowingTestRunner.java b/src/test/java/com/android/tools/r8/shaking/UnusedTypeInThrowingTestRunner.java
deleted file mode 100644
index 2bf42a1..0000000
--- a/src/test/java/com/android/tools/r8/shaking/UnusedTypeInThrowingTestRunner.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2019, 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.
-
-package com.android.tools.r8.shaking;
-
-import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.TestBase;
-import com.google.common.collect.ImmutableList;
-import java.io.IOException;
-import java.nio.file.Path;
-import org.junit.Ignore;
-import org.junit.Test;
-
-public class UnusedTypeInThrowingTestRunner extends TestBase {
-
-  static final Class THROWABLE_CLASS = UnusedTypeInThrowingThrowable.class;
-  static final Class MAIN_CLASS = UnusedTypeInThrowingTest.class;
-
-  @Test
-  @Ignore("b/124019003")
-  public void testTypeIsMarkedAsLive() throws IOException, CompilationFailedException {
-    Path outDex = temp.newFile("out.zip").toPath();
-    testForR8(Backend.CF)
-        .addProgramClasses(MAIN_CLASS)
-        .addProgramClasses(THROWABLE_CLASS)
-        .addKeepMainRule(MAIN_CLASS)
-        .addKeepRules(ImmutableList.of("-keepattributes Exceptions"))
-        .setMode(CompilationMode.RELEASE)
-        .enableInliningAnnotations()
-        .minification(true)
-        .compile()
-        .run(MAIN_CLASS)
-        .assertSuccessWithOutput("42");
-  }
-}
diff --git a/third_party/openjdk/openjdk-9.0.4/osx.tar.gz.sha1 b/third_party/openjdk/openjdk-9.0.4/osx.tar.gz.sha1
index 7db6817..231fb73 100644
--- a/third_party/openjdk/openjdk-9.0.4/osx.tar.gz.sha1
+++ b/third_party/openjdk/openjdk-9.0.4/osx.tar.gz.sha1
@@ -1 +1 @@
-a68b718365f7ce214eec2f6bb89311885940b10e
\ No newline at end of file
+7084f18a3aad664361c52188d5f899d3050e3eb6
\ No newline at end of file