Cache stack map verification from open/closed interfaces analysis

Change-Id: I482279b3c84ca25d7bc1b73dce0c428c54730a21
diff --git a/src/main/java/com/android/tools/r8/cf/CfVerifierTool.java b/src/main/java/com/android/tools/r8/cf/CfVerifierTool.java
index bd4a06f..5b1d74f 100644
--- a/src/main/java/com/android/tools/r8/cf/CfVerifierTool.java
+++ b/src/main/java/com/android/tools/r8/cf/CfVerifierTool.java
@@ -36,7 +36,12 @@
     appView.setAppServices(AppServices.builder(appView).build());
     for (DexProgramClass clazz : appView.appInfo().classes()) {
       clazz.forEachProgramMethod(
-          method -> method.getDefinition().getCode().asCfCode().verifyFrames(method, appView));
+          method ->
+              method
+                  .getDefinition()
+                  .getCode()
+                  .asCfCode()
+                  .getOrComputeStackMapStatus(method, appView));
     }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrameVerifier.java b/src/main/java/com/android/tools/r8/cf/code/CfFrameVerifier.java
index 7866b2d..bdd6512 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrameVerifier.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrameVerifier.java
@@ -378,6 +378,10 @@
       return this == NOT_PRESENT;
     }
 
+    public boolean isNotVerified() {
+      return this == NOT_VERIFIED;
+    }
+
     public boolean isValid() {
       return this == VALID;
     }
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 0d4f9c9..68deb8e 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -248,6 +248,10 @@
     return stackMapStatus;
   }
 
+  public void setStackMapStatus(StackMapStatus stackMapStatus) {
+    this.stackMapStatus = stackMapStatus;
+  }
+
   public com.android.tools.r8.position.Position getDiagnosticPosition() {
     return diagnosticPosition;
   }
@@ -407,7 +411,7 @@
       LensCodeRewriterUtils rewriter,
       MethodVisitor visitor) {
     GraphLens graphLens = appView.graphLens();
-    assert verifyFrames(method, appView).isValidOrNotPresent()
+    assert getOrComputeStackMapStatus(method, appView).isValidOrNotPresent()
         : "Could not validate stack map frames";
     DexItemFactory dexItemFactory = appView.dexItemFactory();
     InitClassLens initClassLens = appView.initClassLens();
@@ -545,7 +549,7 @@
   }
 
   private void verifyFramesOrRemove(ProgramMethod method, AppView<?> appView, GraphLens codeLens) {
-    stackMapStatus = verifyFrames(method, appView, codeLens);
+    stackMapStatus = getOrComputeStackMapStatus(method, appView, codeLens);
     if (!stackMapStatus.isValidOrNotPresent()) {
       ArrayList<CfInstruction> copy = new ArrayList<>(instructions);
       copy.removeIf(CfInstruction::isFrame);
@@ -884,11 +888,20 @@
         originalHolder, maxStack, maxLocals, newInstructions, tryCatchRanges, localVariables);
   }
 
-  public StackMapStatus verifyFrames(ProgramMethod method, AppView<?> appView) {
-    return verifyFrames(method, appView, getCodeLens(appView));
+  public StackMapStatus getOrComputeStackMapStatus(ProgramMethod method, AppView<?> appView) {
+    return getOrComputeStackMapStatus(method, appView, getCodeLens(appView));
   }
 
-  public StackMapStatus verifyFrames(ProgramMethod method, AppView<?> appView, GraphLens codeLens) {
+  public StackMapStatus getOrComputeStackMapStatus(
+      ProgramMethod method, AppView<?> appView, GraphLens codeLens) {
+    if (stackMapStatus.isNotVerified()) {
+      setStackMapStatus(computeStackMapStatus(method, appView, codeLens));
+    }
+    return stackMapStatus;
+  }
+
+  private StackMapStatus computeStackMapStatus(
+      ProgramMethod method, AppView<?> appView, GraphLens codeLens) {
     CfFrameVerifierEventConsumer eventConsumer =
         new CfFrameVerifierEventConsumer() {
 
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index cb3bf73..a62fd2f 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -193,7 +193,8 @@
     DexBuilder.removeRedundantDebugPositions(code);
     CfCode code = buildCfCode();
     assert verifyInvokeInterface(code, appView);
-    assert code.verifyFrames(method, appView, appView.graphLens()).isValidOrNotPresent();
+    assert code.getOrComputeStackMapStatus(method, appView, appView.graphLens())
+        .isValidOrNotPresent();
     return code;
   }
 
diff --git a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
index bc44d01..7d65c1e 100644
--- a/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/interfaces/analysis/CfOpenClosedInterfacesAnalysis.java
@@ -91,8 +91,12 @@
     CfAnalysisConfig config = createConfig(method, cfCode);
     CfOpenClosedInterfacesAnalysisHelper helper =
         new CfOpenClosedInterfacesAnalysisHelper(appView, method, unverifiableCodeDiagnostics);
-    if (runLinearScan(method, cfCode, config, helper).isNotPresent()) {
+    StackMapStatus stackMapStatus = runLinearScan(method, cfCode, config, helper);
+    if (stackMapStatus.isNotPresent()) {
       runFixpoint(method, cfCode, config, helper);
+      cfCode.setStackMapStatus(stackMapStatus);
+    } else if (stackMapStatus.isValid()) {
+      cfCode.setStackMapStatus(stackMapStatus);
     }
     return helper.getOpenInterfaces();
   }