Reapply "Compute reachability sensitive when parsing program classes"

This reverts commit a3e66fdc2349c5d2895482801c10b10cec7822fd.

Change-Id: I897f535b721ca6dfb4306b393a49cde3ae45780f
diff --git a/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java b/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java
index ccfe752..6b6d239 100644
--- a/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java
+++ b/src/main/java/com/android/tools/r8/GlobalSyntheticsGenerator.java
@@ -53,6 +53,7 @@
 import com.android.tools.r8.utils.AndroidApp;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import com.android.tools.r8.utils.SelfRetraceTest;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.ThreadUtils;
@@ -266,7 +267,8 @@
         DexEncodedField.EMPTY_ARRAY,
         MethodCollectionFactory.empty(),
         factory.getSkipNameValidationForTesting(),
-        DexProgramClass::invalidChecksumRequest);
+        DexProgramClass::invalidChecksumRequest,
+        ReachabilitySensitiveValue.DISABLED);
   }
 
   private static void createAllApiStubs(
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index 5ddb8c1..22cf38f 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -73,6 +73,7 @@
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.Pair;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import com.google.common.io.ByteStreams;
 import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
@@ -900,7 +901,10 @@
               virtualMethods,
               dexItemFactory.getSkipNameValidationForTesting(),
               checksumSupplier,
-              null);
+              null,
+              // Interpreting reachability sensitivity from DEX inputs is not supported.
+              // The compiler does not support building IR from DEX with debug information.
+              ReachabilitySensitiveValue.DISABLED);
       classCollection.accept(clazz); // Update the application object.
     }
   }
diff --git a/src/main/java/com/android/tools/r8/graph/ClassKind.java b/src/main/java/com/android/tools/r8/graph/ClassKind.java
index 0e3e660..9d6df7a 100644
--- a/src/main/java/com/android/tools/r8/graph/ClassKind.java
+++ b/src/main/java/com/android/tools/r8/graph/ClassKind.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.graph.MethodCollection.MethodCollectionFactory;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.synthesis.SyntheticMarker;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import java.util.List;
 import java.util.function.Predicate;
 
@@ -38,7 +39,8 @@
               virtualMethods,
               skipNameValidationForTesting,
               checksumSupplier,
-              syntheticMarker) ->
+              syntheticMarker,
+              reachabilitySensitive) ->
               new DexProgramClass(
                   type,
                   originKind,
@@ -60,6 +62,7 @@
                   MethodCollectionFactory.fromMethods(directMethods, virtualMethods),
                   skipNameValidationForTesting,
                   checksumSupplier,
+                  reachabilitySensitive,
                   syntheticMarker),
           DexClass::isProgramClass);
   public static ClassKind<DexClasspathClass> CLASSPATH =
@@ -85,7 +88,8 @@
               virtualMethods,
               skipNameValidationForTesting,
               checksumSupplier,
-              syntheticMarker) ->
+              syntheticMarker,
+              unusedReachabilitySensitive) ->
               new DexClasspathClass(
                   type,
                   kind,
@@ -130,7 +134,8 @@
               virtualMethods,
               skipNameValidationForTesting,
               checksumSupplier,
-              syntheticMarker) ->
+              syntheticMarker,
+              unusedReachabilitySensitive) ->
               new DexLibraryClass(
                   type,
                   kind,
@@ -176,7 +181,8 @@
         DexEncodedMethod[] virtualMethods,
         boolean skipNameValidationForTesting,
         ChecksumSupplier checksumSupplier,
-        SyntheticMarker syntheticMarker);
+        SyntheticMarker syntheticMarker,
+        ReachabilitySensitiveValue reachabilitySensitive);
   }
 
   private final Factory<C> factory;
@@ -209,7 +215,8 @@
       DexEncodedMethod[] virtualMethods,
       boolean skipNameValidationForTesting,
       ChecksumSupplier checksumSupplier,
-      SyntheticMarker syntheticMarker) {
+      SyntheticMarker syntheticMarker,
+      ReachabilitySensitiveValue reachabilitySensitive) {
     return factory.create(
         type,
         kind,
@@ -232,7 +239,8 @@
         virtualMethods,
         skipNameValidationForTesting,
         checksumSupplier,
-        syntheticMarker);
+        syntheticMarker,
+        reachabilitySensitive);
   }
 
   public boolean isOfKind(DexClass clazz) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index c43043c..a7e37bc 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -809,8 +809,11 @@
   public final DexType annotationCovariantReturnTypes =
       createStaticallyKnownType(
           "Ldalvik/annotation/codegen/CovariantReturnType$CovariantReturnTypes;");
