Don't mark all reflectively accessed classes as instantiated

Bug: 172327398
Change-Id: Icc85834c88ef0c14c7e9968223c58908465489c7
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 2ce631f..98128c4 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -346,6 +346,7 @@
   public final DexType classType = createStaticallyKnownType(classDescriptor);
   public final DexType packageType = createStaticallyKnownType(Package.class);
   public final DexType classLoaderType = createStaticallyKnownType(classLoaderDescriptor);
+  public final DexType constructorType = createStaticallyKnownType(constructorDescriptor);
   public final DexType fieldType = createStaticallyKnownType(fieldDescriptor);
   public final DexType methodType = createStaticallyKnownType(methodDescriptor);
   public final DexType autoCloseableType = createStaticallyKnownType(autoCloseableDescriptor);
@@ -1168,6 +1169,7 @@
     public final DexMethod getCanonicalName;
     public final DexMethod getSimpleName;
     public final DexMethod getTypeName;
+    public final DexMethod getConstructor;
     public final DexMethod getDeclaredConstructor;
     public final DexMethod getField;
     public final DexMethod getDeclaredField;
@@ -1201,6 +1203,8 @@
           classDescriptor, getSimpleNameName, stringDescriptor, DexString.EMPTY_ARRAY);
       getTypeName = createMethod(
           classDescriptor, getTypeNameName, stringDescriptor, DexString.EMPTY_ARRAY);
