Reapply "Towards raising a diagnostic for package-private cross-split references"
This reverts commit d29116564dc98ae2ade6877e48bbcb8f0d6fdb62.
Change-Id: I2000b92912ef887692f6fc23bd330ecc51af874d
diff --git a/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java b/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java
new file mode 100644
index 0000000..ee3e64f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/features/IsolatedFeatureSplitsChecker.java
@@ -0,0 +1,174 @@
+// Copyright (c) 2023, 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.features;
+
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.FieldResolutionResult.SingleFieldResolutionResult;
+import com.android.tools.r8.graph.MethodResolutionResult;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.analysis.EnqueuerFieldAccessAnalysis;
+import com.android.tools.r8.graph.analysis.EnqueuerInvokeAnalysis;
+import com.android.tools.r8.graph.analysis.EnqueuerTypeAccessAnalysis;
+import com.android.tools.r8.shaking.Enqueuer;
+import com.android.tools.r8.shaking.EnqueuerWorklist;
+import com.android.tools.r8.utils.InternalOptions;
+
+// TODO(b/300247439): Also trace types referenced from new-array instructions, call sites, etc.
+public class IsolatedFeatureSplitsChecker
+ implements EnqueuerFieldAccessAnalysis, EnqueuerInvokeAnalysis, EnqueuerTypeAccessAnalysis {
+
+ @SuppressWarnings("UnusedVariable")
+ private final AppView<? extends AppInfoWithClassHierarchy> appView;
+
+ @SuppressWarnings("UnusedVariable")
+ private final Enqueuer enqueuer;
+
+ private IsolatedFeatureSplitsChecker(
+ AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {
+ this.appView = appView;
+ this.enqueuer = enqueuer;
+ }
+
+ public static void register(
+ AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {
+ if (enabled(appView, enqueuer)) {
+ IsolatedFeatureSplitsChecker checker = new IsolatedFeatureSplitsChecker(appView, enqueuer);
+ enqueuer
+ .registerFieldAccessAnalysis(checker)
+ .registerInvokeAnalysis(checker)
+ .registerTypeAccessAnalysis(checker);
+ }
+ }
+
+ private static boolean enabled(
+ AppView<? extends AppInfoWithClassHierarchy> appView, Enqueuer enqueuer) {
+ InternalOptions options = appView.options();
+ return options.hasFeatureSplitConfiguration()
+ && options.getFeatureSplitConfiguration().isIsolatedSplitsEnabled()
+ && enqueuer.getMode().isInitialTreeShaking();
+ }
+
+ @SuppressWarnings("UnusedVariable")
+ private void traceFieldAccess(FieldResolutionResult resolutionResult, ProgramMethod context) {
+ // TODO(b/300247439): Check access.
+ }
+
+ @SuppressWarnings("UnusedVariable")
+ private void traceMethodInvoke(MethodResolutionResult resolutionResult, ProgramMethod context) {
+ // TODO(b/300247439): Check access.
+ }
+
+ @SuppressWarnings("UnusedVariable")
+ private void traceTypeAccess(DexClass clazz, ProgramMethod context) {
+ // TODO(b/300247439): Check access.
+ }
+
+ // Field accesses.
+
+ @Override
+ public void traceInstanceFieldRead(
+ DexField field,
+ FieldResolutionResult resolutionResult,
+ ProgramMethod context,
+ EnqueuerWorklist worklist) {
+ traceFieldAccess(resolutionResult, context);
+ }
+
+ @Override
+ public void traceInstanceFieldWrite(
+ DexField field,
+ FieldResolutionResult resolutionResult,
+ ProgramMethod context,
+ EnqueuerWorklist worklist) {
+ traceFieldAccess(resolutionResult, context);
+ }
+
+ @Override
+ public void traceStaticFieldRead(
+ DexField field,
+ SingleFieldResolutionResult<?> resolutionResult,
+ ProgramMethod context,
+ EnqueuerWorklist worklist) {
+ traceFieldAccess(resolutionResult, context);
+ }
+
+ @Override
+ public void traceStaticFieldWrite(
+ DexField field,
+ FieldResolutionResult resolutionResult,
+ ProgramMethod context,
+ EnqueuerWorklist worklist) {
+ traceFieldAccess(resolutionResult, context);
+ }
+
+ // Method invokes.
+
+ @Override
+ public void traceInvokeStatic(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+ traceMethodInvoke(resolutionResult, context);
+ }
+
+ @Override
+ public void traceInvokeDirect(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+ traceMethodInvoke(resolutionResult, context);
+ }
+
+ @Override
+ public void traceInvokeInterface(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+ traceMethodInvoke(resolutionResult, context);
+ }
+
+ @Override
+ public void traceInvokeSuper(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+ traceMethodInvoke(resolutionResult, context);
+ }
+
+ @Override
+ public void traceInvokeVirtual(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
+ traceMethodInvoke(resolutionResult, context);
+ }
+
+ // Type accesses.
+
+ @Override
+ public void traceCheckCast(DexType type, DexClass clazz, ProgramMethod context) {
+ traceTypeAccess(clazz, context);
+ }
+
+ @Override
+ public void traceSafeCheckCast(DexType type, DexClass clazz, ProgramMethod context) {
+ traceTypeAccess(clazz, context);
+ }
+
+ @Override
+ public void traceConstClass(DexType type, DexClass clazz, ProgramMethod context) {
+ traceTypeAccess(clazz, context);
+ }
+
+ @Override
+ public void traceExceptionGuard(DexType type, DexClass clazz, ProgramMethod context) {
+ traceTypeAccess(clazz, context);
+ }
+
+ @Override
+ public void traceInstanceOf(DexType type, DexClass clazz, ProgramMethod context) {
+ traceTypeAccess(clazz, context);
+ }
+
+ @Override
+ public void traceNewInstance(DexType type, DexClass clazz, ProgramMethod context) {
+ traceTypeAccess(clazz, context);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java
index ad0dcbf..1ff19a6 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java
@@ -4,12 +4,13 @@
package com.android.tools.r8.graph.analysis;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
public interface EnqueuerCheckCastAnalysis {
- void traceCheckCast(DexType type, ProgramMethod context);
+ void traceCheckCast(DexType type, DexClass clazz, ProgramMethod context);
- void traceSafeCheckCast(DexType type, ProgramMethod context);
+ void traceSafeCheckCast(DexType type, DexClass clazz, ProgramMethod context);
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerConstClassAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerConstClassAnalysis.java
new file mode 100644
index 0000000..61f127a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerConstClassAnalysis.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2023, 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.graph.analysis;
+
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
+
+public interface EnqueuerConstClassAnalysis {
+
+ void traceConstClass(DexType type, DexClass clazz, ProgramMethod context);
+}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerExceptionGuardAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerExceptionGuardAnalysis.java
index 1bf392e..752e4a5 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerExceptionGuardAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerExceptionGuardAnalysis.java
@@ -4,9 +4,10 @@
package com.android.tools.r8.graph.analysis;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
public interface EnqueuerExceptionGuardAnalysis {
- void traceExceptionGuard(DexType guard, ProgramMethod context);
+ void traceExceptionGuard(DexType guard, DexClass clazz, ProgramMethod context);
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerFieldAccessAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerFieldAccessAnalysis.java
index 0642216..69eb560 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerFieldAccessAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerFieldAccessAnalysis.java
@@ -18,28 +18,24 @@
FieldResolutionResult resolutionResult,
ProgramMethod context,
EnqueuerWorklist worklist) {}
- ;
default void traceInstanceFieldWrite(
DexField field,
FieldResolutionResult resolutionResult,
ProgramMethod context,
EnqueuerWorklist worklist) {}
- ;
default void traceStaticFieldRead(
DexField field,
SingleFieldResolutionResult<?> resolutionResult,
ProgramMethod context,
EnqueuerWorklist worklist) {}
- ;
default void traceStaticFieldWrite(
DexField field,
FieldResolutionResult resolutionResult,
ProgramMethod context,
EnqueuerWorklist worklist) {}
- ;
/**
* Called when the Enqueuer has reached the final fixpoint. Each analysis may use this callback to
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java
index abda4d1..485a311 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java
@@ -4,9 +4,10 @@
package com.android.tools.r8.graph.analysis;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
public interface EnqueuerInstanceOfAnalysis {
- void traceInstanceOf(DexType type, ProgramMethod context);
+ void traceInstanceOf(DexType type, DexClass clazz, ProgramMethod context);
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInvokeAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInvokeAnalysis.java
index d0a39b3..d2ca27d 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInvokeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInvokeAnalysis.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.graph.analysis;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
public interface EnqueuerInvokeAnalysis {
@@ -12,13 +13,18 @@
* Each traceInvokeXX method is called when a corresponding invoke is found while tracing a live
* method.
*/
- void traceInvokeStatic(DexMethod invokedMethod, ProgramMethod context);
+ void traceInvokeStatic(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
- void traceInvokeDirect(DexMethod invokedMethod, ProgramMethod context);
+ void traceInvokeDirect(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
- void traceInvokeInterface(DexMethod invokedMethod, ProgramMethod context);
+ void traceInvokeInterface(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
- void traceInvokeSuper(DexMethod invokedMethod, ProgramMethod context);
+ void traceInvokeSuper(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
- void traceInvokeVirtual(DexMethod invokedMethod, ProgramMethod context);
+ void traceInvokeVirtual(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context);
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerNewInstanceAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerNewInstanceAnalysis.java
new file mode 100644
index 0000000..880c91a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerNewInstanceAnalysis.java
@@ -0,0 +1,13 @@
+// Copyright (c) 2023, 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.graph.analysis;
+
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
+
+public interface EnqueuerNewInstanceAnalysis {
+
+ void traceNewInstance(DexType type, DexClass clazz, ProgramMethod context);
+}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerTypeAccessAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerTypeAccessAnalysis.java
new file mode 100644
index 0000000..3d44ef1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerTypeAccessAnalysis.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2023, 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.graph.analysis;
+
+public interface EnqueuerTypeAccessAnalysis
+ extends EnqueuerCheckCastAnalysis,
+ EnqueuerConstClassAnalysis,
+ EnqueuerExceptionGuardAnalysis,
+ EnqueuerInstanceOfAnalysis,
+ EnqueuerNewInstanceAnalysis {}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/InvokeVirtualToInterfaceVerifyErrorWorkaround.java b/src/main/java/com/android/tools/r8/graph/analysis/InvokeVirtualToInterfaceVerifyErrorWorkaround.java
index 94bf7ce..70fca76 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/InvokeVirtualToInterfaceVerifyErrorWorkaround.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/InvokeVirtualToInterfaceVerifyErrorWorkaround.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.KeepInfo.Joiner;
@@ -53,7 +54,8 @@
}
@Override
- public void traceInvokeVirtual(DexMethod invokedMethod, ProgramMethod context) {
+ public void traceInvokeVirtual(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
if (isInterfaceInSomeApiLevel(invokedMethod.getHolderType())) {
enqueuer.getKeepInfo().joinMethod(context, Joiner::disallowOptimization);
}
@@ -69,22 +71,26 @@
}
@Override
- public void traceInvokeDirect(DexMethod invokedMethod, ProgramMethod context) {
+ public void traceInvokeDirect(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
// Intentionally empty.
}
@Override
- public void traceInvokeInterface(DexMethod invokedMethod, ProgramMethod context) {
+ public void traceInvokeInterface(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
// Intentionally empty.
}
@Override
- public void traceInvokeStatic(DexMethod invokedMethod, ProgramMethod context) {
+ public void traceInvokeStatic(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
// Intentionally empty.
}
@Override
- public void traceInvokeSuper(DexMethod invokedMethod, ProgramMethod context) {
+ public void traceInvokeSuper(
+ DexMethod invokedMethod, MethodResolutionResult resolutionResult, ProgramMethod context) {
// Intentionally empty.
}
}
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 ea7cbf5..b4f643a 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -27,6 +27,7 @@
import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
+import com.android.tools.r8.features.IsolatedFeatureSplitsChecker;
import com.android.tools.r8.graph.AccessControl;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -90,10 +91,13 @@
import com.android.tools.r8.graph.analysis.ApiModelAnalysis;
import com.android.tools.r8.graph.analysis.EnqueuerAnalysis;
import com.android.tools.r8.graph.analysis.EnqueuerCheckCastAnalysis;
+import com.android.tools.r8.graph.analysis.EnqueuerConstClassAnalysis;
import com.android.tools.r8.graph.analysis.EnqueuerExceptionGuardAnalysis;
import com.android.tools.r8.graph.analysis.EnqueuerFieldAccessAnalysis;
import com.android.tools.r8.graph.analysis.EnqueuerInstanceOfAnalysis;
import com.android.tools.r8.graph.analysis.EnqueuerInvokeAnalysis;
+import com.android.tools.r8.graph.analysis.EnqueuerNewInstanceAnalysis;
+import com.android.tools.r8.graph.analysis.EnqueuerTypeAccessAnalysis;
import com.android.tools.r8.graph.analysis.GetArrayOfMissingTypeVerifyErrorWorkaround;
import com.android.tools.r8.graph.analysis.InvokeVirtualToInterfaceVerifyErrorWorkaround;
import com.android.tools.r8.graph.analysis.ResourceAccessAnalysis;
@@ -256,6 +260,8 @@
private final Set<EnqueuerInstanceOfAnalysis> instanceOfAnalyses = new LinkedHashSet<>();
private final Set<EnqueuerExceptionGuardAnalysis> exceptionGuardAnalyses = new LinkedHashSet<>();
private final Set<EnqueuerCheckCastAnalysis> checkCastAnalyses = new LinkedHashSet<>();
+ private final Set<EnqueuerConstClassAnalysis> constClassAnalyses = new LinkedHashSet<>();
+ private final Set<EnqueuerNewInstanceAnalysis> newInstanceAnalyses = new LinkedHashSet<>();
// Don't hold a direct pointer to app info (use appView).
private AppInfoWithClassHierarchy appInfo;
@@ -508,6 +514,7 @@
}
appView.withGeneratedMessageLiteBuilderShrinker(
shrinker -> registerAnalysis(shrinker.createEnqueuerAnalysis()));
+ IsolatedFeatureSplitsChecker.register(appView, this);
ResourceAccessAnalysis.register(appView, this);
}
@@ -585,11 +592,29 @@
return this;
}
+ public Enqueuer registerConstClassAnalysis(EnqueuerConstClassAnalysis analysis) {
+ constClassAnalyses.add(analysis);
+ return this;
+ }
+
public Enqueuer registerExceptionGuardAnalysis(EnqueuerExceptionGuardAnalysis analysis) {
exceptionGuardAnalyses.add(analysis);
return this;
}
+ public Enqueuer registerNewInstanceAnalysis(EnqueuerNewInstanceAnalysis analysis) {
+ newInstanceAnalyses.add(analysis);
+ return this;
+ }
+
+ public Enqueuer registerTypeAccessAnalysis(EnqueuerTypeAccessAnalysis analysis) {
+ return registerCheckCastAnalysis(analysis)
+ .registerConstClassAnalysis(analysis)
+ .registerExceptionGuardAnalysis(analysis)
+ .registerInstanceOfAnalysis(analysis)
+ .registerNewInstanceAnalysis(analysis);
+ }
+
public void setAnnotationRemoverBuilder(AnnotationRemover.Builder annotationRemoverBuilder) {
this.annotationRemoverBuilder = annotationRemoverBuilder;
}
@@ -1227,23 +1252,23 @@
}
void traceCheckCast(DexType type, ProgramMethod currentMethod, boolean ignoreCompatRules) {
- checkCastAnalyses.forEach(analysis -> analysis.traceCheckCast(type, currentMethod));
- internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
+ DexClass clazz = internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
+ checkCastAnalyses.forEach(analysis -> analysis.traceCheckCast(type, clazz, currentMethod));
}
void traceSafeCheckCast(DexType type, ProgramMethod currentMethod) {
- checkCastAnalyses.forEach(analysis -> analysis.traceSafeCheckCast(type, currentMethod));
- internalTraceConstClassOrCheckCast(type, currentMethod, true);
+ DexClass clazz = internalTraceConstClassOrCheckCast(type, currentMethod, true);
+ checkCastAnalyses.forEach(analysis -> analysis.traceSafeCheckCast(type, clazz, currentMethod));
}
- @SuppressWarnings("ReferenceEquality")
void traceConstClass(
DexType type,
ProgramMethod currentMethod,
ListIterator<? extends CfOrDexInstruction> iterator,
boolean ignoreCompatRules) {
handleLockCandidate(type, currentMethod, iterator);
- internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
+ DexClass clazz = internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
+ constClassAnalyses.forEach(analysis -> analysis.traceConstClass(type, clazz, currentMethod));
}
private void handleLockCandidate(
@@ -1298,18 +1323,21 @@
return result;
}
- private void internalTraceConstClassOrCheckCast(
+ private DexClass internalTraceConstClassOrCheckCast(
DexType type, ProgramMethod currentMethod, boolean ignoreCompatRules) {
- DexProgramClass baseClass = resolveBaseType(type, currentMethod);
+ DexClass baseClass = resolveBaseType(type, currentMethod);
traceTypeReference(type, currentMethod);
if (!forceProguardCompatibility || ignoreCompatRules) {
- return;
+ return baseClass;
}
- if (baseClass != null) {
+ if (baseClass != null && baseClass.isProgramClass()) {
// Don't require any constructor, see b/112386012.
+ DexProgramClass baseProgramClass = baseClass.asProgramClass();
markClassAsInstantiatedWithCompatRule(
- baseClass, () -> graphReporter.reportCompatInstantiated(baseClass, currentMethod));
+ baseProgramClass,
+ () -> graphReporter.reportCompatInstantiated(baseProgramClass, currentMethod));
}
+ return baseClass;
}
void traceRecordFieldValues(DexField[] fields, ProgramMethod currentMethod) {
@@ -1401,14 +1429,16 @@
}
void traceInstanceOf(DexType type, ProgramMethod currentMethod) {
- instanceOfAnalyses.forEach(analysis -> analysis.traceInstanceOf(type, currentMethod));
- resolveBaseType(type, currentMethod);
+ DexClass clazz = resolveBaseType(type, currentMethod);
traceTypeReference(type, currentMethod);
+ instanceOfAnalyses.forEach(analysis -> analysis.traceInstanceOf(type, clazz, currentMethod));
}
- void traceExceptionGuard(DexType guard, ProgramMethod currentMethod) {
- exceptionGuardAnalyses.forEach(analysis -> analysis.traceExceptionGuard(guard, currentMethod));
- traceTypeReference(guard, currentMethod);
+ void traceExceptionGuard(DexType type, ProgramMethod currentMethod) {
+ DexClass clazz = resolveBaseType(type, currentMethod);
+ traceTypeReference(type, currentMethod);
+ exceptionGuardAnalyses.forEach(
+ analysis -> analysis.traceExceptionGuard(type, clazz, currentMethod));
}
void traceInvokeDirect(DexMethod invokedMethod, ProgramMethod context) {
@@ -1449,8 +1479,10 @@
methodAccessInfoCollection::registerInvokeDirectInContext, invokedMethod, context)) {
return;
}
- handleInvokeOfDirectTarget(invokedMethod, context, reason);
- invokeAnalyses.forEach(analysis -> analysis.traceInvokeDirect(invokedMethod, context));
+ MethodResolutionResult resolutionResult =
+ handleInvokeOfDirectTarget(invokedMethod, context, reason);
+ invokeAnalyses.forEach(
+ analysis -> analysis.traceInvokeDirect(invokedMethod, resolutionResult, context));
}
void traceInvokeInterface(DexMethod invokedMethod, ProgramMethod context) {
@@ -1467,8 +1499,8 @@
methodAccessInfoCollection::registerInvokeInterfaceInContext, method, context)) {
return;
}
- markVirtualMethodAsReachable(method, true, context, keepReason);
- invokeAnalyses.forEach(analysis -> analysis.traceInvokeInterface(method, context));
+ MethodResolutionResult result = markVirtualMethodAsReachable(method, true, context, keepReason);
+ invokeAnalyses.forEach(analysis -> analysis.traceInvokeInterface(method, result, context));
}
void traceInvokeStatic(DexMethod invokedMethod, ProgramMethod context) {
@@ -1505,8 +1537,10 @@
methodAccessInfoCollection::registerInvokeStaticInContext, invokedMethod, context)) {
return;
}
- handleInvokeOfStaticTarget(invokedMethod, context, reason);
- invokeAnalyses.forEach(analysis -> analysis.traceInvokeStatic(invokedMethod, context));
+ MethodResolutionResult resolutionResult =
+ handleInvokeOfStaticTarget(invokedMethod, context, reason);
+ invokeAnalyses.forEach(
+ analysis -> analysis.traceInvokeStatic(invokedMethod, resolutionResult, context));
}
void traceInvokeSuper(DexMethod invokedMethod, ProgramMethod context) {
@@ -1517,7 +1551,6 @@
return;
}
worklist.enqueueMarkReachableSuperAction(invokedMethod, context);
- invokeAnalyses.forEach(analysis -> analysis.traceInvokeSuper(invokedMethod, context));
}
void traceInvokeVirtual(DexMethod invokedMethod, ProgramMethod context) {
@@ -1544,8 +1577,10 @@
methodAccessInfoCollection::registerInvokeVirtualInContext, invokedMethod, context)) {
return;
}
- markVirtualMethodAsReachable(invokedMethod, false, context, reason);
- invokeAnalyses.forEach(analysis -> analysis.traceInvokeVirtual(invokedMethod, context));
+ MethodResolutionResult resolutionResult =
+ markVirtualMethodAsReachable(invokedMethod, false, context, reason);
+ invokeAnalyses.forEach(
+ analysis -> analysis.traceInvokeVirtual(invokedMethod, resolutionResult, context));
}
void traceNewInstance(DexType type, ProgramMethod context) {
@@ -1557,11 +1592,13 @@
return;
}
- traceNewInstance(
- type,
- context,
- InstantiationReason.NEW_INSTANCE_INSTRUCTION,
- KeepReason.instantiatedIn(context));
+ DexClass clazz =
+ traceNewInstance(
+ type,
+ context,
+ InstantiationReason.NEW_INSTANCE_INSTRUCTION,
+ KeepReason.instantiatedIn(context));
+ newInstanceAnalyses.forEach(analysis -> analysis.traceNewInstance(type, clazz, context));
}
void traceNewInstanceFromLambda(DexType type, ProgramMethod context) {
@@ -1569,19 +1606,22 @@
type, context, InstantiationReason.LAMBDA, KeepReason.invokedFromLambdaCreatedIn(context));
}
- private void traceNewInstance(
+ private DexClass traceNewInstance(
DexType type,
ProgramMethod context,
InstantiationReason instantiationReason,
KeepReason keepReason) {
- DexProgramClass clazz = getProgramClassOrNull(type, context);
- if (clazz != null) {
+ DexClass clazz = resolveBaseType(type, context);
+ if (clazz != null && clazz.isProgramClass()) {
+ DexProgramClass programClass = clazz.asProgramClass();
if (clazz.isAnnotation() || clazz.isInterface()) {
- markTypeAsLive(clazz, graphReporter.registerClass(clazz, keepReason));
+ markTypeAsLive(programClass, graphReporter.registerClass(programClass, keepReason));
} else {
- worklist.enqueueMarkInstantiatedAction(clazz, context, instantiationReason, keepReason);
+ worklist.enqueueMarkInstantiatedAction(
+ programClass, context, instantiationReason, keepReason);
}
}
+ return clazz;
}
void traceInstanceFieldRead(DexField field, ProgramMethod currentMethod) {
@@ -2347,13 +2387,12 @@
appView, annotatedItem, annotation, isLive, annotatedKind, mode);
}
- private DexProgramClass resolveBaseType(DexType type, ProgramDefinition context) {
+ private DexClass resolveBaseType(DexType type, ProgramDefinition context) {
if (type.isArrayType()) {
return resolveBaseType(type.toBaseType(appView.dexItemFactory()), context);
}
if (type.isClassType()) {
- DexProgramClass clazz =
- asProgramClassOrNull(appView.definitionFor(type, context.getContextClass()));
+ DexClass clazz = appView.definitionFor(type, context.getContextClass());
if (clazz != null) {
checkAccess(clazz, context);
}
@@ -2403,9 +2442,11 @@
appInfo.resolveMethodLegacy(method, interfaceInvoke);
methodResolutionResult.visitMethodResolutionResults(
resolutionResult -> {
- checkAccess(resolutionResult, context);
- recordMethodReference(
- method, resolutionResult.getResolutionPair().asProgramDerivedContext(context));
+ if (!resolutionResult.isArrayCloneMethodResult()) {
+ checkAccess(resolutionResult, context);
+ recordMethodReference(
+ method, resolutionResult.getResolutionPair().asProgramDerivedContext(context));
+ }
},
failedResolutionResult -> {
markFailedMethodResolutionTargets(method, failedResolutionResult, context, reason);
@@ -2414,32 +2455,33 @@
return methodResolutionResult;
}
- private void handleInvokeOfStaticTarget(
+ private MethodResolutionResult handleInvokeOfStaticTarget(
DexMethod reference, ProgramDefinition context, KeepReason reason) {
- resolveMethod(reference, context, reason)
- .forEachMethodResolutionResult(
- resolutionResult -> {
- if (!resolutionResult.isSingleResolution()) {
- return;
- }
- SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
- if (resolution.getResolvedHolder().isNotProgramClass()) {
- return;
- }
- DexProgramClass clazz = resolution.getResolvedHolder().asProgramClass();
- DexEncodedMethod encodedMethod = resolution.getResolvedMethod();
+ MethodResolutionResult resolutionResults = resolveMethod(reference, context, reason);
+ resolutionResults.forEachMethodResolutionResult(
+ resolutionResult -> {
+ if (!resolutionResult.isSingleResolution()) {
+ return;
+ }
+ SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
+ if (resolution.getResolvedHolder().isNotProgramClass()) {
+ return;
+ }
+ DexProgramClass clazz = resolution.getResolvedHolder().asProgramClass();
+ DexEncodedMethod encodedMethod = resolution.getResolvedMethod();
- // We have to mark the resolved method as targeted even if it cannot actually be
- // invoked to make sure the invocation will keep failing in the appropriate way.
- ProgramMethod method = new ProgramMethod(clazz, encodedMethod);
- markMethodAsTargeted(method, reason);
+ // We have to mark the resolved method as targeted even if it cannot actually be
+ // invoked to make sure the invocation will keep failing in the appropriate way.
+ ProgramMethod method = new ProgramMethod(clazz, encodedMethod);
+ markMethodAsTargeted(method, reason);
- // Only mark methods for which invocation will succeed at runtime live.
- if (encodedMethod.isStatic()) {
- markDirectAndIndirectClassInitializersAsLive(clazz);
- markDirectStaticOrConstructorMethodAsLive(method, reason);
- }
- });
+ // Only mark methods for which invocation will succeed at runtime live.
+ if (encodedMethod.isStatic()) {
+ markDirectAndIndirectClassInitializersAsLive(clazz);
+ markDirectStaticOrConstructorMethodAsLive(method, reason);
+ }
+ });
+ return resolutionResults;
}
void markDirectAndIndirectClassInitializersAsLive(DexProgramClass clazz) {
@@ -2543,43 +2585,44 @@
handleInvokeOfDirectTarget(method, context, reason);
}
- private void handleInvokeOfDirectTarget(
+ private MethodResolutionResult handleInvokeOfDirectTarget(
DexMethod reference, ProgramDefinition context, KeepReason reason) {
- resolveMethod(reference, context, reason)
- .forEachMethodResolutionResult(
- resolutionResult -> {
- if (resolutionResult.isFailedResolution()) {
- failedMethodResolutionTargets.add(reference);
- return;
- }
+ MethodResolutionResult resolutionResults = resolveMethod(reference, context, reason);
+ resolutionResults.forEachMethodResolutionResult(
+ resolutionResult -> {
+ if (resolutionResult.isFailedResolution()) {
+ failedMethodResolutionTargets.add(reference);
+ return;
+ }
- if (!resolutionResult.isSingleResolution()
- || !resolutionResult.getResolvedHolder().isProgramClass()) {
- return;
- }
+ if (!resolutionResult.isSingleResolution()
+ || !resolutionResult.getResolvedHolder().isProgramClass()) {
+ return;
+ }
- ProgramMethod resolvedMethod =
- resolutionResult.asSingleResolution().getResolvedProgramMethod();
+ ProgramMethod resolvedMethod =
+ resolutionResult.asSingleResolution().getResolvedProgramMethod();
- // We have to mark the resolved method as targeted even if it cannot actually be
- // invoked to make sure the invocation will keep failing in the appropriate way.
- markMethodAsTargeted(resolvedMethod, reason);
+ // We have to mark the resolved method as targeted even if it cannot actually be
+ // invoked to make sure the invocation will keep failing in the appropriate way.
+ markMethodAsTargeted(resolvedMethod, reason);
- // Only mark methods for which invocation will succeed at runtime live.
- if (resolvedMethod.getAccessFlags().isStatic()) {
- return;
- }
+ // Only mark methods for which invocation will succeed at runtime live.
+ if (resolvedMethod.getAccessFlags().isStatic()) {
+ return;
+ }
- markDirectStaticOrConstructorMethodAsLive(resolvedMethod, reason);
+ markDirectStaticOrConstructorMethodAsLive(resolvedMethod, reason);
- // It is valid to have an invoke-direct instruction in a default interface method that
- // targets another default method in the same interface. In a class, that would lead
- // to a verification error. See also testInvokeSpecialToDefaultMethod.
- if (resolvedMethod.getDefinition().isNonPrivateVirtualMethod()
- && virtualMethodsTargetedByInvokeDirect.add(resolvedMethod.getReference())) {
- worklist.enqueueMarkMethodLiveAction(resolvedMethod, context, reason);
- }
- });
+ // It is valid to have an invoke-direct instruction in a default interface method that
+ // targets another default method in the same interface. In a class, that would lead
+ // to a verification error. See also testInvokeSpecialToDefaultMethod.
+ if (resolvedMethod.getDefinition().isNonPrivateVirtualMethod()
+ && virtualMethodsTargetedByInvokeDirect.add(resolvedMethod.getReference())) {
+ worklist.enqueueMarkMethodLiveAction(resolvedMethod, context, reason);
+ }
+ });
+ return resolutionResults;
}
private void ensureFromLibraryOrThrow(DexType type, DexLibraryClass context) {
@@ -3343,89 +3386,91 @@
liveTypes.getItems().forEach(consumer);
}
- private void markVirtualMethodAsReachable(
+ private MethodResolutionResult markVirtualMethodAsReachable(
DexMethod method, boolean interfaceInvoke, ProgramMethod context, KeepReason reason) {
- if (method.holder.isArrayType()) {
+ MethodResolutionResult resolutionResults =
+ resolveMethod(method, context, reason, interfaceInvoke);
+ if (method.getHolderType().isArrayType()) {
// This is an array type, so the actual class will be generated at runtime. We treat this
// like an invoke on a direct subtype of java.lang.Object that has no further subtypes.
// As it has no subtypes, it cannot affect liveness of the program we are processing.
// Ergo, we can ignore it. We need to make sure that the element type is available, though.
- markTypeAsLive(method.holder, context, reason);
- return;
+ markTypeAsLive(method.getHolderType(), context, reason);
+ return resolutionResults;
}
- resolveMethod(method, context, reason, interfaceInvoke)
- .forEachMethodResolutionResult(
- resolutionResult -> {
- if (!resolutionResult.isSingleResolution()) {
- return;
- }
- SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
- // Note that all virtual methods derived from library methods are kept regardless of
- // being reachable, so the following only needs to consider reachable targets in the
- // program.
- // TODO(b/70160030): Revise this to support tree shaking library methods on
- // non-escaping types.
- DexProgramClass initialResolutionHolder =
- resolution.getInitialResolutionHolder().asProgramClass();
- if (initialResolutionHolder == null) {
- recordMethodReference(method, context);
- return;
- }
+ resolutionResults.forEachMethodResolutionResult(
+ resolutionResult -> {
+ if (!resolutionResult.isSingleResolution()) {
+ return;
+ }
+ SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
+ // Note that all virtual methods derived from library methods are kept regardless of
+ // being reachable, so the following only needs to consider reachable targets in the
+ // program.
+ // TODO(b/70160030): Revise this to support tree shaking library methods on
+ // non-escaping types.
+ DexProgramClass initialResolutionHolder =
+ resolution.getInitialResolutionHolder().asProgramClass();
+ if (initialResolutionHolder == null) {
+ recordMethodReference(method, context);
+ return;
+ }
- if (resolution.getResolvedHolder().isNotProgramClass()) {
- // TODO(b/70160030): If the resolution is on a library method, then the keep edge
- // needs to go directly to the target method in the program. Thus this method will
- // need to ensure that 'reason' is not already reported (eg, must be delayed /
- // non-witness) and report that for each possible target edge below.
- return;
- }
+ if (resolution.getResolvedHolder().isNotProgramClass()) {
+ // TODO(b/70160030): If the resolution is on a library method, then the keep edge
+ // needs to go directly to the target method in the program. Thus this method will
+ // need to ensure that 'reason' is not already reported (eg, must be delayed /
+ // non-witness) and report that for each possible target edge below.
+ return;
+ }
- DexProgramClass contextHolder = context.getContextClass();
- // If the method has already been marked, just report the new reason for the resolved
- // target and save the context to ensure correct lookup of virtual dispatch targets.
- ResolutionSearchKey resolutionSearchKey =
- new ResolutionSearchKey(method, interfaceInvoke);
- ProgramMethodSet seenContexts =
- getReachableVirtualTargets(initialResolutionHolder).get(resolutionSearchKey);
- if (seenContexts != null) {
- seenContexts.add(context);
- graphReporter.registerMethod(resolution.getResolvedMethod(), reason);
- return;
- }
+ DexProgramClass contextHolder = context.getContextClass();
+ // If the method has already been marked, just report the new reason for the resolved
+ // target and save the context to ensure correct lookup of virtual dispatch targets.
+ ResolutionSearchKey resolutionSearchKey =
+ new ResolutionSearchKey(method, interfaceInvoke);
+ ProgramMethodSet seenContexts =
+ getReachableVirtualTargets(initialResolutionHolder).get(resolutionSearchKey);
+ if (seenContexts != null) {
+ seenContexts.add(context);
+ graphReporter.registerMethod(resolution.getResolvedMethod(), reason);
+ return;
+ }
- // We have to mark the resolution targeted, even if it does not become live, we
- // need at least an abstract version of it so that it can be targeted.
- DexProgramClass resolvedHolder = resolution.getResolvedHolder().asProgramClass();
- DexEncodedMethod resolvedMethod = resolution.getResolvedMethod();
- markMethodAsTargeted(new ProgramMethod(resolvedHolder, resolvedMethod), reason);
- if (resolution.isAccessibleForVirtualDispatchFrom(contextHolder, appView).isFalse()) {
- // Not accessible from this context, so this call will cause a runtime exception.
- return;
- }
+ // We have to mark the resolution targeted, even if it does not become live, we
+ // need at least an abstract version of it so that it can be targeted.
+ DexProgramClass resolvedHolder = resolution.getResolvedHolder().asProgramClass();
+ DexEncodedMethod resolvedMethod = resolution.getResolvedMethod();
+ markMethodAsTargeted(new ProgramMethod(resolvedHolder, resolvedMethod), reason);
+ if (resolution.isAccessibleForVirtualDispatchFrom(contextHolder, appView).isFalse()) {
+ // Not accessible from this context, so this call will cause a runtime exception.
+ return;
+ }
- // The method resolved and is accessible, so currently live overrides become live.
- reachableVirtualTargets
- .computeIfAbsent(initialResolutionHolder, ignoreArgument(HashMap::new))
- .computeIfAbsent(resolutionSearchKey, ignoreArgument(ProgramMethodSet::create))
- .add(context);
+ // The method resolved and is accessible, so currently live overrides become live.
+ reachableVirtualTargets
+ .computeIfAbsent(initialResolutionHolder, ignoreArgument(HashMap::new))
+ .computeIfAbsent(resolutionSearchKey, ignoreArgument(ProgramMethodSet::create))
+ .add(context);
- resolution
- .lookupVirtualDispatchTargets(
- contextHolder,
- appView,
- (type, subTypeConsumer, lambdaConsumer) ->
- objectAllocationInfoCollection.forEachInstantiatedSubType(
- type, subTypeConsumer, lambdaConsumer, appInfo),
- definition -> keepInfo.isPinned(definition, options, appInfo))
- .forEach(
- target ->
- markVirtualDispatchTargetAsLive(
- target,
- programMethod ->
- graphReporter.reportReachableMethodAsLive(
- resolvedMethod.getReference(), programMethod)));
- });
+ resolution
+ .lookupVirtualDispatchTargets(
+ contextHolder,
+ appView,
+ (type, subTypeConsumer, lambdaConsumer) ->
+ objectAllocationInfoCollection.forEachInstantiatedSubType(
+ type, subTypeConsumer, lambdaConsumer, appInfo),
+ definition -> keepInfo.isPinned(definition, options, appInfo))
+ .forEach(
+ target ->
+ markVirtualDispatchTargetAsLive(
+ target,
+ programMethod ->
+ graphReporter.reportReachableMethodAsLive(
+ resolvedMethod.getReference(), programMethod)));
+ });
+ return resolutionResults;
}
private void markVirtualDispatchTargetAsLive(
@@ -3542,54 +3587,56 @@
}
// Package protected due to entry point from worklist.
- void markSuperMethodAsReachable(DexMethod reference, ProgramMethod from) {
- KeepReason reason = KeepReason.targetedBySuperFrom(from);
- resolveMethod(reference, from, reason)
- .forEachMethodResolutionResult(
- resolutionResult -> {
- if (!resolutionResult.isSingleResolution()) {
- return;
- }
- SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
- // If the resolution is in the program, mark it targeted.
- if (resolution.getResolvedHolder().isProgramClass()) {
- markMethodAsTargeted(
- new ProgramMethod(
- resolution.getResolvedHolder().asProgramClass(),
- resolution.getResolvedMethod()),
- reason);
- }
- // If invoke target is invalid (inaccessible or not an instance-method) record it and
- // stop.
- DexClassAndMethod target =
- resolution.lookupInvokeSuperTarget(from.getHolder(), appView);
- if (target == null) {
- failedMethodResolutionTargets.add(resolution.getResolvedMethod().getReference());
- analyses.forEach(
- analyses ->
- analyses.notifyFailedMethodResolutionTarget(
- resolution.getResolvedMethod(), worklist));
- return;
- }
+ void markSuperMethodAsReachable(DexMethod reference, ProgramMethod context) {
+ KeepReason reason = KeepReason.targetedBySuperFrom(context);
+ MethodResolutionResult resolutionResults = resolveMethod(reference, context, reason);
+ resolutionResults.forEachMethodResolutionResult(
+ resolutionResult -> {
+ if (!resolutionResult.isSingleResolution()) {
+ return;
+ }
+ SingleResolutionResult<?> resolution = resolutionResult.asSingleResolution();
+ // If the resolution is in the program, mark it targeted.
+ if (resolution.getResolvedHolder().isProgramClass()) {
+ markMethodAsTargeted(
+ new ProgramMethod(
+ resolution.getResolvedHolder().asProgramClass(),
+ resolution.getResolvedMethod()),
+ reason);
+ }
+ // If invoke target is invalid (inaccessible or not an instance-method) record it and
+ // stop.
+ DexClassAndMethod target =
+ resolution.lookupInvokeSuperTarget(context.getHolder(), appView);
+ if (target == null) {
+ failedMethodResolutionTargets.add(resolution.getResolvedMethod().getReference());
+ analyses.forEach(
+ analyses ->
+ analyses.notifyFailedMethodResolutionTarget(
+ resolution.getResolvedMethod(), worklist));
+ return;
+ }
- DexProgramClass clazz = target.getHolder().asProgramClass();
- if (clazz == null) {
- return;
- }
+ DexProgramClass clazz = target.getHolder().asProgramClass();
+ if (clazz == null) {
+ return;
+ }
- ProgramMethod method = target.asProgramMethod();
+ ProgramMethod method = target.asProgramMethod();
- if (superInvokeDependencies
- .computeIfAbsent(from.getDefinition(), ignore -> ProgramMethodSet.create())
- .add(method)) {
- if (liveMethods.contains(from)) {
- markMethodAsTargeted(method, KeepReason.invokedViaSuperFrom(from));
- if (!target.getAccessFlags().isAbstract()) {
- markVirtualMethodAsLive(method, KeepReason.invokedViaSuperFrom(from));
- }
- }
+ if (superInvokeDependencies
+ .computeIfAbsent(context.getDefinition(), ignore -> ProgramMethodSet.create())
+ .add(method)) {
+ if (liveMethods.contains(context)) {
+ markMethodAsTargeted(method, KeepReason.invokedViaSuperFrom(context));
+ if (!target.getAccessFlags().isAbstract()) {
+ markVirtualMethodAsLive(method, KeepReason.invokedViaSuperFrom(context));
}
- });
+ }
+ }
+ });
+ invokeAnalyses.forEach(
+ analysis -> analysis.traceInvokeSuper(reference, resolutionResults, context));
}
// Returns the set of live types.
diff --git a/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java b/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
index 5b6511d..045227d 100644
--- a/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
+++ b/src/main/java/com/android/tools/r8/shaking/RuntimeTypeCheckInfo.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.shaking;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
@@ -83,22 +84,22 @@
}
@Override
- public void traceCheckCast(DexType type, ProgramMethod context) {
+ public void traceCheckCast(DexType type, DexClass clazz, ProgramMethod context) {
add(type, checkCastTypes);
}
@Override
- public void traceSafeCheckCast(DexType type, ProgramMethod context) {
+ public void traceSafeCheckCast(DexType type, DexClass clazz, ProgramMethod context) {
// Intentionally empty.
}
@Override
- public void traceInstanceOf(DexType type, ProgramMethod context) {
+ public void traceInstanceOf(DexType type, DexClass clazz, ProgramMethod context) {
add(type, instanceOfTypes);
}
@Override
- public void traceExceptionGuard(DexType guard, ProgramMethod context) {
+ public void traceExceptionGuard(DexType guard, DexClass clazz, ProgramMethod context) {
add(guard, exceptionGuardTypes);
}
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 b71ad68..40b2d19 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -223,6 +223,14 @@
return false;
}
+ public boolean hasFeatureSplitConfiguration() {
+ return featureSplitConfiguration != null;
+ }
+
+ public FeatureSplitConfiguration getFeatureSplitConfiguration() {
+ return featureSplitConfiguration;
+ }
+
public boolean hasProguardConfiguration() {
return proguardConfiguration != null;
}