+
+  public final String annotationReachabilitySensitiveDesc =
+      "Ldalvik/annotation/optimization/ReachabilitySensitive;";
   public final DexType annotationReachabilitySensitive =
-      createStaticallyKnownType("Ldalvik/annotation/optimization/ReachabilitySensitive;");
+      createStaticallyKnownType(annotationReachabilitySensitiveDesc);
 
   private static final String METAFACTORY_METHOD_NAME = "metafactory";
   private static final String METAFACTORY_ALT_METHOD_NAME = "altMetafactory";
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 68bc137..5b0aec4 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -21,7 +21,7 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.synthesis.SyntheticMarker;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OptionalBool;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import com.android.tools.r8.utils.TraversalContinuation;
 import com.android.tools.r8.utils.structural.Ordered;
 import com.android.tools.r8.utils.structural.StructuralItem;
@@ -54,7 +54,7 @@
   private CfVersion initialClassFileVersion = null;
   private boolean deprecated = false;
   private KotlinClassLevelInfo kotlinInfo = getNoKotlinInfo();
-  private OptionalBool reachabilitySensitive = OptionalBool.unknown();
+  private final ReachabilitySensitiveValue reachabilitySensitive;
 
   private final ChecksumSupplier checksumSupplier;
 
@@ -81,6 +81,7 @@
       MethodCollectionFactory methodCollectionFactory,
       boolean skipNameValidationForTesting,
       ChecksumSupplier checksumSupplier,
+      ReachabilitySensitiveValue reachabilitySensitive,
       SyntheticMarker syntheticMarker) {
     super(
         sourceFile,
@@ -106,6 +107,7 @@
     this.originKind = originKind;
     this.checksumSupplier = checksumSupplier;
     this.syntheticMarker = syntheticMarker;
+    this.reachabilitySensitive = reachabilitySensitive;
   }
 
   public DexProgramClass(
@@ -128,7 +130,8 @@
       DexEncodedField[] instanceFields,
       MethodCollectionFactory methodCollectionFactory,
       boolean skipNameValidationForTesting,
-      ChecksumSupplier checksumSupplier) {
+      ChecksumSupplier checksumSupplier,
+      ReachabilitySensitiveValue reachabilitySensitive) {
     this(
         type,
         originKind,
@@ -150,6 +153,7 @@
         methodCollectionFactory,
         skipNameValidationForTesting,
         checksumSupplier,
+        reachabilitySensitive,
         null);
   }
 
@@ -174,7 +178,8 @@
         DexEncodedField.EMPTY_ARRAY,
         MethodCollectionFactory.empty(),
         false,
-        DexProgramClass::invalidChecksumRequest);
+        DexProgramClass::invalidChecksumRequest,
+        ReachabilitySensitiveValue.DISABLED);
   }
 
   @Override
@@ -204,24 +209,12 @@
    * that is the case, dead reference elimination is disabled and locals are kept alive for their
    * entire scope.
    */
