Merge OptimizationInfo booleans into 1 int

- UpdatableOptimization info is shown as using a lot of memory
  on profiles, while it has 13 boolean fields. Merge those into
  a single int field.

Bug: 146188082
Change-Id: I239392a8e68a2e194366e0523a7917a2e1f06a12
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
index d599a38..def162e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
@@ -14,24 +14,16 @@
 import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
 import com.android.tools.r8.ir.optimize.info.initializer.DefaultInstanceInitializerInfo;
 import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
+import com.android.tools.r8.utils.BooleanUtils;
 import java.util.BitSet;
 import java.util.Set;
 import java.util.function.Function;
 
 public class UpdatableMethodOptimizationInfo implements MethodOptimizationInfo {
 
-  private boolean cannotBeKept = false;
-  private boolean classInitializerMayBePostponed = false;
-  private boolean hasBeenInlinedIntoSingleCallSite = false;
   private Set<DexType> initializedClassesOnNormalExit =
       DefaultMethodOptimizationInfo.UNKNOWN_INITIALIZED_CLASSES_ON_NORMAL_EXIT;
   private int returnedArgument = DefaultMethodOptimizationInfo.UNKNOWN_RETURNED_ARGUMENT;
-  private boolean mayHaveSideEffects = DefaultMethodOptimizationInfo.UNKNOWN_MAY_HAVE_SIDE_EFFECTS;
-  private boolean returnValueOnlyDependsOnArguments =
-      DefaultMethodOptimizationInfo.UNKNOWN_RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS;
-  private boolean neverReturnsNull = DefaultMethodOptimizationInfo.UNKNOWN_NEVER_RETURNS_NULL;
-  private boolean neverReturnsNormally =
-      DefaultMethodOptimizationInfo.UNKNOWN_NEVER_RETURNS_NORMALLY;
   private AbstractValue abstractReturnValue =
       DefaultMethodOptimizationInfo.UNKNOWN_ABSTRACT_RETURN_VALUE;
   private TypeLatticeElement returnsObjectWithUpperBoundType =
@@ -39,20 +31,12 @@
   private ClassTypeLatticeElement returnsObjectWithLowerBoundType =
       DefaultMethodOptimizationInfo.UNKNOWN_CLASS_TYPE;
   private InlinePreference inlining = InlinePreference.Default;
-  private boolean useIdentifierNameString =
-      DefaultMethodOptimizationInfo.DOES_NOT_USE_IDENTIFIER_NAME_STRING;
-  private boolean checksNullReceiverBeforeAnySideEffect =
-      DefaultMethodOptimizationInfo.UNKNOWN_CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT;
-  private boolean triggersClassInitBeforeAnySideEffect =
-      DefaultMethodOptimizationInfo.UNKNOWN_TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT;
   // Stores information about instance methods and constructors for
   // class inliner, null value indicates that the method is not eligible.
   private ClassInlinerEligibilityInfo classInlinerEligibility =
       DefaultMethodOptimizationInfo.UNKNOWN_CLASS_INLINER_ELIGIBILITY;
   private InstanceInitializerInfo instanceInitializerInfo =
       DefaultInstanceInitializerInfo.getInstance();
-  private boolean initializerEnablingJavaAssertions =
-      DefaultMethodOptimizationInfo.UNKNOWN_INITIALIZER_ENABLING_JAVA_ASSERTIONS;
   private ParameterUsagesInfo parametersUsages =
       DefaultMethodOptimizationInfo.UNKNOWN_PARAMETER_USAGE_INFO;
   // Stores information about nullability hint per parameter. If set, that means, the method
@@ -73,8 +57,69 @@
   // Note that this bit set takes into account the receiver for instance methods.
   private BitSet nonNullParamOnNormalExits =
       DefaultMethodOptimizationInfo.NO_NULL_PARAMETER_ON_NORMAL_EXITS_FACTS;
-  private boolean reachabilitySensitive = false;
-  private boolean returnValueHasBeenPropagated = false;
+
+  // To reduce the memory footprint of UpdatableMethodOptimizationInfo, all the boolean fields are
+  // merged into a flag int field. The various static final FLAG fields indicate which bit is
+  // used by each boolean. DEFAULT_FLAGS encodes the default value for efficient instantiation and
+  // is computed during class initialization from the default method optimization info. The
+  // methods setFlag, clearFlag and isFlagSet are used to access the booleans.
+  private static final int CANNOT_BE_KEPT_FLAG = 0x1;
+  private static final int CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG = 0x2;
+  private static final int HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG = 0x4;
+  private static final int MAY_HAVE_SIDE_EFFECT_FLAG = 0x8;
+  private static final int RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG = 0x10;
+  private static final int NEVER_RETURNS_NULL_FLAG = 0x20;
+  private static final int NEVER_RETURNS_NORMALLY_FLAG = 0x40;
+  private static final int USE_IDENTIFIER_NAME_STRING_FLAG = 0x80;
+  private static final int CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG = 0x100;
+  private static final int TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG = 0x200;
+  private static final int INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG = 0x400;
+  private static final int REACHABILITY_SENSITIVE_FLAG = 0x800;
+  private static final int RETURN_VALUE_HAS_BEEN_PROPAGATED_FLAG = 0x1000;
+
+  private static final int DEFAULT_FLAGS;
+
+  static {
+    int defaultFlags = 0;
+    MethodOptimizationInfo defaultOptInfo = DefaultMethodOptimizationInfo.DEFAULT_INSTANCE;
+    defaultFlags |= BooleanUtils.intValue(defaultOptInfo.cannotBeKept()) * CANNOT_BE_KEPT_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.classInitializerMayBePostponed())
+            * CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.hasBeenInlinedIntoSingleCallSite())
+            * HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.mayHaveSideEffects()) * MAY_HAVE_SIDE_EFFECT_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.returnValueOnlyDependsOnArguments())
+            * RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.neverReturnsNull()) * NEVER_RETURNS_NULL_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.neverReturnsNormally()) * NEVER_RETURNS_NORMALLY_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.useIdentifierNameString())
+            * USE_IDENTIFIER_NAME_STRING_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.checksNullReceiverBeforeAnySideEffect())
+            * CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.triggersClassInitBeforeAnySideEffect())
+            * TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.isInitializerEnablingJavaAssertions())
+            * INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.isReachabilitySensitive())
+            * REACHABILITY_SENSITIVE_FLAG;
+    defaultFlags |=
+        BooleanUtils.intValue(defaultOptInfo.returnValueHasBeenPropagated())
+            * RETURN_VALUE_HAS_BEEN_PROPAGATED_FLAG;
+    DEFAULT_FLAGS = defaultFlags;
+  }
+
+  private int flags = DEFAULT_FLAGS;
 
   UpdatableMethodOptimizationInfo() {
     // Intentionally left empty, just use the default values.
@@ -83,30 +128,18 @@
   // Copy constructor used to create a mutable copy. Do not forget to copy from template when a new
   // field is added.
   private UpdatableMethodOptimizationInfo(UpdatableMethodOptimizationInfo template) {
-    cannotBeKept = template.cannotBeKept;
-    classInitializerMayBePostponed = template.classInitializerMayBePostponed;
-    hasBeenInlinedIntoSingleCallSite = template.hasBeenInlinedIntoSingleCallSite;
+    flags = template.flags;
     initializedClassesOnNormalExit = template.initializedClassesOnNormalExit;
     returnedArgument = template.returnedArgument;
-    mayHaveSideEffects = template.mayHaveSideEffects;
-    returnValueOnlyDependsOnArguments = template.returnValueOnlyDependsOnArguments;
-    neverReturnsNull = template.neverReturnsNull;
-    neverReturnsNormally = template.neverReturnsNormally;
     abstractReturnValue = template.abstractReturnValue;
     returnsObjectWithUpperBoundType = template.returnsObjectWithUpperBoundType;
     returnsObjectWithLowerBoundType = template.returnsObjectWithLowerBoundType;
     inlining = template.inlining;
-    useIdentifierNameString = template.useIdentifierNameString;
-    checksNullReceiverBeforeAnySideEffect = template.checksNullReceiverBeforeAnySideEffect;
-    triggersClassInitBeforeAnySideEffect = template.triggersClassInitBeforeAnySideEffect;
     classInlinerEligibility = template.classInlinerEligibility;
     instanceInitializerInfo = template.instanceInitializerInfo;
-    initializerEnablingJavaAssertions = template.initializerEnablingJavaAssertions;
     parametersUsages = template.parametersUsages;
     nonNullParamOrThrow = template.nonNullParamOrThrow;
     nonNullParamOnNormalExits = template.nonNullParamOnNormalExits;
-    reachabilitySensitive = template.reachabilitySensitive;
-    returnValueHasBeenPropagated = template.returnValueHasBeenPropagated;
   }
 
   public void fixupClassTypeReferences(
@@ -121,6 +154,26 @@
     }
   }
 
