Make shallow abstractValueSupplier a singleton

Change-Id: I6b324cf2d928108e3fc685f2522248fda496db19
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java b/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java
index 892ff11..5fb46a9 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/constant/SparseConditionalConstantPropagation.java
@@ -6,8 +6,10 @@
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
 import com.android.tools.r8.ir.analysis.value.AbstractValueJoiner.AbstractValueConstantPropagationJoiner;
+import com.android.tools.r8.ir.code.AbstractValueSupplier;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.ConstNumber;
 import com.android.tools.r8.ir.code.IRCode;
@@ -67,7 +69,7 @@
     return new SparseConditionalConstantPropagationOnCode(code).analyze().run();
   }
 
-  private class SparseConditionalConstantPropagationOnCode {
+  private class SparseConditionalConstantPropagationOnCode implements AbstractValueSupplier {
 
     private final IRCode code;
     private final Map<Value, AbstractValue> mapping = new IdentityHashMap<>();
@@ -170,8 +172,7 @@
                   InstructionListIterator iterator = block.listIterator();
                   iterator.nextUntil(i -> i == definition);
                   if (!definition.isArgument()
-                      && !definition.instructionMayHaveSideEffects(
-                          appView, code.context(), this::getCachedAbstractValue)) {
+                      && !definition.instructionMayHaveSideEffects(appView, code.context(), this)) {
                     ConstNumber replacement =
                         ConstNumber.builder().setOutValue(value).setValue(constValue).build();
                     iterator.replaceCurrentInstruction(replacement, affectedValues);
@@ -245,8 +246,7 @@
               code.context().getOptimizationInfo().getArgumentInfos();
           value = argumentInfos.getAbstractArgumentValue(index);
         } else {
-          value =
-              instruction.getAbstractValue(appView, code.context(), this::getCachedAbstractValue);
+          value = instruction.getAbstractValue(appView, code.context(), this);
         }
         AbstractValue previousValue = getCachedAbstractValue(instruction.outValue());
         assert joiner.lessThanOrEqualTo(previousValue, value, instruction.getOutType());
@@ -359,5 +359,10 @@
       }
       return previousExecutable.get(from);
     }
