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);
}