-  public boolean getOrComputeReachabilitySensitive(AppView<?> appView) {
-    if (reachabilitySensitive.isUnknown()) {
-      reachabilitySensitive = OptionalBool.of(internalComputeReachabilitySensitive(appView));
-    }
-    return reachabilitySensitive.isTrue();
+  public boolean isReachabilitySensitive() {
+    return getReachabilitySensitiveValue().isEnabled();
   }
 
-  @SuppressWarnings("ReferenceEquality")
-  private boolean internalComputeReachabilitySensitive(AppView<?> appView) {
-    DexItemFactory dexItemFactory = appView.dexItemFactory();
-    for (DexEncodedMember<?, ?> member : members()) {
-      for (DexAnnotation annotation : member.annotations().annotations) {
-        if (annotation.annotation.type == dexItemFactory.annotationReachabilitySensitive) {
-          return true;
-        }
-      }
-    }
-    return false;
+  public ReachabilitySensitiveValue getReachabilitySensitiveValue() {
+    return reachabilitySensitive;
   }
 
   @Override
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 089194a..57b427e 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -48,10 +48,10 @@
 import com.android.tools.r8.utils.FieldSignatureEquivalence;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.MethodSignatureEquivalence;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import com.android.tools.r8.utils.StringDiagnostic;
 import com.android.tools.r8.utils.StringUtils;
 import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.Iterables;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -258,7 +258,7 @@
     private final List<DexEncodedMethod> directMethods = new ArrayList<>();
     private final List<DexEncodedMethod> virtualMethods = new ArrayList<>();
     private final Set<Wrapper<DexMethod>> methodSignatures = new HashSet<>();
-    private boolean hasReachabilitySensitiveMethod = false;
+    private boolean hasReachabilitySensitiveMember = false;
     private SyntheticMarker syntheticMarker = null;
 
     public CreateDexClassVisitor(
@@ -492,7 +492,6 @@
         addAnnotation(DexAnnotation.createAnnotationDefaultAnnotation(
             type, defaultAnnotations, application.getFactory()));
       }
-      checkReachabilitySensitivity();
       checkRecord();
       T clazz =
           classKind.create(
@@ -517,7 +516,8 @@
               virtualMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
               application.getFactory().getSkipNameValidationForTesting(),
               getChecksumSupplier(classKind),
-              syntheticMarker);
+              syntheticMarker,
+              ReachabilitySensitiveValue.fromBoolean(hasReachabilitySensitiveMember));
       application.checkClassForMethodHandlesLookup(clazz, classKind);
       InnerClassAttribute innerClassAttribute = clazz.getInnerClassAttributeForThisClass();
       // A member class should not be a local or anonymous class.
@@ -599,33 +599,6 @@
       }
     }
 
-    // If anything is marked reachability sensitive, all methods need to be parsed including
-    // locals information. This propagates the reachability sensitivity bit so that if any field
-    // or method is annotated, all methods get parsed with locals information.
-    private void checkReachabilitySensitivity() {
-      if (hasReachabilitySensitiveMethod || hasReachabilitySensitiveField()) {
-        for (DexEncodedMethod method : Iterables.concat(directMethods, virtualMethods)) {
-          Code code = method.getCode();
-          if (code != null && code.isCfCode()) {
-            code.asLazyCfCode().markReachabilitySensitive();
-          }
-        }
-      }
-    }
-
-    @SuppressWarnings("ReferenceEquality")
-    private boolean hasReachabilitySensitiveField() {
-      DexType reachabilitySensitive = application.getFactory().annotationReachabilitySensitive;
-      for (DexEncodedField field : Iterables.concat(instanceFields, staticFields)) {
-        for (DexAnnotation annotation : field.annotations().annotations) {
-          if (annotation.annotation.type == reachabilitySensitive) {
-            return true;
-          }
-        }
-      }
-      return false;
-    }
-
     private void addDefaultAnnotation(String name, DexValue value) {
       if (defaultAnnotations == null) {
         defaultAnnotations = new ArrayList<>();
@@ -718,6 +691,11 @@
             parsingContext,
             parent.application::addKeepDeclaration);
       }
+
+      // Check for reachability sensitive annotation.
+      parent.hasReachabilitySensitiveMember |=
+          parent.application.getFactory().annotationReachabilitySensitiveDesc.equals(desc);
+
       return createAnnotationVisitor(
           desc, visible, getAnnotations(), parent.application, DexAnnotation::new);
     }
@@ -881,6 +859,11 @@
             parsingContext,
             parent.application::addKeepDeclaration);
       }
+
+      // Check for reachability sensitive annotation.
+      parent.hasReachabilitySensitiveMember |=
+          parent.application.getFactory().annotationReachabilitySensitiveDesc.equals(desc);
+
       return createAnnotationVisitor(
           desc, visible, getAnnotations(), parent.application, DexAnnotation::new);
     }
@@ -1030,7 +1013,6 @@
               .build();
       Wrapper<DexMethod> signature = MethodSignatureEquivalence.get().wrap(method);
       if (parent.methodSignatures.add(signature)) {
-        parent.hasReachabilitySensitiveMethod |= isReachabilitySensitive();
         if (flags.isStatic() || flags.isConstructor() || flags.isPrivate()) {
           parent.directMethods.add(dexMethod);
         } else {
@@ -1049,18 +1031,6 @@
       }
     }
 