+  private void setFlag(int flag, boolean value) {
+    if (value) {
+      setFlag(flag);
+    } else {
+      clearFlag(flag);
+    }
+  }
+
+  private void setFlag(int flag) {
+    flags |= flag;
+  }
+
+  private void clearFlag(int flag) {
+    flags &= ~flag;
+  }
+
+  private boolean isFlagSet(int flag) {
+    return (flags & flag) != 0;
+  }
+
   @Override
   public boolean isDefaultMethodOptimizationInfo() {
     return false;
@@ -138,21 +191,21 @@
 
   @Override
   public boolean cannotBeKept() {
-    return cannotBeKept;
+    return isFlagSet(CANNOT_BE_KEPT_FLAG);
   }
 
   // TODO(b/140214568): Should be package-private.
   public void markCannotBeKept() {
-    cannotBeKept = true;
+    setFlag(CANNOT_BE_KEPT_FLAG);
   }
 
   @Override
   public boolean classInitializerMayBePostponed() {
-    return classInitializerMayBePostponed;
+    return isFlagSet(CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG);
   }
 
   void markClassInitializerMayBePostponed() {
-    classInitializerMayBePostponed = true;
+    setFlag(CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG);
   }
 
   @Override
@@ -192,16 +245,16 @@
 
   @Override
   public boolean hasBeenInlinedIntoSingleCallSite() {
-    return hasBeenInlinedIntoSingleCallSite;
+    return isFlagSet(HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG);
   }
 
   void markInlinedIntoSingleCallSite() {
-    hasBeenInlinedIntoSingleCallSite = true;
+    setFlag(HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG);
   }
 
   @Override
   public boolean isReachabilitySensitive() {
-    return reachabilitySensitive;
+    return isFlagSet(REACHABILITY_SENSITIVE_FLAG);
   }
 
   @Override
@@ -217,12 +270,12 @@
 
   @Override
   public boolean neverReturnsNull() {
-    return neverReturnsNull;
+    return isFlagSet(NEVER_RETURNS_NULL_FLAG);
   }
 
   @Override
   public boolean neverReturnsNormally() {
-    return neverReturnsNormally;
+    return isFlagSet(NEVER_RETURNS_NORMALLY_FLAG);
   }
 
   @Override
@@ -237,12 +290,12 @@
 
   @Override
   public boolean isInitializerEnablingJavaAssertions() {
-    return initializerEnablingJavaAssertions;
+    return isFlagSet(INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG);
   }
 
   @Override
   public boolean useIdentifierNameString() {
-    return useIdentifierNameString;
+    return isFlagSet(USE_IDENTIFIER_NAME_STRING_FLAG);
   }
 
   @Override
@@ -257,22 +310,22 @@
 
   @Override
   public boolean checksNullReceiverBeforeAnySideEffect() {
-    return checksNullReceiverBeforeAnySideEffect;
+    return isFlagSet(CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG);
   }
 
   @Override
   public boolean triggersClassInitBeforeAnySideEffect() {
-    return triggersClassInitBeforeAnySideEffect;
+    return isFlagSet(TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG);
   }
 
   @Override
   public boolean mayHaveSideEffects() {
-    return mayHaveSideEffects;
+    return isFlagSet(MAY_HAVE_SIDE_EFFECT_FLAG);
   }
 
   @Override
   public boolean returnValueOnlyDependsOnArguments() {
-    return returnValueOnlyDependsOnArguments;
+    return isFlagSet(RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG);
   }
 
   void setParameterUsages(ParameterUsagesInfo parametersUsages) {
@@ -288,7 +341,7 @@
   }
 
   public void setReachabilitySensitive(boolean reachabilitySensitive) {
-    this.reachabilitySensitive = reachabilitySensitive;
+    setFlag(REACHABILITY_SENSITIVE_FLAG, reachabilitySensitive);
   }
 
   void setClassInlinerEligibility(ClassInlinerEligibilityInfo eligibility) {
@@ -300,7 +353,7 @@
   }
 
   void setInitializerEnablingJavaAssertions() {
-    this.initializerEnablingJavaAssertions = true;
+    setFlag(INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG);
   }
 
   void markInitializesClassesOnNormalExit(Set<DexType> initializedClassesOnNormalExit) {
@@ -314,19 +367,19 @@
   }
 
   void markMayNotHaveSideEffects() {
-    mayHaveSideEffects = false;
+    clearFlag(MAY_HAVE_SIDE_EFFECT_FLAG);
   }
 
   void markReturnValueOnlyDependsOnArguments() {
-    returnValueOnlyDependsOnArguments = true;
+    setFlag(RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG);
   }
 
   void markNeverReturnsNull() {
-    neverReturnsNull = true;
+    setFlag(NEVER_RETURNS_NULL_FLAG);
   }
 
   void markNeverReturnsNormally() {
-    neverReturnsNormally = true;
+    setFlag(NEVER_RETURNS_NORMALLY_FLAG);
   }
 
   void markReturnsAbstractValue(AbstractValue value) {
@@ -385,25 +438,25 @@
 
   // TODO(b/140214568): Should be package-private.
   public void markUseIdentifierNameString() {
-    useIdentifierNameString = true;
+    setFlag(USE_IDENTIFIER_NAME_STRING_FLAG);
   }
 
   void markCheckNullReceiverBeforeAnySideEffect(boolean mark) {
-    checksNullReceiverBeforeAnySideEffect = mark;
+    setFlag(CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT_FLAG, mark);
   }
 
   void markTriggerClassInitBeforeAnySideEffect(boolean mark) {
-    triggersClassInitBeforeAnySideEffect = mark;
+    setFlag(TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT_FLAG, mark);
   }
 
   // TODO(b/140214568): Should be package-private.
   public void markAsPropagated() {
-    returnValueHasBeenPropagated = true;
+    setFlag(RETURN_VALUE_HAS_BEEN_PROPAGATED_FLAG);
   }
 
   @Override
   public boolean returnValueHasBeenPropagated() {
-    return returnValueHasBeenPropagated;
+    return isFlagSet(RETURN_VALUE_HAS_BEEN_PROPAGATED_FLAG);
   }
 
   @Override
@@ -415,9 +468,9 @@
   public void adjustOptimizationInfoAfterRemovingThisParameter() {
     // cannotBeKept: doesn't depend on `this`
     // classInitializerMayBePostponed: `this` could trigger <clinit> of the previous holder.
-    classInitializerMayBePostponed = false;
+    clearFlag(CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG);
     // hasBeenInlinedIntoSingleCallSite: then it should not be staticized.
-    hasBeenInlinedIntoSingleCallSite = false;
+    clearFlag(HAS_BEEN_INLINED_INTO_SINGLE_CALL_SITE_FLAG);
     // initializedClassesOnNormalExit: `this` could trigger <clinit> of the previous holder.
     initializedClassesOnNormalExit =
         DefaultMethodOptimizationInfo.UNKNOWN_INITIALIZED_CLASSES_ON_NORMAL_EXIT;
@@ -441,18 +494,19 @@
     inlining = InlinePreference.Default;
     // useIdentifierNameString: code is not changed.
     // checksNullReceiverBeforeAnySideEffect: no more receiver.
-    checksNullReceiverBeforeAnySideEffect =
-        DefaultMethodOptimizationInfo.UNKNOWN_CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT;
+    markCheckNullReceiverBeforeAnySideEffect(
+        DefaultMethodOptimizationInfo.UNKNOWN_CHECKS_NULL_RECEIVER_BEFORE_ANY_SIDE_EFFECT);
     // triggersClassInitBeforeAnySideEffect: code is not changed.
-    triggersClassInitBeforeAnySideEffect =
-        DefaultMethodOptimizationInfo.UNKNOWN_TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT;
+    markTriggerClassInitBeforeAnySideEffect(
+        DefaultMethodOptimizationInfo.UNKNOWN_TRIGGERS_CLASS_INIT_BEFORE_ANY_SIDE_EFFECT);
     // classInlinerEligibility: chances are the method is not an instance method anymore.
     classInlinerEligibility = DefaultMethodOptimizationInfo.UNKNOWN_CLASS_INLINER_ELIGIBILITY;
     // initializerInfo: the computed initializer info may become invalid.
     instanceInitializerInfo = null;
     // initializerEnablingJavaAssertions: `this` could trigger <clinit> of the previous holder.
-    initializerEnablingJavaAssertions =
-        DefaultMethodOptimizationInfo.UNKNOWN_INITIALIZER_ENABLING_JAVA_ASSERTIONS;
+    setFlag(
+        INITIALIZER_ENABLING_JAVA_ASSERTIONS_FLAG,
+        DefaultMethodOptimizationInfo.UNKNOWN_INITIALIZER_ENABLING_JAVA_ASSERTIONS);
     parametersUsages =
         parametersUsages == DefaultMethodOptimizationInfo.UNKNOWN_PARAMETER_USAGE_INFO
             ? DefaultMethodOptimizationInfo.UNKNOWN_PARAMETER_USAGE_INFO