+      getConstructor =
+          createMethod(classType, createProto(constructorType, classArrayType), "getConstructor");
       getDeclaredConstructor =
           createMethod(
               classDescriptor,
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
index 2dc287a..2168235 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringMarker.java
@@ -33,6 +33,7 @@
 import com.android.tools.r8.ir.code.StaticPut;
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.naming.dexitembasedstring.ClassNameComputationInfo;
+import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringLookupResult;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.position.TextPosition;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
@@ -207,8 +208,9 @@
     List<Value> ins = invoke.arguments();
     Value[] changes = new Value[ins.size()];
     if (isReflectionMethod(appView.dexItemFactory(), invokedMethod) || isClassNameComparison) {
-      DexReference itemBasedString = identifyIdentifier(invoke, appView);
-      if (itemBasedString == null) {
+      IdentifierNameStringLookupResult<?> identifierLookupResult =
+          identifyIdentifier(invoke, appView, code.context());
+      if (identifierLookupResult == null) {
         warnUndeterminedIdentifierIfNecessary(invokedMethod, code.context(), invoke, null);
         return iterator;
       }
@@ -225,7 +227,10 @@
       Value newIn = code.createValue(in.getType(), in.getLocalInfo());
       DexItemBasedConstString decoupled =
           new DexItemBasedConstString(
-              newIn, itemBasedString, ClassNameComputationInfo.none(), throwingInfo);
+              newIn,
+              identifierLookupResult.getReference(),
+              ClassNameComputationInfo.none(),
+              throwingInfo);
       changes[identifierPosition] = newIn;
 
       if (in.numberOfAllUsers() == 1) {
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
index ba73522..a406a8d 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierNameStringUtils.java
@@ -10,12 +10,14 @@
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.code.ArrayPut;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.CheckCast;
@@ -28,6 +30,7 @@
 import com.android.tools.r8.ir.code.InvokeVirtual;
 import com.android.tools.r8.ir.code.NewArrayEmpty;
 import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringLookupResult;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.google.common.collect.Sets;
 import java.util.ArrayList;
@@ -196,26 +199,28 @@
    * @return {@link DexReference} corresponding to the first constant string argument that matches a
    *     class or member name, or {@code null} if no such constant was found.
    */
-  public static DexReference identifyIdentifier(
-      InvokeMethod invoke, DexDefinitionSupplier definitions) {
+  public static IdentifierNameStringLookupResult<?> identifyIdentifier(
+      InvokeMethod invoke, DexDefinitionSupplier definitions, ProgramMethod context) {
+    DexItemFactory dexItemFactory = definitions.dexItemFactory();
     List<Value> ins = invoke.arguments();
     // The only static calls: Class#forName,
     //   which receive either (String) or (String, boolean, ClassLoader) as ins.
     if (invoke.isInvokeStatic()) {
       InvokeStatic invokeStatic = invoke.asInvokeStatic();
-      if (definitions.dexItemFactory().classMethods
-          .isReflectiveClassLookup(invokeStatic.getInvokedMethod())) {
-        return ConstantValueUtils.getDexTypeFromClassForName(invokeStatic, definitions);
+      if (dexItemFactory.classMethods.isReflectiveClassLookup(invokeStatic.getInvokedMethod())) {
+        return IdentifierNameStringLookupResult.fromClassForName(
+            ConstantValueUtils.getDexTypeFromClassForName(invokeStatic, definitions));
       }
     }
 
     if (invoke.isInvokeVirtual()) {
       InvokeVirtual invokeVirtual = invoke.asInvokeVirtual();
-      if (isClassNameComparison(invokeVirtual, definitions.dexItemFactory())) {
+      if (isClassNameComparison(invokeVirtual, dexItemFactory)) {
         int argumentIndex = getPositionOfFirstConstString(invokeVirtual);
         if (argumentIndex >= 0) {
-          return inferTypeFromConstStringValue(
-              definitions, invokeVirtual.inValues().get(argumentIndex));
+          return IdentifierNameStringLookupResult.fromClassNameComparison(
+              inferTypeFromConstStringValue(
+                  definitions, invokeVirtual.inValues().get(argumentIndex)));
         }
       }
     }
@@ -226,8 +231,7 @@
     }
 
     boolean isReferenceFieldUpdater =
-        invoke.getReturnType().descriptor
-            == definitions.dexItemFactory().referenceFieldUpdaterDescriptor;
+        invoke.getReturnType().descriptor == dexItemFactory.referenceFieldUpdaterDescriptor;
     int positionOfIdentifier = isReferenceFieldUpdater ? 2 : 1;
     Value in = ins.get(positionOfIdentifier);
     if (in.isConstString()) {
@@ -241,7 +245,7 @@
         // declared in the library. Hence there is no need to handle this case.
         return null;
       }
-      DexClass holder = definitions.definitionFor(holderType);
+      DexClass holder = definitions.definitionFor(holderType, context);
       if (holder == null) {
         return null;
       }
@@ -253,22 +257,29 @@
           return null;
         }
         DexType fieldType = fieldTypeValue.getConstInstruction().asConstClass().getValue();
-        return inferFieldInHolder(holder, dexString.toString(), fieldType);
+        return IdentifierNameStringLookupResult.fromUncategorized(
+            inferFieldInHolder(holder, dexString.toString(), fieldType));
       }
       if (numOfParams == 2) {
-        return inferFieldInHolder(holder, dexString.toString(), null);
+        return IdentifierNameStringLookupResult.fromUncategorized(
+            inferFieldInHolder(holder, dexString.toString(), null));
       }
       assert numOfParams == 3;
-      DexTypeList arguments =
-          retrieveDexTypeListFromClassList(invoke, ins.get(2), definitions.dexItemFactory());
+      DexTypeList arguments = retrieveDexTypeListFromClassList(invoke, ins.get(2), dexItemFactory);
       if (arguments == null) {
         return null;
       }
-      return inferMethodInHolder(holder, dexString.toString(), arguments);
+      return IdentifierNameStringLookupResult.fromUncategorized(
+          inferMethodInHolder(holder, dexString.toString(), arguments));
     }
     if (in.isDexItemBasedConstString()) {
       DexItemBasedConstString constString = in.getConstInstruction().asDexItemBasedConstString();
-      return constString.getItem();
+      if (constString.getItem().isDexType()) {
+        return IdentifierNameStringLookupResult.fromDexTypeBasedConstString(
+            constString.getItem().asDexType());
+      }
+      return IdentifierNameStringLookupResult.fromDexMemberBasedConstString(
+          constString.getItem().asDexMember());
     }
     return null;
   }
@@ -364,7 +375,7 @@
     return itemBasedString;
   }
 
-  private static DexReference inferFieldInHolder(DexClass holder, String name, DexType fieldType) {
+  private static DexField inferFieldInHolder(DexClass holder, String name, DexType fieldType) {
     for (DexEncodedField encodedField : holder.fields()) {
       if (encodedField.field.name.toString().equals(name)
           && (fieldType == null || encodedField.field.type == fieldType)) {
@@ -374,7 +385,7 @@
     return null;
   }
 
-  private static DexReference inferMethodNameInHolder(DexClass holder, String name) {
+  private static DexMethod inferMethodNameInHolder(DexClass holder, String name) {
     for (DexEncodedMethod encodedMethod : holder.methods()) {
       if (encodedMethod.method.name.toString().equals(name)) {
         return encodedMethod.method;
@@ -383,7 +394,7 @@
     return null;
   }
 
-  private static DexReference inferMethodInHolder(
+  private static DexMethod inferMethodInHolder(
       DexClass holder, String name, DexTypeList arguments) {
     assert arguments != null;
     for (DexEncodedMethod encodedMethod : holder.methods()) {
diff --git a/src/main/java/com/android/tools/r8/naming/identifiernamestring/ClassForNameIdentifierNameStringLookupResult.java b/src/main/java/com/android/tools/r8/naming/identifiernamestring/ClassForNameIdentifierNameStringLookupResult.java
new file mode 100644
index 0000000..2498026
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/identifiernamestring/ClassForNameIdentifierNameStringLookupResult.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2020, 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.identifiernamestring;
+
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.InternalOptions;
+
+public class ClassForNameIdentifierNameStringLookupResult
+    extends IdentifierNameStringTypeLookupResult {
+
+  ClassForNameIdentifierNameStringLookupResult(DexType type) {
+    super(type);
+  }
+
+  @Override
+  public boolean isTypeInitializedFromUse() {
+    return true;
+  }
+
+  @Override
+  public boolean isTypeInstantiatedFromUse(InternalOptions options) {
+    return options.isForceProguardCompatibilityEnabled();
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/identifiernamestring/ClassNameComparisonIdentifierNameStringLookupResult.java b/src/main/java/com/android/tools/r8/naming/identifiernamestring/ClassNameComparisonIdentifierNameStringLookupResult.java
new file mode 100644
index 0000000..0305995
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/identifiernamestring/ClassNameComparisonIdentifierNameStringLookupResult.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2020, 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.identifiernamestring;
+
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.InternalOptions;
+
+public class ClassNameComparisonIdentifierNameStringLookupResult
+    extends IdentifierNameStringTypeLookupResult {
+
+  ClassNameComparisonIdentifierNameStringLookupResult(DexType type) {
+    super(type);
+  }
+
+  @Override
+  public boolean isTypeInitializedFromUse() {
+    return false;
+  }
+
+  @Override
+  public boolean isTypeInstantiatedFromUse(InternalOptions options) {
+    return false;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/identifiernamestring/DexMemberBasedConstStringIdentifierNameStringLookupResult.java b/src/main/java/com/android/tools/r8/naming/identifiernamestring/DexMemberBasedConstStringIdentifierNameStringLookupResult.java
new file mode 100644
index 0000000..5072d35
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/identifiernamestring/DexMemberBasedConstStringIdentifierNameStringLookupResult.java
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, 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.identifiernamestring;
+
+import com.android.tools.r8.graph.DexMember;
+
+public class DexMemberBasedConstStringIdentifierNameStringLookupResult
+    extends IdentifierNameStringMemberLookupResult {
+
+  DexMemberBasedConstStringIdentifierNameStringLookupResult(DexMember<?, ?> member) {
+    super(member);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/identifiernamestring/DexTypeBasedConstStringIdentifierNameStringLookupResult.java b/src/main/java/com/android/tools/r8/naming/identifiernamestring/DexTypeBasedConstStringIdentifierNameStringLookupResult.java
new file mode 100644
index 0000000..f2c1ec1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/identifiernamestring/DexTypeBasedConstStringIdentifierNameStringLookupResult.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2020, 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.identifiernamestring;
+
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.InternalOptions;
+
+public class DexTypeBasedConstStringIdentifierNameStringLookupResult
+    extends IdentifierNameStringTypeLookupResult {
+
+  DexTypeBasedConstStringIdentifierNameStringLookupResult(DexType type) {
+    super(type);
+  }
+
+  @Override
+  public boolean isTypeInitializedFromUse() {
+    return false;
+  }
+
+  @Override
+  public boolean isTypeInstantiatedFromUse(InternalOptions options) {
+    return false;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringLookupResult.java b/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringLookupResult.java
new file mode 100644
index 0000000..2c11771
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringLookupResult.java
@@ -0,0 +1,58 @@
+// Copyright (c) 2020, 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.identifiernamestring;
+
+import static com.android.tools.r8.utils.FunctionUtils.applyOrElse;
+
+import com.android.tools.r8.graph.DexMember;
+import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.graph.DexType;
+
+public abstract class IdentifierNameStringLookupResult<R extends DexReference> {
+
+  private final R reference;
+
+  IdentifierNameStringLookupResult(R reference) {
+    assert reference != null;
+    this.reference = reference;
+  }
+
+  public static ClassForNameIdentifierNameStringLookupResult fromClassForName(DexType type) {
+    return applyOrElse(type, ClassForNameIdentifierNameStringLookupResult::new, null);
+  }
+
+  public static ClassNameComparisonIdentifierNameStringLookupResult fromClassNameComparison(
+      DexType type) {
+    return applyOrElse(type, ClassNameComparisonIdentifierNameStringLookupResult::new, null);
+  }
+
+  public static DexTypeBasedConstStringIdentifierNameStringLookupResult fromDexTypeBasedConstString(
+      DexType type) {
+    return applyOrElse(type, DexTypeBasedConstStringIdentifierNameStringLookupResult::new, null);
+  }
+
+  public static DexMemberBasedConstStringIdentifierNameStringLookupResult
+      fromDexMemberBasedConstString(DexMember<?, ?> member) {
+    return applyOrElse(
+        member, DexMemberBasedConstStringIdentifierNameStringLookupResult::new, null);
+  }
+
+  public static UncategorizedMemberIdentifierNameStringLookupResult fromUncategorized(
+      DexMember<?, ?> member) {
+    return applyOrElse(member, UncategorizedMemberIdentifierNameStringLookupResult::new, null);
+  }
+
+  public boolean isTypeResult() {
+    return false;
+  }
+
+  public IdentifierNameStringTypeLookupResult asTypeResult() {
+    return null;
+  }
+
+  public R getReference() {
+    return reference;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringMemberLookupResult.java b/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringMemberLookupResult.java
new file mode 100644
index 0000000..61d7925
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringMemberLookupResult.java
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, 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.identifiernamestring;
+
+import com.android.tools.r8.graph.DexMember;
+
+public abstract class IdentifierNameStringMemberLookupResult
+    extends IdentifierNameStringLookupResult<DexMember<?, ?>> {
+
+  IdentifierNameStringMemberLookupResult(DexMember<?, ?> member) {
+    super(member);
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringTypeLookupResult.java b/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringTypeLookupResult.java
new file mode 100644
index 0000000..6707406
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/identifiernamestring/IdentifierNameStringTypeLookupResult.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2020, 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.identifiernamestring;
+
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.utils.InternalOptions;
+
+public abstract class IdentifierNameStringTypeLookupResult
+    extends IdentifierNameStringLookupResult<DexType> {
+
+  IdentifierNameStringTypeLookupResult(DexType type) {
+    super(type);
+  }
+
+  public abstract boolean isTypeInitializedFromUse();
+
+  public abstract boolean isTypeInstantiatedFromUse(InternalOptions options);
+
+  @Override
+  public boolean isTypeResult() {
+    return true;
+  }
+
+  @Override
+  public IdentifierNameStringTypeLookupResult asTypeResult() {
+    return this;
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/identifiernamestring/UncategorizedMemberIdentifierNameStringLookupResult.java b/src/main/java/com/android/tools/r8/naming/identifiernamestring/UncategorizedMemberIdentifierNameStringLookupResult.java
new file mode 100644
index 0000000..5d29fc1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/identifiernamestring/UncategorizedMemberIdentifierNameStringLookupResult.java
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, 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.identifiernamestring;
+
+import com.android.tools.r8.graph.DexMember;
+
+public class UncategorizedMemberIdentifierNameStringLookupResult
+    extends IdentifierNameStringMemberLookupResult {
+
+  UncategorizedMemberIdentifierNameStringLookupResult(DexMember<?, ?> member) {
+    super(member);
+  }
+}
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 cef391b..64fb203 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -91,6 +91,8 @@
 import com.android.tools.r8.ir.desugar.LambdaRewriter;
 import com.android.tools.r8.kotlin.KotlinMetadataEnqueuerExtension;
 import com.android.tools.r8.logging.Log;
+import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringLookupResult;
+import com.android.tools.r8.naming.identifiernamestring.IdentifierNameStringTypeLookupResult;
 import com.android.tools.r8.shaking.DelayedRootSetActionItem.InterfaceMethodSyntheticBridgeAction;
 import com.android.tools.r8.shaking.EnqueuerWorklist.EnqueuerAction;
 import com.android.tools.r8.shaking.GraphReporter.KeepReasonWitness;
@@ -1579,14 +1581,16 @@
       // Ignore primitive types.
       return;
     }
-    DexProgramClass holder = getProgramClassOrNull(type);
-    if (holder == null) {
+    DexProgramClass clazz = getProgramClassOrNull(type);
+    if (clazz == null) {
       return;
     }
-    markTypeAsLive(
-        holder,
-        scopedMethodsForLiveTypes.computeIfAbsent(type, ignore -> new ScopedDexMethodSet()),
-        graphReporter.registerClass(holder, reason));
+    markTypeAsLive(clazz, reason);
+  }
+
+  private void markTypeAsLive(DexProgramClass clazz, KeepReason reason) {
+    assert clazz != null;
+    markTypeAsLive(clazz, graphReporter.registerClass(clazz, reason));
   }
 
   private void markTypeAsLive(DexType type, Function<DexProgramClass, KeepReasonWitness> reason) {
@@ -3813,18 +3817,22 @@
     if (!isReflectionMethod(dexItemFactory, invokedMethod)) {
       return;
     }
-    DexReference identifierItem = identifyIdentifier(invoke, appView);
-    if (identifierItem == null) {
+    IdentifierNameStringLookupResult<?> identifierLookupResult =
+        identifyIdentifier(invoke, appView, method);
+    if (identifierLookupResult == null) {
       return;
     }
-    if (identifierItem.isDexType()) {
-      DexProgramClass clazz = getProgramClassOrNullFromReflectiveAccess(identifierItem.asDexType());
+    DexReference referencedItem = identifierLookupResult.getReference();
+    if (referencedItem.isDexType()) {
+      assert identifierLookupResult.isTypeResult();
+      IdentifierNameStringTypeLookupResult identifierTypeLookupResult =
+          identifierLookupResult.asTypeResult();
+      DexProgramClass clazz = getProgramClassOrNullFromReflectiveAccess(referencedItem.asDexType());
       if (clazz == null) {
         return;
       }
-      if (clazz.isAnnotation() || clazz.isInterface()) {
-        markTypeAsLive(clazz.type, KeepReason.reflectiveUseIn(method));
-      } else {
+      markTypeAsLive(clazz, KeepReason.reflectiveUseIn(method));
+      if (identifierTypeLookupResult.isTypeInstantiatedFromUse(options)) {
         workList.enqueueMarkInstantiatedAction(
             clazz, null, InstantiationReason.REFLECTION, KeepReason.reflectiveUseIn(method));
         if (clazz.hasDefaultInitializer()) {
@@ -3833,9 +3841,11 @@
           markMethodAsTargeted(initializer, reason);
           markDirectStaticOrConstructorMethodAsLive(initializer, reason);
         }
+      } else if (identifierTypeLookupResult.isTypeInitializedFromUse()) {
+        markDirectAndIndirectClassInitializersAsLive(clazz);
       }
-    } else if (identifierItem.isDexField()) {
-      DexField field = identifierItem.asDexField();
+    } else if (referencedItem.isDexField()) {
+      DexField field = referencedItem.asDexField();
       DexProgramClass clazz = getProgramClassOrNull(field.holder);
       if (clazz == null) {
         return;
@@ -3862,8 +3872,8 @@
         markFieldAsKept(programField, KeepReason.reflectiveUseIn(method));
       }
     } else {
-      assert identifierItem.isDexMethod();
-      DexMethod targetedMethodReference = identifierItem.asDexMethod();
+      assert referencedItem.isDexMethod();
+      DexMethod targetedMethodReference = referencedItem.asDexMethod();
       DexProgramClass clazz = getProgramClassOrNull(targetedMethodReference.holder);
       if (clazz == null) {
         return;
@@ -3927,8 +3937,9 @@
     }
 
     InvokeVirtual constructorDefinition = constructorValue.definition.asInvokeVirtual();
-    if (constructorDefinition.getInvokedMethod()
-        != appView.dexItemFactory().classMethods.getDeclaredConstructor) {
+    DexMethod invokedMethod = constructorDefinition.getInvokedMethod();
+    if (invokedMethod != appView.dexItemFactory().classMethods.getConstructor
+        && invokedMethod != appView.dexItemFactory().classMethods.getDeclaredConstructor) {
       // Give up, we can't tell which constructor is being invoked.
       return;
     }
@@ -3942,7 +3953,7 @@
       return;
     }
 
-    DexProgramClass clazz = getProgramClassOrNull(instantiatedType);
+    DexProgramClass clazz = getProgramClassOrNullFromReflectiveAccess(instantiatedType);
     if (clazz == null) {
       return;
     }
diff --git a/src/main/java/com/android/tools/r8/utils/FunctionUtils.java b/src/main/java/com/android/tools/r8/utils/FunctionUtils.java
index b7c7a87..3338dde 100644
--- a/src/main/java/com/android/tools/r8/utils/FunctionUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/FunctionUtils.java
@@ -10,6 +10,10 @@
 
 public class FunctionUtils {
 
+  public static <S, T> T applyOrElse(S object, Function<S, T> fn, T orElse) {
+    return object != null ? fn.apply(object) : orElse;
+  }
+
   public static <S, T, R> Function<S, Function<T, R>> curry(BiFunction<S, T, R> function) {
     return arg -> arg2 -> function.apply(arg, arg2);
   }