-    @SuppressWarnings("ReferenceEquality")
-    private boolean isReachabilitySensitive() {
-      DexType reachabilitySensitive =
-          parent.application.getFactory().annotationReachabilitySensitive;
-      for (DexAnnotation annotation : getAnnotations()) {
-        if (annotation.annotation.type == reachabilitySensitive) {
-          return true;
-        }
-      }
-      return false;
-    }
-
     private List<DexAnnotation> getAnnotations() {
       if (annotations == null) {
         annotations = new ArrayList<>();
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index c41f8df..34c1b21 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -73,6 +73,7 @@
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.ExceptionUtils;
 import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.RetracerForCodePrinting;
 import com.android.tools.r8.utils.StringDiagnostic;
@@ -119,12 +120,6 @@
   private JarApplicationReader application;
   private CfCode code;
   private ReparseContext context;
-  private boolean reachabilitySensitive = false;
-
-  public void markReachabilitySensitive() {
-    assert code == null;
-    reachabilitySensitive = true;
-  }
 
   @Override
   public boolean isCfCode() {
@@ -158,11 +153,17 @@
   private void internalParseCode() {
     ReparseContext context = this.context;
     JarApplicationReader application = this.application;
-    assert application != null;
     assert context != null;
+    assert application != null;
+    DexProgramClass programOwner = context.owner.asProgramClass();
+    ReachabilitySensitiveValue reachabilitySensitive =
+        programOwner != null
+            ? programOwner.getReachabilitySensitiveValue()
+            : ReachabilitySensitiveValue.DISABLED;
+    DebugParsingOptions parsingOptions = getParsingOptions(application, reachabilitySensitive);
     // The ClassCodeVisitor is in charge of setting this.context to null.
     try {
-      parseCode(context, false);
+      parseCode(context, false, parsingOptions);
     } catch (JsrEncountered e) {
       for (Code code : context.codeList) {
         code.asLazyCfCode().code = null;
@@ -170,7 +171,7 @@
         code.asLazyCfCode().application = application;
       }
       try {
-        parseCode(context, true);
+        parseCode(context, true, parsingOptions);
       } catch (JsrEncountered e1) {
         throw new Unreachable(e1);
       }
@@ -204,9 +205,8 @@
     }
   }
 
-  public void parseCode(ReparseContext context, boolean useJsrInliner) {
-    DebugParsingOptions parsingOptions = getParsingOptions(application, reachabilitySensitive);
-
+  private void parseCode(
+      ReparseContext context, boolean useJsrInliner, DebugParsingOptions parsingOptions) {
     ClassCodeVisitor classVisitor =
         new ClassCodeVisitor(
             context.owner,
@@ -301,7 +301,8 @@
 
   @Override
   public String toString() {
-    return asCfCode().toString();
+    // Don't force parsing in toString as it causes unexpected behavior when debugging.
+    return code != null ? code.toString() : "<lazy-code>";
   }
 
   @Override
@@ -1177,7 +1178,7 @@
   }
 
   private static DebugParsingOptions getParsingOptions(
-      JarApplicationReader application, boolean reachabilitySensitive) {
+      JarApplicationReader application, ReachabilitySensitiveValue reachabilitySensitive) {
     // TODO(b/166841731): We should compute our own from the compressed format.
     int parsingOptions =
         application.options.canUseInputStackMaps()
@@ -1194,7 +1195,7 @@
         configuration.isKeepParameterNames()
             || keep.localVariableTable
             || keep.localVariableTypeTable
-            || reachabilitySensitive;
+            || reachabilitySensitive.isEnabled();
     boolean lineInfo =
         (keep.lineNumberTable || application.options.canUseNativeDexPcInsteadOfDebugInfo());
     boolean methodParaeters = keep.methodParameters;
diff --git a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
index 03758b2..54dc05d 100644
--- a/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/ProgramMethod.java
@@ -180,8 +180,8 @@
     return getDefinition().getKotlinInfo();
   }
 
-  public boolean getOrComputeReachabilitySensitive(AppView<?> appView) {
-    return getHolder().getOrComputeReachabilitySensitive(appView);
+  public boolean isReachabilitySensitive() {
+    return getHolder().isReachabilitySensitive();
   }
 
   public void setCode(Code newCode, AppView<?> appView) {
@@ -202,7 +202,7 @@
     if (appView.testing().noLocalsTableOnInput) {
       return false;
     }
-    return appView.options().debug || getOrComputeReachabilitySensitive(appView);
+    return appView.options().debug || isReachabilitySensitive();
   }
 
   public ProgramMethod rewrittenWithLens(
diff --git a/src/main/java/com/android/tools/r8/graph/fixup/TreeFixerBase.java b/src/main/java/com/android/tools/r8/graph/fixup/TreeFixerBase.java
index ec65897..9f40e9f 100644
--- a/src/main/java/com/android/tools/r8/graph/fixup/TreeFixerBase.java
+++ b/src/main/java/com/android/tools/r8/graph/fixup/TreeFixerBase.java
@@ -113,7 +113,6 @@
     return newProgramClasses;
   }
 
-  @SuppressWarnings("ReferenceEquality")
   // Should remain private as the correctness of the fixup requires the lazy 'newProgramClasses'.
   private DexProgramClass fixupClass(DexProgramClass clazz) {
     DexProgramClass newClass =
@@ -137,7 +136,8 @@
             DexEncodedField.EMPTY_ARRAY,
             newHolder -> clazz.getMethodCollection().fixup(newHolder, this::fixupMethod),
             dexItemFactory.getSkipNameValidationForTesting(),
-            clazz.getChecksumSupplier());
+            clazz.getChecksumSupplier(),
+            clazz.getReachabilitySensitiveValue());
     newClass.setInstanceFields(fixupFields(clazz.instanceFields()));
     newClass.setStaticFields(fixupFields(clazz.staticFields()));
     // Transfer properties that are not passed to the constructor.
@@ -151,7 +151,7 @@
       newClass.setKotlinInfo(clazz.getKotlinInfo());
     }
     // If the class type changed, record the move in the lens.
-    if (newClass.getType() != clazz.getType()) {
+    if (newClass.getType().isNotIdenticalTo(clazz.getType())) {
       return recordClassChange(clazz, newClass);
     }
     return newClass;
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index 7f7653b..5077746 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -632,7 +632,7 @@
 
   public boolean isConsistentSSABeforeTypesAreCorrectAllowingRedundantBlocks(AppView<?> appView) {
     assert isConsistentGraph(appView, true);
-    assert consistentBlockInstructions(appView, true);
+    assert consistentBlockInstructions(true);
     assert consistentDefUseChains();
     assert validThrowingInstructions();
     assert noCriticalEdges();
@@ -689,7 +689,7 @@
     assert consistentBlockNumbering();
     assert consistentPredecessorSuccessors();
     assert consistentCatchHandlers();
-    assert consistentBlockInstructions(appView, ssa);
+    assert consistentBlockInstructions(ssa);
     assert consistentMetadata();
     assert verifyAllThrowingInstructionsHavePositions();
     return true;
@@ -889,13 +889,11 @@
     return true;
   }
 
-  private boolean consistentBlockInstructions(AppView<?> appView, boolean ssa) {
+  private boolean consistentBlockInstructions(boolean ssa) {
     boolean argumentsAllowed = true;
     for (BasicBlock block : blocks) {
       assert block.consistentBlockInstructions(
-          argumentsAllowed,
-          options.debug || context().getOrComputeReachabilitySensitive(appView),
-          ssa);
+          argumentsAllowed, options.debug || context().isReachabilitySensitive(), ssa);
       argumentsAllowed = false;
     }
     return true;
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index 15082ac..4d73577 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -87,7 +87,7 @@
   public DeadInstructionResult canBeDeadCode(AppView<?> appView, IRCode code) {
     InternalOptions options = appView.options();
     if (options.debug
-        || code.context().getOrComputeReachabilitySensitive(appView)
+        || code.context().isReachabilitySensitive()
         || !code.getConversionOptions().isGeneratingDex()) {
       return DeadInstructionResult.notDead();
     }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index b95529b..8d03811 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -502,7 +502,7 @@
   }
 
   public boolean isDebugMode() {
-    return appView.options().debug || getProgramMethod().getOrComputeReachabilitySensitive(appView);
+    return appView.options().debug || getProgramMethod().isReachabilitySensitive();
   }
 
   public Int2ReferenceSortedMap<BlockInfo> getCFG() {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 733a207..e3e340b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -522,7 +522,7 @@
       previous = printMethod(code, "IR after disable assertions (SSA)", previous);
     }
 
-    boolean isDebugMode = options.debug || context.getOrComputeReachabilitySensitive(appView);
+    boolean isDebugMode = options.debug || context.isReachabilitySensitive();
     assert !method.isProcessed() || !isDebugMode
         : "Method already processed: "
             + context.toSourceString()
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
index c56ddbf..44cf6e7 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
@@ -76,7 +76,7 @@
   }
 
   protected boolean isDebugMode(ProgramMethod context) {
-    return options.debug || context.getOrComputeReachabilitySensitive(appView);
+    return options.debug || context.isReachabilitySensitive();
   }
 
   protected abstract String getRewriterId();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
index 8de8311..604299b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/EmulatedInterfaceApplicationRewriter.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.graph.MethodCollection.MethodCollectionFactory;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.utils.IterableUtils;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.IdentityHashMap;
@@ -89,7 +90,8 @@
             DexEncodedField.EMPTY_ARRAY,
             MethodCollectionFactory.fromMethods(newDirectMethods, newVirtualMethods),
             false,
-            emulatedInterface.getChecksumSupplier());
+            emulatedInterface.getChecksumSupplier(),
+            ReachabilitySensitiveValue.DISABLED);
     newEmulatedInterface.addExtraInterfaces(
         getRewrittenInterfacesOfEmulatedInterface(emulatedInterface), appView.dexItemFactory());
     return newEmulatedInterface;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index c6d8ac4..b6804e7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -151,7 +151,7 @@
     }
 
     ProgramMethod context = code.context();
-    if (context.getOrComputeReachabilitySensitive(appView)) {
+    if (context.isReachabilitySensitive()) {
       return ClassInitializerDefaultsResult.empty();
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 3d78982..4b9c547 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -160,7 +160,7 @@
     }
     ProgramMethod method = code.context();
     DexEncodedMethod definition = method.getDefinition();
-    if (definition.isClassInitializer() || method.getOrComputeReachabilitySensitive(appView)) {
+    if (definition.isClassInitializer() || method.isReachabilitySensitive()) {
       return ConstraintWithTarget.NEVER;
     }
     KeepMethodInfo keepInfo = appView.getKeepInfo(method);
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index 2acd209..c099750 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -233,7 +233,7 @@
     // and we do not actually want locals information in the output.
     if (options().debug) {
       computeDebugInfo(code, blocks, liveIntervals, this, liveAtEntrySets);
-    } else if (code.context().getOrComputeReachabilitySensitive(appView)) {
+    } else if (code.context().isReachabilitySensitive()) {
       InstructionListIterator it = code.instructionListIterator();
       while (it.hasNext()) {
         Instruction instruction = it.next();
@@ -1661,7 +1661,7 @@
     // Set all free positions for possible registers to max integer.
     RegisterPositions freePositions = new RegisterPositionsImpl(registerConstraint + 1);
 
-    if ((options().debug || code.context().getOrComputeReachabilitySensitive(appView))
+    if ((options().debug || code.context().isReachabilitySensitive())
         && !code.method().accessFlags.isStatic()) {
       // If we are generating debug information or if the method is reachability sensitive,
       // we pin the this value register. The debugger expects to always be able to find it in
@@ -2712,7 +2712,7 @@
             }
           }
         }
-        if (appView.options().debug || code.context().getOrComputeReachabilitySensitive(appView)) {
+        if (appView.options().debug || code.context().isReachabilitySensitive()) {
           // In debug mode, or if the method is reachability sensitive, extend the live range
           // to cover the full scope of a local variable (encoded as debug values).
           int number = instruction.getNumber();
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
index 8eac490..af43714 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracingImpl.java
@@ -97,7 +97,7 @@
     }
 
     // If the access is from a reachability sensitive method, then bail out.
-    if (context.getHolder().getOrComputeReachabilitySensitive(appView)) {
+    if (context.getHolder().isReachabilitySensitive()) {
       return enqueueDeferredEnqueuerActions(field);
     }
 
diff --git a/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerFactory.java b/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerFactory.java
index e33a5fa..3354e65 100644
--- a/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerFactory.java
+++ b/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerFactory.java
@@ -32,6 +32,7 @@
 import com.android.tools.r8.graph.NestHostClassAttribute;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import com.google.common.collect.ImmutableList;
 import java.util.Collections;
 
@@ -58,7 +59,8 @@
         MethodCollectionFactory.fromMethods(
             createDirectMethods(dexItemFactory), createVirtualMethods(dexItemFactory)),
         dexItemFactory.getSkipNameValidationForTesting(),
-        DexProgramClass::invalidChecksumRequest);
+        DexProgramClass::invalidChecksumRequest,
+        ReachabilitySensitiveValue.DISABLED);
   }
 
   private static DexEncodedField[] createInstanceFields() {
diff --git a/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerImplFactory.java b/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerImplFactory.java
index f6d1bf4..a70f457 100644
--- a/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerImplFactory.java
+++ b/src/main/java/com/android/tools/r8/startup/generated/InstrumentationServerImplFactory.java
@@ -51,6 +51,7 @@
 import com.android.tools.r8.ir.code.MonitorType;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import com.google.common.collect.ImmutableList;
 import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap;
 import java.util.ArrayDeque;
@@ -80,7 +81,8 @@
         MethodCollectionFactory.fromMethods(
             createDirectMethods(dexItemFactory), createVirtualMethods(dexItemFactory)),
         dexItemFactory.getSkipNameValidationForTesting(),
-        DexProgramClass::invalidChecksumRequest);
+        DexProgramClass::invalidChecksumRequest,
+        ReachabilitySensitiveValue.DISABLED);
   }
 
   private static DexEncodedField[] createInstanceFields(DexItemFactory dexItemFactory) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
index 068a1a7..3340e46 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
@@ -25,6 +25,7 @@
 import com.android.tools.r8.graph.RecordComponentInfo;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -214,7 +215,8 @@
                 DexEncodedMethod.EMPTY_ARRAY,
                 factory.getSkipNameValidationForTesting(),
                 c -> checksum,
-                null);
+                null,
+                ReachabilitySensitiveValue.DISABLED);
     if (useSortedMethodBacking) {
       clazz.getMethodCollection().useSortedBacking();
     }
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index bbfe77c..62bd8a2 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -924,12 +924,12 @@
 
   public boolean debug = false;
 