+
+    @Override
+    public AbstractValue getAbstractValue(Value value, AppView<?> appView, ProgramMethod context) {
+      return getCachedAbstractValue(value);
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/AbstractValueSupplier.java b/src/main/java/com/android/tools/r8/ir/code/AbstractValueSupplier.java
index 757d5d7..d6e40ed 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AbstractValueSupplier.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AbstractValueSupplier.java
@@ -10,29 +10,23 @@
 
 public interface AbstractValueSupplier {
 
-  UnknownAbstractValueSupplier UNKNOWN = new UnknownAbstractValueSupplier();
+  AbstractValueSupplier UNKNOWN = (value, appView, context) -> AbstractValue.unknown();
+  AbstractValueSupplier SHALLOW =
+      (value, appView, context) -> value.getAbstractValue(appView, context, unknown());
 
-  AbstractValue getAbstractValue(Value value);
+  AbstractValue getAbstractValue(Value value, AppView<?> appView, ProgramMethod context);
 
   /**
-   * Returns an {@link AbstractValueSupplier} that supplies a {@link UnknownAbstractValueSupplier}
-   * in the recursive call to {@link Value#getAbstractValue}, so that a shallow value is computed.
-   * This is to prevent that computing the abstract value can end up evaluating large arithmetic
-   * expressions, which should ideally only be done during constant propagation.
+   * Returns an {@link AbstractValueSupplier} that supplies UNKNOWN in the recursive call to {@link
+   * Value#getAbstractValue}, so that a shallow value is computed. This is to prevent that computing
+   * the abstract value can end up evaluating large arithmetic expressions, which should ideally
+   * only be done during constant propagation.
    */
-  static AbstractValueSupplier getShallow(AppView<?> appView, ProgramMethod context) {
-    return value -> value.getAbstractValue(appView, context, unknown());
+  static AbstractValueSupplier shallow() {
+    return SHALLOW;
   }
 
-  static UnknownAbstractValueSupplier unknown() {
+  static AbstractValueSupplier unknown() {
     return UNKNOWN;
   }
-
-  class UnknownAbstractValueSupplier implements AbstractValueSupplier {
-
-    @Override
-    public AbstractValue getAbstractValue(Value value) {
-      return AbstractValue.unknown();
-    }
-  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
index 654aff1..fd16968 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
@@ -136,8 +136,10 @@
     if (outValue.hasLocalInfo()) {
       return AbstractValue.unknown();
     }
-    AbstractValue leftAbstractValue = abstractValueSupplier.getAbstractValue(leftValue());
-    AbstractValue rightAbstractValue = abstractValueSupplier.getAbstractValue(rightValue());
+    AbstractValue leftAbstractValue =
+        abstractValueSupplier.getAbstractValue(leftValue(), appView, context);
+    AbstractValue rightAbstractValue =
+        abstractValueSupplier.getAbstractValue(rightValue(), appView, context);
     if (leftAbstractValue.isSingleNumberValue() && rightAbstractValue.isSingleNumberValue()) {
       SingleNumberValue leftConst = leftAbstractValue.asSingleNumberValue();
       SingleNumberValue rightConst = rightAbstractValue.asSingleNumberValue();
diff --git a/src/main/java/com/android/tools/r8/ir/code/Cmp.java b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
index fae64e1..b9d83f71 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Cmp.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
@@ -165,8 +165,10 @@
     if (outValue.hasLocalInfo()) {
       return AbstractValue.unknown();
     }
-    AbstractValue leftAbstractValue = abstractValueSupplier.getAbstractValue(leftValue());
-    AbstractValue rightAbstractValue = abstractValueSupplier.getAbstractValue(rightValue());
+    AbstractValue leftAbstractValue =
+        abstractValueSupplier.getAbstractValue(leftValue(), appView, context);
+    AbstractValue rightAbstractValue =
+        abstractValueSupplier.getAbstractValue(rightValue(), appView, context);
     if (leftAbstractValue.isSingleNumberValue() && rightAbstractValue.isSingleNumberValue()) {
       SingleNumberValue leftConst = leftAbstractValue.asSingleNumberValue();
       SingleNumberValue rightConst = rightAbstractValue.asSingleNumberValue();
diff --git a/src/main/java/com/android/tools/r8/ir/code/Div.java b/src/main/java/com/android/tools/r8/ir/code/Div.java
index 6325179..f5c5593 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Div.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Div.java
@@ -140,7 +140,8 @@
     if (!instructionTypeCanThrow()) {
       return false;
     }
-    AbstractValue rightAbstractValue = abstractValueSupplier.getAbstractValue(rightValue());
+    AbstractValue rightAbstractValue =
+        abstractValueSupplier.getAbstractValue(rightValue(), appView, context);
     if (rightAbstractValue.isSingleNumberValue() && !rightAbstractValue.isZero()) {
       return false;
     }
@@ -159,7 +160,8 @@
   @Override
   public AbstractValue getAbstractValue(
       AppView<?> appView, ProgramMethod context, AbstractValueSupplier abstractValueSupplier) {
-    AbstractValue rightAbstractValue = abstractValueSupplier.getAbstractValue(rightValue());
+    AbstractValue rightAbstractValue =
+        abstractValueSupplier.getAbstractValue(rightValue(), appView, context);
     if (!rightAbstractValue.isZero()) {
       return super.getAbstractValue(appView, context, abstractValueSupplier);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index d200922..565e62f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -641,8 +641,7 @@
   }
 
   public final boolean instructionMayHaveSideEffects(AppView<?> appView, ProgramMethod context) {
-    return instructionMayHaveSideEffects(
-        appView, context, AbstractValueSupplier.getShallow(appView, context));
+    return instructionMayHaveSideEffects(appView, context, AbstractValueSupplier.shallow());
   }
 
   public final boolean instructionMayHaveSideEffects(
@@ -654,7 +653,7 @@
   public final boolean instructionMayHaveSideEffects(
       AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
     return instructionMayHaveSideEffects(
-        appView, context, AbstractValueSupplier.getShallow(appView, context), assumption);
+        appView, context, AbstractValueSupplier.shallow(), assumption);
   }
 
   public boolean instructionMayHaveSideEffects(
@@ -673,8 +672,7 @@
       AppView<?> appView, ProgramMethod context);
 
   public final boolean instructionInstanceCanThrow(AppView<?> appView, ProgramMethod context) {
-    return instructionInstanceCanThrow(
-        appView, context, AbstractValueSupplier.getShallow(appView, context));
+    return instructionInstanceCanThrow(appView, context, AbstractValueSupplier.shallow());
   }
 
   public final boolean instructionInstanceCanThrow(
@@ -686,7 +684,7 @@
   public final boolean instructionInstanceCanThrow(
       AppView<?> appView, ProgramMethod context, SideEffectAssumption assumption) {
     return instructionInstanceCanThrow(
-        appView, context, AbstractValueSupplier.getShallow(appView, context), assumption);
+        appView, context, AbstractValueSupplier.shallow(), assumption);
   }
 
   public boolean instructionInstanceCanThrow(
diff --git a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
index a197004..47a0470 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
@@ -113,8 +113,10 @@
     if (outValue.hasLocalInfo()) {
       return AbstractValue.unknown();
     }
-    AbstractValue leftAbstractValue = abstractValueSupplier.getAbstractValue(leftValue());
-    AbstractValue rightAbstractValue = abstractValueSupplier.getAbstractValue(rightValue());
+    AbstractValue leftAbstractValue =
+        abstractValueSupplier.getAbstractValue(leftValue(), appView, context);
+    AbstractValue rightAbstractValue =
+        abstractValueSupplier.getAbstractValue(rightValue(), appView, context);
     if (leftAbstractValue.isSingleNumberValue() && rightAbstractValue.isSingleNumberValue()) {
       SingleNumberValue leftConst = leftAbstractValue.asSingleNumberValue();
       SingleNumberValue rightConst = rightAbstractValue.asSingleNumberValue();
diff --git a/src/main/java/com/android/tools/r8/ir/code/Neg.java b/src/main/java/com/android/tools/r8/ir/code/Neg.java
index 46b1c59..b578927 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Neg.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Neg.java
@@ -89,7 +89,8 @@
     if (outValue.hasLocalInfo()) {
       return AbstractValue.unknown();
     }
-    AbstractValue sourceLattice = abstractValueSupplier.getAbstractValue(source());
+    AbstractValue sourceLattice =
+        abstractValueSupplier.getAbstractValue(source(), appView, context);
     if (sourceLattice.isSingleNumberValue()) {
       SingleNumberValue sourceConst = sourceLattice.asSingleNumberValue();
       long newConst;
diff --git a/src/main/java/com/android/tools/r8/ir/code/Not.java b/src/main/java/com/android/tools/r8/ir/code/Not.java
index 2a98b81..09901ea 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Not.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Not.java
@@ -46,7 +46,8 @@
     if (outValue.hasLocalInfo()) {
       return AbstractValue.unknown();
     }
-    AbstractValue sourceLattice = abstractValueSupplier.getAbstractValue(source());
+    AbstractValue sourceLattice =
+        abstractValueSupplier.getAbstractValue(source(), appView, context);
     if (sourceLattice.isSingleNumberValue()) {
       SingleNumberValue sourceConst = sourceLattice.asSingleNumberValue();
       long newConst;
diff --git a/src/main/java/com/android/tools/r8/ir/code/Rem.java b/src/main/java/com/android/tools/r8/ir/code/Rem.java
index fae9c59..3c53f35 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Rem.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Rem.java
@@ -139,7 +139,8 @@
     if (!instructionTypeCanThrow()) {
       return false;
     }
-    AbstractValue rightAbstractValue = abstractValueSupplier.getAbstractValue(rightValue());
+    AbstractValue rightAbstractValue =
+        abstractValueSupplier.getAbstractValue(rightValue(), appView, context);
     if (rightAbstractValue.isSingleNumberValue() && !rightAbstractValue.isZero()) {
       return false;
     }
@@ -161,7 +162,8 @@
     if (outValue.hasLocalInfo()) {
       return AbstractValue.unknown();
     }
-    AbstractValue rightLattice = abstractValueSupplier.getAbstractValue(rightValue());
+    AbstractValue rightLattice =
+        abstractValueSupplier.getAbstractValue(rightValue(), appView, context);
     if (!rightLattice.isZero()) {
       return super.getAbstractValue(appView, context, abstractValueSupplier);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index 91477cd..fd48de4 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -213,8 +213,7 @@
           feedback.methodReturnsArgument(method, definition.asArgument().getIndex());
         }
         AbstractValue abstractReturnValue =
-            definition.getAbstractValue(
-                appView, context, AbstractValueSupplier.getShallow(appView, context));
+            definition.getAbstractValue(appView, context, AbstractValueSupplier.shallow());
         if (abstractReturnValue.isNonTrivial()) {
           feedback.methodReturnsAbstractValue(method, appView, abstractReturnValue);
           if (checkCastAndInstanceOfMethodSpecialization != null) {
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
index 0b5d053..898b72d 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagator.java
@@ -131,8 +131,6 @@
       ProgramMethod method, IRCode code, MethodProcessor methodProcessor, Timing timing) {
     if (codeScanner != null) {
       assert methodProcessor.isPrimaryMethodProcessor();
-      AbstractValueSupplier abstractValueSupplier =
-          value -> value.getAbstractValue(appView, method);
       PathConstraintSupplier pathConstraintSupplier =
           new PathConstraintSupplier(
               appView,
@@ -140,7 +138,12 @@
               codeScanner.getFieldValueFactory(),
               codeScanner.getMethodParameterFactory());
       codeScanner.scan(
-          method, code, methodProcessor, abstractValueSupplier, pathConstraintSupplier, timing);
+          method,
+          code,
+          methodProcessor,
+          AbstractValueSupplier.shallow(),
+          pathConstraintSupplier,
+          timing);
 
       assert effectivelyUnusedArgumentsAnalysis != null;
       effectivelyUnusedArgumentsAnalysis.scan(method, code, pathConstraintSupplier);
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
index 516f0e2..5f33057 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorCodeScanner.java
@@ -369,7 +369,7 @@
         return ConcreteArrayTypeValueState.create(nullability);
       }
 
-      AbstractValue abstractValue = abstractValueSupplier.getAbstractValue(value);
+      AbstractValue abstractValue = abstractValueSupplier.getAbstractValue(value, appView, context);
       if (abstractValue.isUnknown()) {
         abstractValue =
             getFallbackAbstractValueForField(
@@ -1006,7 +1006,7 @@
         return ConcreteArrayTypeValueState.create(nullability);
       }
 
-      AbstractValue abstractValue = abstractValueSupplier.getAbstractValue(value);
+      AbstractValue abstractValue = abstractValueSupplier.getAbstractValue(value, appView, context);
 
       // For class types, we track both the abstract value and the dynamic type. If both are
       // unknown, then use UnknownParameterState.