-  public boolean shouldCompileMethodInDebugMode(AppView<?> appView, ProgramMethod method) {
-    return debug || method.getOrComputeReachabilitySensitive(appView);
+  public boolean shouldCompileMethodInDebugMode(ProgramMethod method) {
+    return debug || method.isReachabilitySensitive();
   }
 
   public boolean shouldCompileMethodInReleaseMode(AppView<?> appView, ProgramMethod method) {
-    return !shouldCompileMethodInDebugMode(appView, method);
+    return !shouldCompileMethodInDebugMode(method);
   }
 
   private final AccessModifierOptions accessModifierOptions = new AccessModifierOptions(this);
diff --git a/src/main/java/com/android/tools/r8/utils/ReachabilitySensitiveValue.java b/src/main/java/com/android/tools/r8/utils/ReachabilitySensitiveValue.java
new file mode 100644
index 0000000..efdddc8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/ReachabilitySensitiveValue.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2024, 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.utils;
+
+public enum ReachabilitySensitiveValue {
+  DISABLED,
+  ENABLED;
+
+  public static ReachabilitySensitiveValue fromBoolean(boolean enabled) {
+    return enabled ? ENABLED : DISABLED;
+  }
+
+  public boolean isEnabled() {
+    return this == ENABLED;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java b/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
index c7c00b8..6499f3d 100644
--- a/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.conversion.callgraph.Node;
 import com.android.tools.r8.origin.SynthesizedOrigin;
+import com.android.tools.r8.utils.ReachabilitySensitiveValue;
 import java.util.Collections;
 
 class CallGraphTestBase extends TestBase {
@@ -44,7 +45,8 @@
           DexEncodedField.EMPTY_ARRAY,
           MethodCollectionFactory.empty(),
           false,
-          DexProgramClass::invalidChecksumRequest);
+          DexProgramClass::invalidChecksumRequest,
+          ReachabilitySensitiveValue.DISABLED);
 
   Node createNode(String methodName) {
     DexMethod signature =