Revert "Mark methods as library overrides in a final pass after enqueuing"
This reverts commit c57812e79dabfa3324a93033fa64475437748c6a.
Revert "Insert bridges for library targets for memberrebinding"
This reverts commit 4e346053460be40df72c58f21d58864a2aaefded.
Change-Id: I9f04616dd8d76c1d776f0975b7a3dc89906421a6
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 14cac77..71898e2 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -700,8 +700,17 @@
appView.setGraphLens(memberRebindingIdentityLens);
// Remove redundant bridges that have been inserted for member rebinding.
- new RedundantBridgeRemover(appView.withLiveness())
- .run(memberRebindingIdentityLens, executorService);
+ // This can only be done if we have AppInfoWithLiveness.
+ if (appView.appInfo().hasLiveness()) {
+ new RedundantBridgeRemover(appView.withLiveness())
+ .run(memberRebindingIdentityLens, executorService);
+ } else {
+ // If we don't have AppInfoWithLiveness here, it must be because we are not shrinking. When
+ // we are not shrinking, we can't move visibility bridges. In principle, though, it would be
+ // possible to remove visibility bridges that have been synthesized by R8, but we currently
+ // do not have this information.
+ assert !options.isShrinking();
+ }
if (appView.appInfo().hasLiveness()) {
SyntheticFinalization.finalizeWithLiveness(appView.withLiveness(), executorService, timing);
diff --git a/src/main/java/com/android/tools/r8/graph/ClasspathOrLibraryClass.java b/src/main/java/com/android/tools/r8/graph/ClasspathOrLibraryClass.java
index 78de6f7..d666539 100644
--- a/src/main/java/com/android/tools/r8/graph/ClasspathOrLibraryClass.java
+++ b/src/main/java/com/android/tools/r8/graph/ClasspathOrLibraryClass.java
@@ -15,10 +15,4 @@
static ClasspathOrLibraryClass asClasspathOrLibraryClass(DexClass clazz) {
return clazz != null ? clazz.asClasspathOrLibraryClass() : null;
}
-
- DexEncodedMethod lookupMethod(DexMethod method);
-
- DexEncodedMethod lookupVirtualMethod(DexMethod method);
-
- Iterable<DexEncodedMethod> virtualMethods();
}
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index 675d2df..d0417b4 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -73,10 +73,6 @@
public abstract String toString(DexEncodedMethod method, RetracerForCodePrinting retracer);
- public boolean passThroughDesugarAndIRConversion() {
- return false;
- }
-
public boolean isCfCode() {
return false;
}
@@ -129,14 +125,6 @@
return false;
}
- public boolean isMemberRebindingBridgeCode() {
- return false;
- }
-
- public MemberRebindingBridgeCode asMemberRebindingBridgeCode() {
- return null;
- }
-
public ThrowNullCode asThrowNullCode() {
return null;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
index dc2949c..165ff81 100644
--- a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
@@ -67,11 +67,6 @@
return INSTANCE;
}
- @Override
- public boolean passThroughDesugarAndIRConversion() {
- return true;
- }
-
public static boolean canonicalizeCodeIfPossible(AppView<?> appView, ProgramMethod method) {
if (hasDefaultInstanceInitializerCode(method, appView)) {
method.setCode(get(), appView);
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 2e2755d..411e5ee 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -517,12 +517,6 @@
public final DexType retentionType =
createStaticallyKnownType("Ljava/lang/annotation/Retention;");
- public final DexType recentlyNonNull =
- createStaticallyKnownType("Landroidx/annotation/RecentlyNonNull;");
- public final DexType recentlyNullable =
- createStaticallyKnownType("Landroidx/annotation/RecentlyNullable;");
- public final DexType nullable = createStaticallyKnownType("Landroidx/annotation/Nullable;");
- public final DexType nonNull = createStaticallyKnownType("Landroidx/annotation/NonNull;");
public final DexType runtimeExceptionType = createStaticallyKnownType(runtimeExceptionDescriptor);
public final DexType assertionErrorType = createStaticallyKnownType(assertionErrorDescriptor);
public final DexType throwableType = createStaticallyKnownType(throwableDescriptor);
diff --git a/src/main/java/com/android/tools/r8/graph/MemberRebindingBridgeCode.java b/src/main/java/com/android/tools/r8/graph/MemberRebindingBridgeCode.java
deleted file mode 100644
index 9c136e8..0000000
--- a/src/main/java/com/android/tools/r8/graph/MemberRebindingBridgeCode.java
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2022, 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;
-
-import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.graph.proto.RewrittenPrototypeDescription;
-import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.InvokeSuper;
-import com.android.tools.r8.ir.code.NumberGenerator;
-import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.ir.code.Position.SyntheticPosition;
-import com.android.tools.r8.ir.code.Return;
-import com.android.tools.r8.ir.conversion.IRBuilder;
-import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
-import com.android.tools.r8.ir.conversion.MethodConversionOptions.ThrowingMethodConversionOptions;
-import com.android.tools.r8.ir.conversion.SyntheticStraightLineSourceCode;
-import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.RetracerForCodePrinting;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
-import java.util.function.Consumer;
-
-public class MemberRebindingBridgeCode extends Code {
-
- private final DexMethod target;
- private final boolean isInterface;
-
- private MemberRebindingBridgeCode(DexMethod target, boolean isInterface) {
- this.target = target;
- this.isInterface = isInterface;
- }
-
- @Override
- public boolean isMemberRebindingBridgeCode() {
- return true;
- }
-
- public DexMethod getTarget() {
- return target;
- }
-
- public boolean getInterface() {
- return isInterface;
- }
-
- @Override
- public boolean passThroughDesugarAndIRConversion() {
- return true;
- }
-
- @Override
- public MemberRebindingBridgeCode asMemberRebindingBridgeCode() {
- return this;
- }
-
- @Override
- public IRCode buildIR(
- ProgramMethod method,
- AppView<?> appView,
- Origin origin,
- MutableMethodConversionOptions conversionOptions) {
- DexMethod originalMethod =
- appView.graphLens().getOriginalMethodSignature(method.getReference());
- MemberRebindingBridgeSourceCode source =
- new MemberRebindingBridgeSourceCode(originalMethod, this.target, isInterface);
- return IRBuilder.create(method, appView, source, origin).build(method, conversionOptions);
- }
-
- @Override
- public IRCode buildInliningIR(
- ProgramMethod context,
- ProgramMethod method,
- AppView<?> appView,
- GraphLens codeLens,
- NumberGenerator valueNumberGenerator,
- Position callerPosition,
- Origin origin,
- RewrittenPrototypeDescription protoChanges) {
- DexMethod originalMethod =
- appView.graphLens().getOriginalMethodSignature(method.getReference());
- MemberRebindingBridgeSourceCode source =
- new MemberRebindingBridgeSourceCode(
- originalMethod, this.target, isInterface, callerPosition);
- return IRBuilder.createForInlining(
- method, appView, codeLens, source, origin, valueNumberGenerator, protoChanges)
- .build(context, new ThrowingMethodConversionOptions(appView.options()));
- }
-
- @Override
- public void registerCodeReferences(ProgramMethod method, UseRegistry registry) {
- registry.registerInvokeSuper(this.target);
- }
-
- @Override
- public void registerCodeReferencesForDesugaring(ClasspathMethod method, UseRegistry registry) {
- registry.registerInvokeSuper(this.target);
- }
-
- @Override
- public String toString() {
- return "<member-rebinding-bridge-code>";
- }
-
- @Override
- public String toString(DexEncodedMethod method, RetracerForCodePrinting retracer) {
- StringBuilder builder = new StringBuilder();
- if (method != null) {
- builder.append(method.toSourceString()).append("\n");
- }
- return builder.append(this).toString();
- }
-
- @Override
- public int estimatedDexCodeSizeUpperBoundInBytes() {
- throw new Unreachable();
- }
-
- @Override
- public boolean isEmptyVoidMethod() {
- return false;
- }
-
- @Override
- protected int computeHashCode() {
- return System.identityHashCode(this);
- }
-
- @Override
- protected boolean computeEquals(Object other) {
- return this == other;
- }
-
- @Override
- public boolean isSharedCodeObject() {
- return true;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- static class MemberRebindingBridgeSourceCode extends SyntheticStraightLineSourceCode {
-
- MemberRebindingBridgeSourceCode(DexMethod context, DexMethod method, boolean isInterface) {
- this(context, method, isInterface, null);
- }
-
- MemberRebindingBridgeSourceCode(
- DexMethod context, DexMethod method, boolean isInterface, Position callerPosition) {
- super(
- getInstructionBuilders(method, isInterface),
- SyntheticPosition.builder()
- .setLine(0)
- .setMethod(context)
- .setCallerPosition(callerPosition)
- .build());
- }
-
- private static List<Consumer<IRBuilder>> getInstructionBuilders(
- DexMethod method, boolean isInterface) {
- return ImmutableList.of(
- builder -> {
- InvokeSuper invokeSuper =
- InvokeSuper.builder()
- .setMethod(method)
- .setArguments(
- ListUtils.newArrayList(
- builder.getReceiverValue(), builder.getArgumentValues()))
- .setInterface(isInterface)
- .applyIf(
- !method.getReturnType().isVoidType(),
- b -> b.setFreshOutValue(builder.appView, builder))
- .build();
- builder.add(invokeSuper);
- builder.addReturn(new Return(invokeSuper.outValue()));
- });
- }
- }
-
- public static class Builder {
-
- private DexMethod target;
- private boolean isInterface;
-
- public Builder setTarget(DexMethod target) {
- this.target = target;
- return this;
- }
-
- public Builder setInterface(boolean isInterface) {
- this.isInterface = isInterface;
- return this;
- }
-
- public MemberRebindingBridgeCode build() {
- assert target != null;
- return new MemberRebindingBridgeCode(target, isInterface);
- }
- }
-}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
index 085d96d..12da839 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessFlags.java
@@ -7,7 +7,6 @@
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.function.BooleanSupplier;
-import java.util.function.Consumer;
public class MethodAccessFlags extends AccessFlags<MethodAccessFlags> {
@@ -265,17 +264,17 @@
public Builder set(int flag) {
flags.set(flag);
- return self();
+ return this;
}
public Builder setBridge() {
flags.setBridge();
- return self();
+ return this;
}
public Builder setConstructor() {
flags.setConstructor();
- return self();
+ return this;
}
public Builder setStrict(boolean value) {
@@ -284,7 +283,7 @@
} else {
flags.unsetStrict();
}
- return self();
+ return this;
}
public Builder setSynchronized(boolean value) {
@@ -293,23 +292,7 @@
} else {
flags.unsetSynchronized();
}
- return self();
- }
-
- public Builder setAbstract(boolean value) {
- if (value) {
- flags.setAbstract();
- } else {
- flags.unsetAbstract();
- }
- return self();
- }
-
- public Builder applyIf(boolean condition, Consumer<Builder> consumer) {
- if (condition) {
- consumer.accept(self());
- }
- return self();
+ return this;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
index ef7586a..8c949fe 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodResolutionResult.java
@@ -183,12 +183,6 @@
public abstract LookupMethodTarget lookupVirtualDispatchTarget(
DexClass dynamicInstance, AppInfoWithClassHierarchy appInfo);
- public abstract LookupMethodTarget lookupVirtualDispatchTarget(
- DexClass dynamicInstance,
- AppInfoWithClassHierarchy appInfo,
- Consumer<DexType> typeCausingFailureConsumer,
- Consumer<? super DexEncodedMethod> methodCausingFailureConsumer);
-
public abstract LookupTarget lookupVirtualDispatchTarget(
LambdaDescriptor lambdaInstance,
AppInfoWithClassHierarchy appInfo,
@@ -554,9 +548,9 @@
lookupVirtualDispatchTarget(
subClass,
appInfo,
+ resolvedHolder.type,
resultBuilder::addTypeCausingFailure,
- resultBuilder::addMethodCausingFailure,
- resolvedHolder.type);
+ resultBuilder::addMethodCausingFailure);
if (lookupTarget != null) {
incompleteness.checkDexClassAndMethod(lookupTarget);
addVirtualDispatchTarget(lookupTarget, resolvedHolder.isInterface(), resultBuilder);
@@ -704,21 +698,7 @@
public LookupMethodTarget lookupVirtualDispatchTarget(
DexClass dynamicInstance, AppInfoWithClassHierarchy appInfo) {
return lookupVirtualDispatchTarget(
- dynamicInstance, appInfo, emptyConsumer(), emptyConsumer());
- }
-
- @Override
- public LookupMethodTarget lookupVirtualDispatchTarget(
- DexClass dynamicInstance,
- AppInfoWithClassHierarchy appInfo,
- Consumer<DexType> typeCausingFailureConsumer,
- Consumer<? super DexEncodedMethod> methodCausingFailureConsumer) {
- return lookupVirtualDispatchTarget(
- dynamicInstance,
- appInfo,
- typeCausingFailureConsumer,
- methodCausingFailureConsumer,
- initialResolutionHolder.type);
+ dynamicInstance, appInfo, initialResolutionHolder.type, emptyConsumer(), emptyConsumer());
}
@Override
@@ -744,9 +724,9 @@
private LookupMethodTarget lookupVirtualDispatchTarget(
DexClass dynamicInstance,
AppInfoWithClassHierarchy appInfo,
+ DexType resolutionHolder,
Consumer<DexType> typeCausingFailureConsumer,
- Consumer<? super DexEncodedMethod> methodCausingFailureConsumer,
- DexType resolutionHolder) {
+ Consumer<? super DexEncodedMethod> methodCausingFailureConsumer) {
assert appInfo.isSubtype(dynamicInstance.type, resolutionHolder)
: dynamicInstance.type + " is not a subtype of " + resolutionHolder;
// TODO(b/148591377): Enable this assertion.
@@ -1050,15 +1030,6 @@
}
@Override
- public LookupMethodTarget lookupVirtualDispatchTarget(
- DexClass dynamicInstance,
- AppInfoWithClassHierarchy appInfo,
- Consumer<DexType> typeCausingFailureConsumer,
- Consumer<? super DexEncodedMethod> methodCausingFailureConsumer) {
- return null;
- }
-
- @Override
public LookupTarget lookupVirtualDispatchTarget(
LambdaDescriptor lambdaInstance,
AppInfoWithClassHierarchy appInfo,
@@ -1440,15 +1411,6 @@
}
@Override
- public DexClassAndMethod lookupVirtualDispatchTarget(
- DexClass dynamicInstance,
- AppInfoWithClassHierarchy appInfo,
- Consumer<DexType> typeCausingFailureConsumer,
- Consumer<? super DexEncodedMethod> methodCausingFailureConsumer) {
- throw new Unreachable("Should not be called on MultipleFieldResolutionResult");
- }
-
- @Override
public LookupTarget lookupVirtualDispatchTarget(
LambdaDescriptor lambdaInstance,
AppInfoWithClassHierarchy appInfo,
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerLibraryOverrideAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerLibraryOverrideAnalysis.java
deleted file mode 100644
index 5b84a81..0000000
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerLibraryOverrideAnalysis.java
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright (c) 2022, 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 static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
-
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
-import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.ClasspathOrLibraryClass;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.LookupMethodTarget;
-import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
-import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.shaking.Enqueuer;
-import com.android.tools.r8.utils.DepthFirstSearchWorkListBase.StatefulDepthFirstSearchWorkList;
-import com.android.tools.r8.utils.OptionalBool;
-import com.android.tools.r8.utils.TraversalContinuation;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.IdentityHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import java.util.function.Function;
-
-public class EnqueuerLibraryOverrideAnalysis extends EnqueuerAnalysis {
-
- private final Set<ClasspathOrLibraryClass> setWithSingleJavaLangObject;
-
- private final Map<DexClass, LibraryMethodOverridesInHierarchy> libraryClassesInHierarchyCache =
- new IdentityHashMap<>();
- private final AppView<? extends AppInfoWithClassHierarchy> appView;
-
- public EnqueuerLibraryOverrideAnalysis(AppView<? extends AppInfoWithClassHierarchy> appView) {
- this.appView = appView;
- DexClass javaLangObjectClass = appView.definitionFor(appView.dexItemFactory().objectType);
- if (javaLangObjectClass != null && javaLangObjectClass.isNotProgramClass()) {
- setWithSingleJavaLangObject =
- ImmutableSet.of(javaLangObjectClass.asClasspathOrLibraryClass());
- } else {
- setWithSingleJavaLangObject = Collections.emptySet();
- }
- }
-
- @Override
- public void done(Enqueuer enqueuer) {
- Set<DexProgramClass> liveProgramTypes = enqueuer.getLiveProgramTypes();
- ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection =
- enqueuer.getObjectAllocationInfoCollection();
- liveProgramTypes.forEach(
- liveProgramType -> {
- if (!objectAllocationInfoCollection.isInstantiatedDirectly(liveProgramType)) {
- return;
- }
- // Abstract classes cannot be instantiated.
- if (liveProgramType.isAbstract()) {
- return;
- }
- markLibraryOverridesForProgramClass(liveProgramType);
- });
- }
-
- private void markLibraryOverridesForProgramClass(DexProgramClass programClass) {
- LibraryMethodOverridesInHierarchy libraryMethodOverridesInHierarchy =
- ensureLibraryClassesPopulatedForProgramClass(programClass);
- AppInfoWithClassHierarchy appInfoWithClassHierarchy = appView.appInfo();
- libraryMethodOverridesInHierarchy.forEachOverriddenMethod(
- (libraryClass, method) ->
- appInfoWithClassHierarchy
- .resolveMethodOn(libraryClass.asDexClass(), method.getReference())
- .forEachMethodResolutionResult(
- result -> {
- LookupMethodTarget lookupTarget =
- result.lookupVirtualDispatchTarget(
- programClass,
- appInfoWithClassHierarchy,
- emptyConsumer(),
- failingMethod -> {
- DexClass holderClass =
- appInfoWithClassHierarchy.definitionFor(
- failingMethod.getContextType());
- if (holderClass != null && holderClass.isProgramClass()) {
- failingMethod.setLibraryMethodOverride(OptionalBool.TRUE);
- }
- });
- if (lookupTarget != null) {
- DexEncodedMethod definition = lookupTarget.getDefinition();
- definition.setLibraryMethodOverride(OptionalBool.TRUE);
- }
- }));
- }
-
- /***
- * Populating the library state for an instantiated program class is done by a DFS
- * algorithm where we compute all library classes in the hierarchy and then, when doing backtracking, we check if a program method has a corresponding
- * definition in one of its library classes. If a program method potentially overrides a library
- * method we keep track of it for simulating virtual dispatch on it later.
- *
- * A special care has to be taken here when interfaces contributing to classes later in the
- * hierarchy than the override:
- * <pre>
- * class ProgramA {
- * foo() {...}
- * }
- *
- * interface Lib {
- * foo();
- * }
- *
- * class ProgramB extends ProgramA implements Lib { }
- * </pre>
- *
- * This pattern does not satisfy the DFS algorithm since ProgramB do not directly override any
- * methods in Lib. As a consequence we always consider all interface methods to be overridden. In
- * general this is almost always the case since we do not see many default library methods in the
- * library.
- *
- * @return the computed library method override state for this program class.
- */
- private LibraryMethodOverridesInHierarchy ensureLibraryClassesPopulatedForProgramClass(
- DexProgramClass clazz) {
- new StatefulDepthFirstSearchWorkList<DexClass, LibraryMethodOverridesInHierarchy, Void>() {
-
- @Override
- @SuppressWarnings("ReturnValueIgnored")
- protected TraversalContinuation<Void, LibraryMethodOverridesInHierarchy> process(
- DFSNodeWithState<DexClass, LibraryMethodOverridesInHierarchy> node,
- Function<DexClass, DFSNodeWithState<DexClass, LibraryMethodOverridesInHierarchy>>
- childNodeConsumer) {
- DexClass clazz = node.getNode();
- LibraryMethodOverridesInHierarchy libraryMethodOverridesInHierarchy =
- libraryClassesInHierarchyCache.get(clazz);
- if (libraryMethodOverridesInHierarchy != null) {
- node.setState(libraryMethodOverridesInHierarchy);
- } else {
- clazz.forEachImmediateSupertype(
- superType ->
- appView
- .contextIndependentDefinitionForWithResolutionResult(superType)
- .forEachClassResolutionResult(childNodeConsumer::apply));
- }
- return TraversalContinuation.doContinue();
- }
-
- @Override
- protected TraversalContinuation<Void, LibraryMethodOverridesInHierarchy> joiner(
- DFSNodeWithState<DexClass, LibraryMethodOverridesInHierarchy> node,
- List<DFSNodeWithState<DexClass, LibraryMethodOverridesInHierarchy>> childStates) {
- DexClass clazz = node.getNode();
- if (node.getState() == null) {
- LibraryMethodOverridesInHierarchy.Builder builder =
- LibraryMethodOverridesInHierarchy.builder();
- childStates.forEach(childState -> builder.addParentState(childState.getState()));
- if (clazz.isNotProgramClass()) {
- builder.addLibraryClass(clazz.asClasspathOrLibraryClass());
- }
- builder.buildLibraryClasses(setWithSingleJavaLangObject);
- if (clazz.isProgramClass()) {
- clazz
- .asProgramClass()
- .virtualProgramMethods()
- .forEach(builder::addLibraryOverridesForMethod);
- }
- LibraryMethodOverridesInHierarchy newState = builder.build();
- node.setState(newState);
- LibraryMethodOverridesInHierarchy oldState =
- libraryClassesInHierarchyCache.put(clazz, newState);
- assert oldState == null;
- }
- return TraversalContinuation.doContinue();
- }
- }.run(clazz);
-
- return libraryClassesInHierarchyCache.get(clazz);
- }
-
- /***
- * The LibraryMethodOverridesInHierarchy keeps track of the library classes and the potential
- * overridden library methods for each class in the hierarchy of a class. The libraryClasses are
- * a flattened list of all library classes that exists in the hierarchy and the overriden library
- * methods is a map of methods that may be overridden for the current class.
- */
- private static class LibraryMethodOverridesInHierarchy {
-
- private final List<LibraryMethodOverridesInHierarchy> parentStates;
- private final Set<ClasspathOrLibraryClass> libraryClasses;
- private final Map<DexEncodedMethod, ClasspathOrLibraryClass> overriddenLibraryMethods;
-
- private LibraryMethodOverridesInHierarchy(
- List<LibraryMethodOverridesInHierarchy> parentStates,
- Set<ClasspathOrLibraryClass> libraryClasses,
- Map<DexEncodedMethod, ClasspathOrLibraryClass> overriddenLibraryMethods) {
- this.parentStates = parentStates;
- this.libraryClasses = libraryClasses;
- this.overriddenLibraryMethods = overriddenLibraryMethods;
- }
-
- public void forEachOverriddenMethod(
- BiConsumer<ClasspathOrLibraryClass, DexEncodedMethod> consumer) {
- forEachOverriddenMethod(consumer, Sets.newIdentityHashSet());
- }
-
- private void forEachOverriddenMethod(
- BiConsumer<ClasspathOrLibraryClass, DexEncodedMethod> consumer,
- Set<DexEncodedMethod> seen) {
- overriddenLibraryMethods.forEach(
- (method, clazz) -> {
- if (seen.add(method)) {
- consumer.accept(clazz, method);
- }
- });
- parentStates.forEach(parentState -> parentState.forEachOverriddenMethod(consumer, seen));
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static class Builder {
-
- private Map<DexEncodedMethod, ClasspathOrLibraryClass> overriddenLibraryMethods;
- private Set<ClasspathOrLibraryClass> libraryClasses;
- private final List<LibraryMethodOverridesInHierarchy> parentStates = new ArrayList<>();
- private boolean hasBuildLibraryClasses = false;
-
- public void addParentState(LibraryMethodOverridesInHierarchy state) {
- assert !hasBuildLibraryClasses;
- parentStates.add(state);
- }
-
- public void addLibraryClass(ClasspathOrLibraryClass libraryClass) {
- ensureLibraryClasses();
- libraryClasses.add(libraryClass);
- if (libraryClass.isInterface()) {
- ensureOverriddenLibraryMethods();
- libraryClass
- .virtualMethods()
- .forEach(
- virtualMethod ->
- overriddenLibraryMethods.putIfAbsent(virtualMethod, libraryClass));
- }
- }
-
- private void ensureLibraryClasses() {
- if (libraryClasses == null) {
- libraryClasses = new LinkedHashSet<>();
- }
- }
-
- private void buildLibraryClasses(Set<ClasspathOrLibraryClass> setWithSingleJavaLangObject) {
- if (libraryClasses != null) {
- parentStates.forEach(parentState -> libraryClasses.addAll(parentState.libraryClasses));
- } else if (parentStates.size() == 1) {
- libraryClasses = parentStates.get(0).libraryClasses;
- } else {
- libraryClasses = new LinkedHashSet<>();
- for (LibraryMethodOverridesInHierarchy parentState : parentStates) {
- libraryClasses.addAll(parentState.libraryClasses);
- }
- if (libraryClasses.size() == 1) {
- assert libraryClasses.equals(setWithSingleJavaLangObject);
- libraryClasses = setWithSingleJavaLangObject;
- }
- }
- hasBuildLibraryClasses = true;
- }
-
- private void addLibraryOverridesForMethod(ProgramMethod method) {
- assert hasBuildLibraryClasses;
- DexMethod reference = method.getReference();
- libraryClasses.forEach(
- libraryClass -> {
- if (libraryClass.isInterface()) {
- // All interface methods are already added when visiting.
- return;
- }
- DexEncodedMethod libraryMethod = libraryClass.lookupVirtualMethod(reference);
- if (libraryMethod != null) {
- addOverriddenMethod(libraryClass, libraryMethod);
- }
- });
- }
-
- private void addOverriddenMethod(ClasspathOrLibraryClass clazz, DexEncodedMethod method) {
- ensureOverriddenLibraryMethods();
- ClasspathOrLibraryClass existing = overriddenLibraryMethods.put(method, clazz);
- assert existing == null;
- }
-
- private void ensureOverriddenLibraryMethods() {
- if (overriddenLibraryMethods == null) {
- overriddenLibraryMethods = new IdentityHashMap<>();
- }
- }
-
- public LibraryMethodOverridesInHierarchy build() {
- return new LibraryMethodOverridesInHierarchy(
- parentStates,
- libraryClasses,
- overriddenLibraryMethods == null ? Collections.emptyMap() : overriddenLibraryMethods);
- }
- }
- }
-}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 2cef6fe..c99ee11 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -47,7 +47,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -1686,18 +1685,6 @@
return self();
}
- public B apply(Consumer<B> consumer) {
- consumer.accept(self());
- return self();
- }
-
- public B applyIf(boolean condition, Consumer<B> consumer) {
- if (condition) {
- consumer.accept(self());
- }
- return self();
- }
-
public B setPosition(Instruction other) {
return setPosition(other.getPosition());
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
index 0fd2dc9..ae47eb6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
@@ -140,28 +140,4 @@
void internalRegisterUse(UseRegistry<?> registry, DexClassAndMethod context) {
registry.registerInvokeSuper(getInvokedMethod());
}
-
- public static Builder builder() {
- return new Builder();
- }
-
- public static class Builder extends InvokeMethod.Builder<InvokeSuper.Builder, InvokeSuper> {
-
- private boolean isInterface;
-
- @Override
- public InvokeSuper build() {
- return amend(new InvokeSuper(method, outValue, arguments, isInterface));
- }
-
- public Builder setInterface(boolean isInterface) {
- this.isInterface = isInterface;
- return self();
- }
-
- @Override
- public Builder self() {
- return this;
- }
- }
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index cb45923..4a29cb6 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -114,7 +114,6 @@
import com.android.tools.r8.ir.code.Throw;
import com.android.tools.r8.ir.code.Ushr;
import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.code.ValueFactory;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.code.ValueTypeConstraint;
import com.android.tools.r8.ir.code.Xor;
@@ -149,11 +148,11 @@
/**
* Builder object for constructing high-level IR from dex bytecode.
*
- * <p>The generated IR is in SSA form. The SSA construction is based on the paper "Simple and
- * Efficient Construction of Static Single Assignment Form" available at
+ * <p>The generated IR is in SSA form. The SSA construction is based on the paper
+ * "Simple and Efficient Construction of Static Single Assignment Form" available at
* http://compilers.cs.uni-saarland.de/papers/bbhlmz13cc.pdf
*/
-public class IRBuilder implements ValueFactory {
+public class IRBuilder {
public static final int INITIAL_BLOCK_OFFSET = -1;
@@ -182,11 +181,6 @@
}
}
- @Override
- public Value createValue(TypeElement type, DebugLocalInfo localInfo) {
- return new Value(valueNumberGenerator.next(), type, localInfo);
- }
-
// SSA construction uses a worklist of basic blocks reachable from the entry and their
// instruction offsets.
private static class WorklistItem {
@@ -1836,7 +1830,7 @@
addReturn(new Return());
}
- public void addReturn(Return ret) {
+ private void addReturn(Return ret) {
// Attach the live locals to the return instruction to avoid a local change on monitor exit.
attachLocalValues(ret);
source.buildPostlude(this);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 73c4b37..f85f8d5 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -1566,7 +1566,7 @@
}
Code code = method.getDefinition().getCode();
assert !code.isThrowNullCode();
- return code.passThroughDesugarAndIRConversion();
+ return code.isDefaultInstanceInitializerCode();
}
// Compute optimization info summary for the current method unless it is pinned
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryConversionCfProvider.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryConversionCfProvider.java
index 40d34cb..94bd06b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryConversionCfProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryConversionCfProvider.java
@@ -208,7 +208,9 @@
.generateCfCode();
DexEncodedMethod newMethod = wrapperSynthesizer.newSynthesizedMethod(methodToInstall, cfCode);
newMethod.setCode(cfCode, DexEncodedMethod.NO_PARAMETER_INFO);
- newMethod.setLibraryMethodOverride(OptionalBool.TRUE);
+ if (method.getDefinition().isLibraryMethodOverride().isTrue()) {
+ newMethod.setLibraryMethodOverride(OptionalBool.TRUE);
+ }
ProgramMethod callback = new ProgramMethod(clazz, newMethod);
assert eventConsumer != null;
eventConsumer.acceptAPIConversionCallback(callback);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
index 5377ecb..5f0bea9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
@@ -608,6 +608,11 @@
}
@Override
+ protected List<Void> getFinalStateForRoots(Collection<? extends StringBuilderNode> roots) {
+ return null;
+ }
+
+ @Override
public TraversalContinuation<Void, Void> joiner(DFSNode<StringBuilderNode> node) {
StringBuilderNode node1 = node.getNode();
processingOrder.add(node1);
diff --git a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
index 4c47989..0da73cf 100644
--- a/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/IdentifierMinifier.java
@@ -195,9 +195,7 @@
instructions);
code.asCfCode().setInstructions(newInstructions);
} else {
- assert code.isDefaultInstanceInitializerCode()
- || code.isThrowNullCode()
- || code.isMemberRebindingBridgeCode();
+ assert code.isDefaultInstanceInitializerCode() || code.isThrowNullCode();
}
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 79bbfe6..2ac83b2 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -6,7 +6,6 @@
import static com.android.tools.r8.utils.AndroidApiLevelUtils.isApiSafeForMemberRebinding;
import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
-import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
@@ -19,8 +18,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.LibraryMethod;
-import com.android.tools.r8.graph.MemberRebindingBridgeCode;
-import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodAccessInfoCollection;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
@@ -56,7 +53,6 @@
private final InternalOptions options;
private final MemberRebindingLens.Builder lensBuilder;
- private final Map<DexMethod, DexClassAndMethod> insertedLibraryBridges = new IdentityHashMap<>();
public MemberRebindingAnalysis(AppView<AppInfoWithLiveness> appView) {
assert appView.graphLens().isContextFreeForMethods();
@@ -78,66 +74,69 @@
return original;
}
- if (!invokeType.isSuper() || !options.canHaveSuperInvokeBug()) {
- LibraryMethod eligibleLibraryMethod = null;
- SingleResolutionResult<?> currentResolutionResult = resolutionResult;
- while (currentResolutionResult != null) {
- DexClassAndMethod currentResolvedMethod = currentResolutionResult.getResolutionPair();
- if (canRebindDirectlyToLibraryMethod(
- currentResolvedMethod,
- currentResolutionResult.withInitialResolutionHolder(
- currentResolutionResult.getResolvedHolder()),
- contexts,
- invokeType,
- original)) {
- eligibleLibraryMethod = currentResolvedMethod.asLibraryMethod();
- }
- if (appView.getAssumeInfoCollection().contains(currentResolvedMethod)) {
- break;
- }
- DexClass currentResolvedHolder = currentResolvedMethod.getHolder();
- if (resolvedMethod.getDefinition().belongsToVirtualPool()
- && !currentResolvedHolder.isInterface()
- && currentResolvedHolder.getSuperType() != null) {
- currentResolutionResult =
- appView
- .appInfo()
- .resolveMethodOnClassLegacy(currentResolvedHolder.getSuperType(), original)
- .asSingleResolution();
- } else {
- break;
- }
+ if (invokeType.isSuper() && options.canHaveSuperInvokeBug()) {
+ // To preserve semantics we should find the first library method on the boundary.
+ DexType firstLibraryTarget =
+ firstLibraryClassOrFirstInterfaceTarget(
+ resolutionResult.getResolvedHolder(),
+ appView,
+ resolvedMethod.getReference(),
+ original.getHolderType(),
+ DexClass::lookupMethod);
+ if (firstLibraryTarget == null) {
+ return original;
}
- if (eligibleLibraryMethod != null) {
- return eligibleLibraryMethod.getReference();
+ DexClass libraryHolder = appView.definitionFor(firstLibraryTarget);
+ if (libraryHolder == null) {
+ return original;
}
+ if (libraryHolder == resolvedMethod.getHolder()) {
+ return resolvedMethod.getReference();
+ }
+ return resolvedMethod.getReference().withHolder(libraryHolder, appView.dexItemFactory());
}
- if (resolvedMethod.getDefinition().isStatic()) {
- return original;
+ LibraryMethod eligibleLibraryMethod = null;
+ SingleResolutionResult<?> currentResolutionResult = resolutionResult;
+ while (currentResolutionResult != null) {
+ DexClassAndMethod currentResolvedMethod = currentResolutionResult.getResolutionPair();
+ if (canRebindDirectlyToLibraryMethod(
+ currentResolvedMethod,
+ currentResolutionResult.withInitialResolutionHolder(
+ currentResolutionResult.getResolvedHolder()),
+ contexts,
+ invokeType,
+ original)) {
+ eligibleLibraryMethod = currentResolvedMethod.asLibraryMethod();
+ }
+ if (appView.getAssumeInfoCollection().contains(currentResolvedMethod)) {
+ break;
+ }
+ DexClass currentResolvedHolder = currentResolvedMethod.getHolder();
+ if (resolvedMethod.getDefinition().belongsToVirtualPool()
+ && !currentResolvedHolder.isInterface()
+ && currentResolvedHolder.getSuperType() != null) {
+ currentResolutionResult =
+ appView
+ .appInfo()
+ .resolveMethodOnClassLegacy(currentResolvedHolder.getSuperType(), original)
+ .asSingleResolution();
+ } else {
+ break;
+ }
+ }
+ if (eligibleLibraryMethod != null) {
+ return eligibleLibraryMethod.getReference();
}
- // If we could not find a valid library method to rebind to then create a bridge on the top most
- // program class before crossing into library.
- DexClass newHolder =
- resolvedMethod.getHolder().isInterface()
- ? firstProgramClassForTarget(
- appView, resolvedMethod.getReference(), original.getHolderType())
- : firstProgramClass(appView, original.getHolderType());
- if (newHolder == null || newHolder.isNotProgramClass()) {
- return original;
- }
- // We cannot insert default methods on interfaces after desugaring, so we return the resolved
- // method.
- if (newHolder.isInterface() && !options.canUseDefaultAndStaticInterfaceMethods()) {
- return resolvedMethod.getReference();
- }
- if (!appView.getAssumeInfoCollection().get(resolvedMethod).isEmpty()) {
- return original;
- }
- DexMethod bridge = original.withHolder(newHolder, appView.dexItemFactory());
- insertedLibraryBridges.put(bridge, resolvedMethod);
- return bridge;
+ DexType newHolder =
+ firstLibraryClassOrFirstInterfaceTarget(
+ resolvedMethod.getHolder(),
+ appView,
+ resolvedMethod.getReference(),
+ original.getHolderType(),
+ DexClass::lookupMethod);
+ return newHolder != null ? original.withHolder(newHolder, appView.dexItemFactory()) : original;
}
private boolean canRebindDirectlyToLibraryMethod(
@@ -147,8 +146,8 @@
Type invokeType,
DexMethod original) {
// TODO(b/194422791): It could potentially be that `original.holder` is not a subtype of
- // `resolvedMethod.holder` on all API levels, in which case it is not OK to rebind to the
- // resolved method.
+ // `original.holder` on all API levels, in which case it is not OK to rebind to the resolved
+ // method.
return resolvedMethod.isLibraryMethod()
&& isAccessibleInAllContexts(resolvedMethod, resolutionResult, contexts)
&& !isInvokeSuperToInterfaceMethod(resolvedMethod, invokeType)
@@ -239,34 +238,6 @@
return null;
}
- private static DexClass firstProgramClassForTarget(
- DexDefinitionSupplier definitions, DexMethod target, DexType current) {
- DexClass clazz = definitions.contextIndependentDefinitionFor(current);
- if (clazz == null) {
- return null;
- }
- DexEncodedMethod potential = clazz.lookupMethod(target);
- if (potential != null) {
- // Found, return type.
- return clazz;
- }
- if (clazz.superType != null) {
- DexClass matchingSuper = firstProgramClassForTarget(definitions, target, clazz.superType);
- if (matchingSuper != null) {
- // Found in supertype, return first program class.
- return matchingSuper.isNotProgramClass() ? clazz : matchingSuper;
- }
- }
- for (DexType iface : clazz.getInterfaces()) {
- DexClass matchingIface = firstProgramClassForTarget(definitions, target, iface);
- if (matchingIface != null) {
- // Found in interface, return first program class.
- return matchingIface.isNotProgramClass() ? clazz : matchingIface;
- }
- }
- return null;
- }
-
private static DexType firstLibraryClass(DexDefinitionSupplier definitions, DexType bottom) {
DexClass searchClass = definitions.contextIndependentDefinitionFor(bottom);
while (searchClass != null && searchClass.isProgramClass()) {
@@ -276,21 +247,6 @@
return searchClass != null ? searchClass.getType() : null;
}
- private static DexProgramClass firstProgramClass(
- DexDefinitionSupplier definitions, DexType bottom) {
- DexProgramClass searchClass =
- DexProgramClass.asProgramClassOrNull(definitions.contextIndependentDefinitionFor(bottom));
- while (searchClass != null && searchClass.isProgramClass()) {
- DexClass superClass =
- definitions.definitionFor(searchClass.getSuperType(), searchClass.asProgramClass());
- if (superClass.isNotProgramClass()) {
- return searchClass;
- }
- searchClass = superClass.asProgramClass();
- }
- return null;
- }
-
private MethodResolutionResult resolveMethodOnClass(DexMethod method) {
return appView.appInfo().resolveMethodOnClassLegacy(method.holder, method);
}
@@ -415,7 +371,7 @@
builder -> {
if (!targetDefinition.isAbstract()
&& targetDefinition.getApiLevelForCode().isNotSetApiLevel()) {
- assert !target.isProgramMethod();
+ assert target.isLibraryMethod();
builder.setApiLevelForCode(
appView
.apiLevelCompute()
@@ -424,8 +380,7 @@
appView.computedMinApiLevel()));
}
builder.setIsLibraryMethodOverrideIf(
- !target.isProgramMethod() && !targetDefinition.isStatic(),
- OptionalBool.TRUE);
+ target.isLibraryMethod(), OptionalBool.TRUE);
});
bridgeHolder.addMethod(bridgeMethodDefinition);
}
@@ -557,39 +512,9 @@
computeMethodRebinding(appInfo.getMethodAccessInfoCollection());
recordNonReboundFieldAccesses(executorService);
appInfo.getFieldAccessInfoCollection().flattenAccessContexts();
- insertLibraryBridges();
return lensBuilder.build();
}
- private void insertLibraryBridges() {
- insertedLibraryBridges.forEach(
- (method, resolvedMethod) -> {
- assert !resolvedMethod.isProgramMethod();
- DexProgramClass holder =
- DexProgramClass.asProgramClassOrNull(appView.definitionFor(method.getHolderType()));
- assert holder != null;
- assert !holder.isInterface() || options.canUseDefaultAndStaticInterfaceMethods();
- DexEncodedMethod resolvedDefinition = resolvedMethod.getDefinition();
- holder.addMethod(
- DexEncodedMethod.syntheticBuilder()
- .setMethod(method)
- .setApiLevelForDefinition(resolvedDefinition.getApiLevelForDefinition())
- // Since we could not member rebind to this definition it is at least higher than
- // min-api.
- .setApiLevelForCode(ComputedApiLevel.unknown())
- .setCode(
- MemberRebindingBridgeCode.builder()
- .setTarget(resolvedMethod.getDefinition().getReference())
- .setInterface(resolvedMethod.getHolder().isInterface())
- .build())
- .setAccessFlags(MethodAccessFlags.builder().setPublic().setSynthetic().build())
- .setClassFileVersion(resolvedDefinition.getClassFileVersion())
- .setDeprecated(resolvedDefinition.deprecated)
- .setIsLibraryMethodOverride(OptionalBool.TRUE)
- .build());
- });
- }
-
private boolean verifyFieldAccessCollectionContainsAllNonReboundFieldReferences(
ExecutorService executorService) throws ExecutionException {
Set<DexField> nonReboundFieldReferences = computeNonReboundFieldReferences(executorService);
diff --git a/src/main/java/com/android/tools/r8/optimize/RedundantBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/RedundantBridgeRemover.java
index f3fa401..5cbb1b6 100644
--- a/src/main/java/com/android/tools/r8/optimize/RedundantBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/RedundantBridgeRemover.java
@@ -5,7 +5,6 @@
import static com.android.tools.r8.utils.ThreadUtils.processItems;
-import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -20,6 +19,7 @@
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.optimize.InvokeSingleTargetExtractor.InvokeKind;
import com.android.tools.r8.optimize.redundantbridgeremoval.RedundantBridgeRemovalLens;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.KeepMethodInfo;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.Map;
@@ -29,23 +29,20 @@
public class RedundantBridgeRemover {
- private final AppView<? extends AppInfoWithClassHierarchy> appView;
+ private final AppView<AppInfoWithLiveness> appView;
- public RedundantBridgeRemover(AppView<? extends AppInfoWithClassHierarchy> appView) {
+ public RedundantBridgeRemover(AppView<AppInfoWithLiveness> appView) {
this.appView = appView;
}
private DexClassAndMethod getTargetForRedundantBridge(ProgramMethod method) {
- assert appView.hasLiveness();
DexEncodedMethod definition = method.getDefinition();
BridgeInfo bridgeInfo = definition.getOptimizationInfo().getBridgeInfo();
boolean isBridge = definition.isBridge() || bridgeInfo != null;
- // TODO(b/258176116): We can only remove bridges if they are marked as bridge or abstract.
if (!isBridge || definition.isAbstract()) {
return null;
}
- InvokeSingleTargetExtractor targetExtractor =
- new InvokeSingleTargetExtractor(appView.withLiveness(), method);
+ InvokeSingleTargetExtractor targetExtractor = new InvokeSingleTargetExtractor(appView, method);
method.registerCodeReferences(targetExtractor);
DexMethod target = targetExtractor.getTarget();
// javac-generated visibility forward bridge method has same descriptor (name, signature and
@@ -137,27 +134,12 @@
RedundantBridgeRemovalLens.Builder lensBuilder, ExecutorService executorService)
throws ExecutionException {
Map<DexProgramClass, ProgramMethodSet> bridgesToRemove = new ConcurrentHashMap<>();
- boolean hasLiveness = appView.hasLiveness();
- // If we don't have AppInfoWithLiveness here, it must be because we are not shrinking. When we
- // are not shrinking, we can't remove visibility bridges. In principle, though, it would be
- // possible to remove visibility bridges that have been synthesized by R8, but we currently do
- // not have this information.
- assert hasLiveness || !appView.options().isShrinking();
processItems(
appView.appInfo().classes(),
clazz -> {
ProgramMethodSet bridgesToRemoveForClass = ProgramMethodSet.create();
clazz.forEachProgramMethod(
method -> {
- DexEncodedMethod definition = method.getDefinition();
- if (definition.getCode() != null
- && definition.getCode().isMemberRebindingBridgeCode()) {
- bridgesToRemoveForClass.add(method);
- return;
- }
- if (!hasLiveness) {
- return;
- }
KeepMethodInfo keepInfo = appView.getKeepInfo(method);
if (!keepInfo.isShrinkingAllowed(appView.options())
|| !keepInfo.isOptimizationAllowed(appView.options())) {
@@ -179,7 +161,7 @@
// the target is not public, but still accessible to call sites.
boolean isEligibleForRetargeting =
appView.testing().enableRetargetingConstructorBridgeCalls
- || !definition.isInstanceInitializer();
+ || !method.getDefinition().isInstanceInitializer();
if (isEligibleForRetargeting
&& target.getAccessFlags().isPublic()
&& target.getHolder().isPublic()) {
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 c7a45bc..173c302 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -95,7 +95,6 @@
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.EnqueuerLibraryOverrideAnalysis;
import com.android.tools.r8.graph.analysis.GetArrayOfMissingTypeVerifyErrorWorkaround;
import com.android.tools.r8.graph.analysis.InvokeVirtualToInterfaceVerifyErrorWorkaround;
import com.android.tools.r8.ir.analysis.proto.ProtoEnqueuerUseRegistry;
@@ -536,10 +535,6 @@
return graphReporter;
}
- public Set<DexProgramClass> getLiveProgramTypes() {
- return liveTypes.getItems();
- }
-
private EnqueuerUseRegistryFactory createUseRegistryFactory() {
if (mode.isFinalTreeShaking()) {
return appView.withGeneratedMessageLiteShrinker(
@@ -684,6 +679,17 @@
return definitionFor(type, context, this::recordNonProgramClass, this::reportMissingClass);
}
+ public DexLibraryClass definitionForLibraryClassOrIgnore(DexType type) {
+ assert type.isClassType();
+ ClassResolutionResult classResolutionResult =
+ appInfo().contextIndependentDefinitionForWithResolutionResult(type);
+ return classResolutionResult.hasClassResolutionResult()
+ && !classResolutionResult.isMultipleClassResolutionResult()
+ ? DexLibraryClass.asLibraryClassOrNull(
+ classResolutionResult.toSingleClassWithProgramOverLibrary())
+ : null;
+ }
+
public boolean hasAlternativeLibraryDefinition(DexProgramClass programClass) {
ClassResolutionResult classResolutionResult =
internalDefinitionFor(
@@ -2863,7 +2869,10 @@
} else {
markLibraryAndClasspathMethodOverridesAsLive(instantiation, clazz);
}
- clazz.forEachImmediateSupertype(worklist::addIfNotSeen);
+ if (clazz.superType != null) {
+ worklist.addIfNotSeen(clazz.superType);
+ }
+ worklist.addIfNotSeen(clazz.interfaces);
});
}
}
@@ -2960,7 +2969,7 @@
// class comment of DesugaredLibraryAPIConverter and vivifiedType logic.
// In the first enqueuer phase, the signature has not been desugared, so firstResolution
// maintains the library override. In the second enqueuer phase, the signature has been
- // desugared, and the second resolution maintains the library override.
+ // desugared, and the second resolution maintains the the library override.
if (instantiation.isClass()
&& appView.typeRewriter.hasRewrittenTypeInSignature(
method.getReference().proto, appView)) {
@@ -2992,6 +3001,11 @@
method ->
graphReporter.reportLibraryMethodAsLive(
instantiation, method, libraryOrClasspathClass));
+ if (instantiation.isClass()) {
+ // TODO(b/149976493): We need to mark these for lambdas too!
+ markOverridesAsLibraryMethodOverrides(
+ instantiation.asClass(), lookup.asMethodTarget().getDefinition().getReference());
+ }
}
private void markOverridesAsLibraryMethodOverrides(
@@ -3604,9 +3618,6 @@
if (options.apiModelingOptions().enableLibraryApiModeling) {
registerAnalysis(new ApiModelAnalysis(appView));
}
- if (!mode.isMainDexTracing()) {
- registerAnalysis(new EnqueuerLibraryOverrideAnalysis(appView));
- }
// Transfer the minimum keep info from the root set into the Enqueuer state.
includeMinimumKeepInfo(rootSet);
@@ -3629,8 +3640,8 @@
enqueueAllIfNotShrinking();
trace(executorService, timing);
options.reporter.failIfPendingErrors();
- analyses.forEach(analyses -> analyses.done(this));
finalizeLibraryMethodOverrideInformation();
+ analyses.forEach(analyses -> analyses.done(this));
assert verifyKeptGraph();
if (mode.isInitialTreeShaking() && forceProguardCompatibility) {
appView.setProguardCompatibilityActions(proguardCompatibilityActionsBuilder.build());
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 33d8f24..b479808 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -52,7 +52,6 @@
import com.android.tools.r8.graph.GraphLens.MethodLookupResult;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.LookupResult.LookupResultSuccess;
-import com.android.tools.r8.graph.MemberRebindingBridgeCode;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ObjectAllocationInfoCollection;
@@ -803,20 +802,6 @@
graphLens.getOriginalMethodSignature(implementationMethod);
assert originalMethod == originalImplementationMethod;
assert implementationMethod == renamedMethod;
- } else if (encodedMethod.hasCode()
- && encodedMethod.getCode().isMemberRebindingBridgeCode()
- && renamedMethod != originalMethod) {
- MemberRebindingBridgeCode memberRebindingBridgeCode =
- encodedMethod.getCode().asMemberRebindingBridgeCode();
- DexEncodedMethod resolvedMethod =
- appView
- .appInfo()
- .resolveMethodOn(
- originalMethod.getHolderType(),
- originalMethod,
- memberRebindingBridgeCode.getInterface())
- .getResolvedMethod();
- assert resolvedMethod.getReference() == memberRebindingBridgeCode.getTarget();
} else {
assert method == renamedMethod;
}
@@ -872,8 +857,8 @@
.resolveMethodOnInterfaceLegacy(method.getHolderType(), method.getReference())
.lookupVirtualDispatchTargets(target, appInfo)
.asLookupResultSuccess();
+ assert lookupResult != null;
if (lookupResult == null) {
- assert false;
return true;
}
if (lookupResult.contains(method)) {
@@ -1560,29 +1545,19 @@
assert invocationTarget.isStatic()
|| invocationTarget.isNonPrivateVirtualMethod()
|| invocationTarget.isNonStaticPrivateMethod();
+ SynthesizedBridgeCode code =
+ new SynthesizedBridgeCode(
+ newMethod,
+ appView.graphLens().getOriginalMethodSignature(method.getReference()),
+ invocationTarget.getReference(),
+ invocationTarget.isStatic()
+ ? STATIC
+ : (invocationTarget.isNonPrivateVirtualMethod() ? VIRTUAL : DIRECT),
+ target.isInterface());
- Code code;
- if (invocationTarget.getCode().isMemberRebindingBridgeCode()) {
- // Duplicate the code object, it should never be emitted anyway. The bridge is also
- // inserted for signatures defined in the library and these are not subject to be rewritten
- // after.
- code = invocationTarget.getCode();
- } else {
- SynthesizedBridgeCode bridgeCode =
- new SynthesizedBridgeCode(
- newMethod,
- appView.graphLens().getOriginalMethodSignature(method.getReference()),
- invocationTarget.getReference(),
- invocationTarget.isStatic()
- ? STATIC
- : (invocationTarget.isNonPrivateVirtualMethod() ? VIRTUAL : DIRECT),
- target.isInterface());
-
- // Add the bridge to the list of synthesized bridges such that the method signatures will
- // be updated by the end of vertical class merging.
- synthesizedBridges.add(bridgeCode);
- code = bridgeCode;
- }
+ // Add the bridge to the list of synthesized bridges such that the method signatures will
+ // be updated by the end of vertical class merging.
+ synthesizedBridges.add(code);
CfVersion classFileVersion =
method.hasClassFileVersion() ? method.getClassFileVersion() : null;
@@ -2023,10 +1998,6 @@
return AbortReason.UNSAFE_INLINING;
}
- public Collection<DexType> getRemovedClasses() {
- return Collections.unmodifiableCollection(mergedClasses.keySet());
- }
-
public class SingleTypeMapperGraphLens extends NonIdentityGraphLens {
private final DexType source;
@@ -2441,4 +2412,8 @@
};
}
}
+
+ public Collection<DexType> getRemovedClasses() {
+ return Collections.unmodifiableCollection(mergedClasses.keySet());
+ }
}
diff --git a/src/main/java/com/android/tools/r8/utils/ListUtils.java b/src/main/java/com/android/tools/r8/utils/ListUtils.java
index 33e4a3d..406d482 100644
--- a/src/main/java/com/android/tools/r8/utils/ListUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ListUtils.java
@@ -197,16 +197,6 @@
return list;
}
- public static <T> ArrayList<T> newArrayList(T element, List<T> otherOrNull) {
- int size = otherOrNull == null ? 1 : otherOrNull.size() + 1;
- ArrayList<T> list = new ArrayList<>(size);
- list.add(element);
- if (otherOrNull != null) {
- list.addAll(otherOrNull);
- }
- return list;
- }
-
public static <T> ArrayList<T> newArrayList(ForEachable<T> forEachable) {
ArrayList<T> list = new ArrayList<>();
forEachable.forEach(list::add);
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithDifferentApiLevelTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithDifferentApiLevelTest.java
index 179eab8..3c2923d 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithDifferentApiLevelTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithDifferentApiLevelTest.java
@@ -138,7 +138,14 @@
if (isGreaterOrEqualToClassMethodMockLevel()) {
runResult.assertSuccessWithOutputLines("LibraryClass::foo");
} else if (isGreaterOrEqualToIfaceMockLevel()) {
- runResult.assertFailureWithErrorThatThrows(AbstractMethodError.class);
+ if (isR8) {
+ runResult.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
+ } else {
+ runResult.assertFailureWithErrorThatThrows(AbstractMethodError.class);
+ }
+ } else if (isR8 && parameters.isCfRuntime()) {
+ // TODO(b/254510678): R8 should not rebind to the library method.
+ runResult.assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
} else {
runResult.assertSuccessWithOutputLines("Hello World");
}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithSameApiLevelTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithSameApiLevelTest.java
index 8f122d6..f6a0a49 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithSameApiLevelTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelIndirectTargetWithSameApiLevelTest.java
@@ -125,6 +125,9 @@
private void checkOutput(SingleTestRunResult<?> runResult, boolean isR8) {
if (isGreaterOrEqualToMockLevel()) {
runResult.assertSuccessWithOutputLines("LibraryClass::foo");
+ } else if (isR8 && parameters.isCfRuntime()) {
+ // TODO(b/254510678): R8 should not rebind to the library method.
+ runResult.assertFailureWithErrorThatThrows(NoClassDefFoundError.class);
} else {
runResult.assertSuccessWithOutputLines("Hello World");
}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelOutlineSubTypeStaticReferenceTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelOutlineSubTypeStaticReferenceTest.java
index 28a9abb..19971c3 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelOutlineSubTypeStaticReferenceTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelOutlineSubTypeStaticReferenceTest.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.testing.AndroidBuildVersion;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.lang.reflect.Method;
import java.util.Collections;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -126,11 +127,16 @@
}
private void inspect(CodeInspector inspector, boolean isR8) throws Exception {
+ Method otherMethod = Sub.class.getMethod("otherMethod");
+ Method libraryMethod = LibraryClass.class.getMethod("foo");
+ // TODO(b/254510678): R8 should not member-rebind to a potential non-existing method.
verifyThat(
inspector,
parameters,
- Reference.method(
- Reference.classFromClass(Sub.class), "foo", Collections.emptyList(), null))
+ isR8
+ ? Reference.methodFromMethod(libraryMethod)
+ : Reference.method(
+ Reference.classFromClass(Sub.class), "foo", Collections.emptyList(), null))
.isOutlinedFromUntil(Sub.class.getDeclaredMethod("otherMethod"), libraryApiLevel);
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
index 994d9cf..d6ede8b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaTimeTest.java
@@ -152,12 +152,10 @@
String holder =
libraryDesugaringSpecification.hasTimeDesugaring(parameters)
? "j$.time.temporal.TemporalAccessor"
- : "com.android.tools.r8.desugar.desugaredlibrary.JavaTimeTest$TemporalAccessorImpl";
- ClassSubject temporalAccessor = inspector.clazz(holder);
- assertThat(temporalAccessor, isPresent());
+ : "java.time.temporal.TemporalAccessor";
assertThat(
inspector.clazz(TemporalAccessorImplSub.class).uniqueMethodWithFinalName("query"),
- CodeMatchers.invokesMethod(null, temporalAccessor.getFinalName(), "query", null));
+ CodeMatchers.invokesMethod(null, holder, "query", null));
} else {
if (!parameters
.getApiLevel()
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingFrontierTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingFrontierTest.java
index 98bf6f6..2584946 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingFrontierTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingFrontierTest.java
@@ -4,9 +4,7 @@
package com.android.tools.r8.memberrebinding;
-import static com.android.tools.r8.utils.codeinspector.CodeMatchers.invokesMethodWithHolderAndName;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
-import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assume.assumeTrue;
@@ -16,6 +14,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeMatchers;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -44,7 +43,7 @@
.compile()
.apply(this::setupRunclasspath)
.run(parameters.getRuntime(), Main.class)
- .apply(this::checkOutput);
+ .apply(result -> checkOutput(result, false));
}
@Test
@@ -62,13 +61,15 @@
.apply(this::setupRunclasspath)
.inspect(
inspector -> {
+ // TODO(b/254510678): We should not rebind to I.foo
ClassSubject mainClass = inspector.clazz(Main.class);
assertThat(mainClass, isPresent());
MethodSubject foo = mainClass.mainMethod();
- assertThat(foo, not(invokesMethodWithHolderAndName(typeName(I.class), "foo")));
+ assertThat(
+ foo, CodeMatchers.invokesMethodWithHolderAndName(typeName(I.class), "foo"));
})
.run(parameters.getRuntime(), Main.class)
- .apply(this::checkOutput);
+ .apply(result -> checkOutput(result, true));
}
private byte[] removeFooMethod(Class<?> clazz) throws Exception {
@@ -91,12 +92,17 @@
.addRunClasspathClassFileData(removeFooMethod(I.class)));
}
- private void checkOutput(SingleTestRunResult<?> runResult) {
+ private void checkOutput(SingleTestRunResult<?> runResult, boolean r8) {
if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
runResult.assertSuccessWithOutputLines("I::foo");
return;
}
- runResult.assertSuccessWithOutputLines("Base::foo");
+ // TODO(b/254510678): We should not rebind to I.foo
+ if (r8) {
+ runResult.assertFailureWithErrorThatThrows(NoSuchMethodError.class);
+ } else {
+ runResult.assertSuccessWithOutputLines("Base::foo");
+ }
}
private interface I {
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
index eb9a8dc..605ddf7 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/MemberRebindingTest.java
@@ -165,13 +165,10 @@
assertTrue(iterator.next().holder().is("java.util.AbstractList"));
assertTrue(iterator.next().holder().is("memberrebinding.subpackage.PublicClassInTheMiddle"));
assertTrue(iterator.next().holder().is("memberrebinding.subpackage.PublicClassInTheMiddle"));
- // For the next three - test that we do not rebind but keep the static holder.
- assertTrue(
- iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
- assertTrue(
- iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
- assertTrue(
- iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
+ // For the next three - test that we re-bind to the lowest library class.
+ assertTrue(iterator.next().holder().is("memberrebindinglib.SubClass"));
+ assertTrue(iterator.next().holder().is("memberrebindinglib.SubClass"));
+ assertTrue(iterator.next().holder().is("memberrebindinglib.SubClass"));
// The next one is already precise.
assertTrue(
iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
@@ -180,10 +177,8 @@
assertTrue(iterator.next().holder().is("memberrebindinglib.AnIndependentInterface"));
// Some dispatches on classes.
assertTrue(iterator.next().holder().is("java.lang.System"));
- assertTrue(
- iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
- assertTrue(
- iterator.next().holder().is("memberrebinding.SuperClassOfClassExtendsOtherLibraryClass"));
+ assertTrue(iterator.next().holder().is("memberrebindinglib.SubClass"));
+ assertTrue(iterator.next().holder().is("memberrebindinglib.ImplementedInProgramClass"));
assertFalse(iterator.hasNext());
}
diff --git a/src/test/java/com/android/tools/r8/regress/b149890887/MissingLibraryTargetTest.java b/src/test/java/com/android/tools/r8/regress/b149890887/MissingLibraryTargetTest.java
index 8c4d936..d01d917 100644
--- a/src/test/java/com/android/tools/r8/regress/b149890887/MissingLibraryTargetTest.java
+++ b/src/test/java/com/android/tools/r8/regress/b149890887/MissingLibraryTargetTest.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
@@ -61,7 +62,7 @@
.addKeepMainRule(MAIN)
.addClasspathClasses(LIBRARY)
.setMinApi(parameters.getApiLevel())
- .addDontWarn(MissingLibraryClass.class)
+ .addKeepRules("-dontwarn")
.compile()
.addRunClasspathFiles(runtimeClasspath())
.run(parameters.getRuntime(), MAIN)
diff --git a/src/test/java/com/android/tools/r8/resolution/duplicatedefinitions/MaximallySpecificMultipleOnCompleteTest.java b/src/test/java/com/android/tools/r8/resolution/duplicatedefinitions/MaximallySpecificMultipleOnCompleteTest.java
index f452c4b..e220b6e 100644
--- a/src/test/java/com/android/tools/r8/resolution/duplicatedefinitions/MaximallySpecificMultipleOnCompleteTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/duplicatedefinitions/MaximallySpecificMultipleOnCompleteTest.java
@@ -139,6 +139,7 @@
@Override
default void foo() {
System.out.println("J_Program::foo");
+ ;
}
}
@@ -146,6 +147,7 @@
@Override
default void foo() {
System.out.println("J_Library::foo");
+ ;
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInInterfaceMarkingTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInInterfaceMarkingTest.java
index ac11d72..42268b2 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInInterfaceMarkingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInInterfaceMarkingTest.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.shaking;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestBase;
@@ -14,7 +14,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.utils.OptionalBool;
import java.util.AbstractList;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -50,17 +49,17 @@
private void verifyLibraryOverrideInformation(AppInfoWithLiveness appInfo, Enqueuer.Mode mode) {
DexItemFactory dexItemFactory = appInfo.dexItemFactory();
verifyIsEmptyMarkedAsOverridingLibraryMethod(
- appInfo, dexItemFactory.createType(descriptor(A.class)), OptionalBool.TRUE);
+ appInfo, dexItemFactory.createType(descriptor(A.class)));
verifyIsEmptyMarkedAsOverridingLibraryMethod(
- appInfo, dexItemFactory.createType(descriptor(I.class)), OptionalBool.FALSE);
+ appInfo, dexItemFactory.createType(descriptor(I.class)));
}
private void verifyIsEmptyMarkedAsOverridingLibraryMethod(
- AppInfoWithLiveness appInfo, DexType type, OptionalBool expected) {
+ AppInfoWithLiveness appInfo, DexType type) {
DexProgramClass clazz = appInfo.definitionFor(type).asProgramClass();
DexEncodedMethod method =
clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("isEmpty"));
- assertEquals(expected, method.isLibraryMethodOverride());
+ assertTrue(method.isLibraryMethodOverride().isTrue());
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
index 928a2fc..563a312 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideInLambdaMarkingTest.java
@@ -4,8 +4,7 @@
package com.android.tools.r8.shaking;
-import static com.android.tools.r8.CollectorsUtils.toSingle;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestBase;
@@ -16,7 +15,6 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.Enqueuer.Mode;
-import com.android.tools.r8.utils.OptionalBool;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;
@@ -54,29 +52,21 @@
private void verifyLibraryOverrideInformation(AppInfoWithLiveness appInfo, Mode mode) {
DexItemFactory dexItemFactory = appInfo.dexItemFactory();
verifyIteratorMethodMarkedAsOverridingLibraryMethod(
- appInfo, dexItemFactory.createType(descriptor(I.class)), OptionalBool.FALSE);
+ appInfo, dexItemFactory.createType(descriptor(I.class)));
verifyIteratorMethodMarkedAsOverridingLibraryMethod(
- appInfo, dexItemFactory.createType(descriptor(J.class)), OptionalBool.FALSE);
- if (parameters.isDexRuntime()) {
- DexProgramClass lambda =
- appInfo.classes().stream()
- .filter(x -> x.toSourceString().contains("$InternalSyntheticLambda"))
- .collect(toSingle());
- verifyIteratorMethodMarkedAsOverridingLibraryMethod(
- appInfo, lambda.getType(), OptionalBool.TRUE);
- }
+ appInfo, dexItemFactory.createType(descriptor(J.class)));
}
private void verifyIteratorMethodMarkedAsOverridingLibraryMethod(
- AppInfoWithLiveness appInfo, DexType type, OptionalBool expected) {
+ AppInfoWithLiveness appInfo, DexType type) {
DexProgramClass clazz = appInfo.definitionFor(type).asProgramClass();
DexEncodedMethod method =
clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("iterator"));
// TODO(b/149976493): Mark library overrides from lambda instances.
if (parameters.isCfRuntime()) {
- assertEquals(OptionalBool.FALSE, method.isLibraryMethodOverride());
+ assertTrue(method.isLibraryMethodOverride().isFalse());
} else {
- assertEquals(expected, method.isLibraryMethodOverride());
+ assertTrue(method.isLibraryMethodOverride().isTrue());
}
}
diff --git a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideMarkingTest.java b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideMarkingTest.java
index 188d4aa..a7908c2 100644
--- a/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideMarkingTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/LibraryMethodOverrideMarkingTest.java
@@ -6,6 +6,7 @@
import static com.google.common.base.Predicates.alwaysTrue;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestBase;
@@ -15,7 +16,6 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.utils.OptionalBool;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -49,17 +49,17 @@
private void verifyLibraryOverrideInformation(AppInfoWithLiveness appInfo, Enqueuer.Mode mode) {
DexItemFactory dexItemFactory = appInfo.dexItemFactory();
verifySingleVirtualMethodMarkedAsOverridingLibraryMethod(
- appInfo, dexItemFactory.createType(descriptor(A.class)), OptionalBool.FALSE);
+ appInfo, dexItemFactory.createType(descriptor(A.class)));
verifySingleVirtualMethodMarkedAsOverridingLibraryMethod(
- appInfo, dexItemFactory.createType(descriptor(B.class)), OptionalBool.TRUE);
+ appInfo, dexItemFactory.createType(descriptor(B.class)));
}
private void verifySingleVirtualMethodMarkedAsOverridingLibraryMethod(
- AppInfoWithLiveness appInfo, DexType type, OptionalBool expected) {
+ AppInfoWithLiveness appInfo, DexType type) {
DexProgramClass clazz = appInfo.definitionFor(type).asProgramClass();
assertEquals(1, clazz.getMethodCollection().numberOfVirtualMethods());
DexEncodedMethod method = clazz.lookupVirtualMethod(alwaysTrue());
- assertEquals(expected, method.isLibraryMethodOverride());
+ assertTrue(method.isLibraryMethodOverride().isTrue());
}
static class TestClass {
diff --git a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideAbstractTest.java b/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideAbstractTest.java
deleted file mode 100644
index c7f3e23..0000000
--- a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideAbstractTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (c) 2022, 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.shaking.librarymethodoverride;
-
-import static org.junit.Assert.assertTrue;
-
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.Enqueuer;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class LibraryMethodOverrideAbstractTest extends TestBase {
-
- @Parameter() public TestParameters parameters;
-
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimesAndApiLevels().build();
- }
-
- @Test
- public void testRuntime() throws Exception {
- testForRuntime(parameters)
- .addProgramClasses(SubProgramClass.class, Main.class)
- .addProgramClassFileData(
- transformer(ProgramClass.class).removeMethodsWithName("foo").transform())
- .addLibraryClasses(LibraryClass.class)
- .addRunClasspathFiles(buildOnDexRuntime(parameters, LibraryClass.class))
- .run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrows(AbstractMethodError.class);
- }
-
- @Test
- public void testR8() throws Exception {
- testForR8(parameters.getBackend())
- .addProgramClasses(SubProgramClass.class, Main.class)
- .addProgramClassFileData(
- transformer(ProgramClass.class).removeMethodsWithName("foo").transform())
- .addDefaultRuntimeLibrary(parameters)
- .addLibraryClasses(LibraryClass.class)
- .addOptionsModification(
- options -> options.testing.enqueuerInspector = this::verifyLibraryOverrideInformation)
- .setMinApi(parameters.getApiLevel())
- .addKeepMainRule(Main.class)
- .compile()
- .addBootClasspathClasses(LibraryClass.class)
- .run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrows(AbstractMethodError.class);
- }
-
- private void verifyLibraryOverrideInformation(AppInfoWithLiveness appInfo, Enqueuer.Mode mode) {
- if (mode.isInitialTreeShaking()) {
- DexItemFactory dexItemFactory = appInfo.dexItemFactory();
- DexProgramClass clazz =
- appInfo
- .definitionFor(dexItemFactory.createType(descriptor(SubProgramClass.class)))
- .asProgramClass();
- DexEncodedMethod method =
- clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("foo"));
- assertTrue(method.isLibraryMethodOverride().isTrue());
- }
- }
-
- public abstract static class LibraryClass {
-
- abstract void foo();
-
- public static void callFoo(LibraryClass libraryClass) {
- libraryClass.foo();
- }
- }
-
- public abstract static class SubProgramClass extends LibraryClass {
-
- @Override
- abstract void foo();
- }
-
- public static class ProgramClass extends SubProgramClass {
-
- @Override
- void foo() {
- throw new RuntimeException("Should have been removed.");
- }
- }
-
- public static class Main {
-
- public static void main(String[] args) {
- LibraryClass.callFoo(new ProgramClass());
- }
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideDefaultMethodICCETest.java b/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideDefaultMethodICCETest.java
deleted file mode 100644
index aa8ca52..0000000
--- a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideDefaultMethodICCETest.java
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2022, 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.shaking.librarymethodoverride;
-
-import static org.junit.Assert.assertTrue;
-
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.Enqueuer;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class LibraryMethodOverrideDefaultMethodICCETest extends TestBase {
-
- @Parameter() public TestParameters parameters;
-
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimesAndApiLevels().build();
- }
-
- @Test
- public void testRuntime() throws Exception {
- testForRuntime(parameters)
- .addProgramClasses(Main.class, ProgramI.class, ProgramJ.class)
- .addProgramClassFileData(
- transformer(ProgramClass.class)
- .setImplements(LibraryInterface.class, ProgramI.class, ProgramJ.class)
- .transform())
- .addLibraryClasses(LibraryInterface.class, LibraryCaller.class)
- .addRunClasspathFiles(
- buildOnDexRuntime(parameters, LibraryInterface.class, LibraryCaller.class))
- .run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrowsIf(
- parameters.isCfRuntime() && parameters.getRuntime().asCf().isOlderThan(CfVm.JDK11),
- IncompatibleClassChangeError.class)
- .assertFailureWithErrorThatThrowsIf(
- parameters.isCfRuntime()
- && parameters.getRuntime().asCf().isNewerThanOrEqual(CfVm.JDK11),
- AbstractMethodError.class)
- .assertFailureWithErrorThatThrowsIf(
- parameters.isDexRuntime(), IncompatibleClassChangeError.class);
- }
-
- @Test
- public void testR8() throws Exception {
- testForR8(parameters.getBackend())
- .addProgramClasses(Main.class, ProgramI.class, ProgramJ.class)
- .addProgramClassFileData(
- transformer(ProgramClass.class)
- .setImplements(LibraryInterface.class, ProgramI.class, ProgramJ.class)
- .transform())
- .addDefaultRuntimeLibrary(parameters)
- .addLibraryClasses(LibraryInterface.class, LibraryCaller.class)
- .addOptionsModification(
- options -> options.testing.enqueuerInspector = this::verifyLibraryOverrideInformation)
- .setMinApi(parameters.getApiLevel())
- .addKeepMainRule(Main.class)
- .addDontObfuscate()
- .compile()
- .addBootClasspathClasses(LibraryInterface.class, LibraryCaller.class)
- .run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrowsIf(
- parameters.canUseDefaultAndStaticInterfaceMethods(), AbstractMethodError.class)
- .assertFailureWithErrorThatThrowsIf(
- !parameters.canUseDefaultAndStaticInterfaceMethods(),
- IncompatibleClassChangeError.class);
- }
-
- private void verifyLibraryOverrideInformation(AppInfoWithLiveness appInfo, Enqueuer.Mode mode) {
- if (mode.isInitialTreeShaking()) {
- if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
- verifyMethodFooOnHolderIsSetAsLibraryOverride(appInfo, ProgramI.class);
- verifyMethodFooOnHolderIsSetAsLibraryOverride(appInfo, ProgramJ.class);
- } else {
- verifyMethodFooOnHolderIsSetAsLibraryOverride(appInfo, ProgramClass.class);
- }
- }
- }
-
- private void verifyMethodFooOnHolderIsSetAsLibraryOverride(
- AppInfoWithLiveness appInfo, Class<?> programClass) {
- DexItemFactory dexItemFactory = appInfo.dexItemFactory();
- DexProgramClass clazz =
- appInfo.definitionFor(dexItemFactory.createType(descriptor(programClass))).asProgramClass();
- DexEncodedMethod method =
- clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("foo"));
- assertTrue(method.isLibraryMethodOverride().isTrue());
- }
-
- public interface LibraryInterface {
-
- void foo();
- }
-
- public static class LibraryCaller {
-
- public static void callFoo(LibraryInterface iface) {
- iface.foo();
- }
- }
-
- public interface ProgramI extends LibraryInterface {
-
- @Override
- default void foo() {
- System.out.println("ProgramI::foo");
- }
- }
-
- public interface ProgramJ extends LibraryInterface {
-
- @Override
- default void foo() {
- System.out.println("ProgramJ::foo");
- }
- }
-
- public static class ProgramClass implements LibraryInterface, ProgramI /* ,ProgramJ */ {}
-
- public static class Main {
-
- public static void main(String[] args) {
- LibraryCaller.callFoo(new ProgramClass());
- }
- }
-}
diff --git a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideDefaultMethodTest.java b/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideDefaultMethodTest.java
index 046c2e5..939b14a 100644
--- a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideDefaultMethodTest.java
@@ -4,8 +4,6 @@
package com.android.tools.r8.shaking.librarymethodoverride;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestBase;
@@ -60,26 +58,13 @@
private void verifyLibraryOverrideInformation(AppInfoWithLiveness appInfo, Enqueuer.Mode mode) {
DexItemFactory dexItemFactory = appInfo.dexItemFactory();
- DexProgramClass programI =
+ DexProgramClass clazz =
appInfo
.definitionFor(dexItemFactory.createType(descriptor(ProgramI.class)))
.asProgramClass();
- DexEncodedMethod programIFoo =
- programI.lookupVirtualMethod(m -> m.getReference().name.toString().equals("foo"));
- assertEquals(
- parameters.canUseDefaultAndStaticInterfaceMethods(),
- programIFoo.isLibraryMethodOverride().isTrue());
- DexProgramClass programClass =
- appInfo
- .definitionFor(dexItemFactory.createType(descriptor(ProgramClass.class)))
- .asProgramClass();
- DexEncodedMethod programClassFoo =
- programClass.lookupVirtualMethod(m -> m.getReference().name.toString().equals("foo"));
- if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
- assertNull(programClassFoo);
- } else {
- assertTrue(programClassFoo.isLibraryMethodOverride().isTrue());
- }
+ DexEncodedMethod method =
+ clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("foo"));
+ assertTrue(method.isLibraryMethodOverride().isTrue());
}
public interface LibraryI {
diff --git a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideOfClassMethodWithInterfaceTest.java b/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideOfClassMethodWithInterfaceTest.java
index 4524dd7..247b780 100644
--- a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideOfClassMethodWithInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideOfClassMethodWithInterfaceTest.java
@@ -66,7 +66,8 @@
.asProgramClass();
DexEncodedMethod method =
clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("foo"));
- assertTrue(method.isLibraryMethodOverride().isFalse());
+ // TODO(b/259531498): We should not mark the interface method as overriding.
+ assertTrue(method.isLibraryMethodOverride().isTrue());
}
public abstract static class LibraryClass {
diff --git a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideOfSuperClassNotInHierarchyTest.java b/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideOfSuperClassNotInHierarchyTest.java
deleted file mode 100644
index c9c8bf8..0000000
--- a/src/test/java/com/android/tools/r8/shaking/librarymethodoverride/LibraryMethodOverrideOfSuperClassNotInHierarchyTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2022, 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.shaking.librarymethodoverride;
-
-import static org.junit.Assert.assertEquals;
-
-import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.shaking.Enqueuer;
-import com.android.tools.r8.utils.OptionalBool;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class LibraryMethodOverrideOfSuperClassNotInHierarchyTest extends TestBase {
-
- private final String[] EXPECTED = new String[] {"SecondProgramClass::foo"};
-
- @Parameter() public TestParameters parameters;
-
- @Parameters(name = "{0}")
- public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimesAndApiLevels().build();
- }
-
- @Test
- public void testRuntime() throws Exception {
- testForRuntime(parameters)
- .addProgramClasses(
- FirstProgramClass.class, SecondProgramClass.class, ThirdProgramClass.class, Main.class)
- .addLibraryClasses(LibraryClass.class, LibraryInterface.class)
- .addRunClasspathFiles(
- buildOnDexRuntime(parameters, LibraryClass.class, LibraryInterface.class))
- .run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutputLines(EXPECTED);
- }
-
- @Test
- public void testR8() throws Exception {
- testForR8(parameters.getBackend())
- .addProgramClasses(
- FirstProgramClass.class, SecondProgramClass.class, ThirdProgramClass.class, Main.class)
- .addDefaultRuntimeLibrary(parameters)
- .addLibraryClasses(LibraryClass.class, LibraryInterface.class)
- .addOptionsModification(
- options -> options.testing.enqueuerInspector = this::verifyLibraryOverrideInformation)
- .setMinApi(parameters.getApiLevel())
- .addKeepMainRule(Main.class)
- .compile()
- .addBootClasspathClasses(LibraryClass.class, LibraryInterface.class)
- .run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutputLines(EXPECTED);
- }
-
- private void verifyLibraryOverrideInformation(AppInfoWithLiveness appInfo, Enqueuer.Mode mode) {
- if (!mode.isInitialTreeShaking()) {
- return;
- }
- DexItemFactory dexItemFactory = appInfo.dexItemFactory();
- DexProgramClass clazz =
- appInfo
- .definitionFor(dexItemFactory.createType(descriptor(FirstProgramClass.class)))
- .asProgramClass();
- DexEncodedMethod method =
- clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("foo"));
- assertEquals(OptionalBool.FALSE, method.isLibraryMethodOverride());
- clazz =
- appInfo
- .definitionFor(dexItemFactory.createType(descriptor(SecondProgramClass.class)))
- .asProgramClass();
- method = clazz.lookupVirtualMethod(m -> m.getReference().name.toString().equals("foo"));
- assertEquals(OptionalBool.TRUE, method.isLibraryMethodOverride());
- }
-
- public interface LibraryInterface {
-
- void foo();
- }
-
- public static class LibraryClass {
-
- public static void callFoo(LibraryInterface i) {
- i.foo();
- }
- }
-
- public static class FirstProgramClass {
-
- public void foo() {
- System.out.println("FirstProgramClass::foo");
- }
- }
-
- public static class SecondProgramClass extends FirstProgramClass {
-
- @Override
- public void foo() {
- System.out.println("SecondProgramClass::foo");
- }
- }
-
- public static class ThirdProgramClass extends SecondProgramClass implements LibraryInterface {}
-
- public static class Main {
-
- public static void main(String[] args) {
- LibraryClass.callFoo(new ThirdProgramClass());
- }
- }
-}
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index b72d822..8108730 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -1139,25 +1139,6 @@
});
}
- public ClassFileTransformer removeCode(MethodPredicate predicate) {
- return addMethodTransformer(
- new MethodTransformer() {
- @Override
- public void visitCode() {
- if (!MethodPredicate.testContext(predicate, getContext())) {
- super.visitCode();
- }
- }
-
- @Override
- public void visitInsn(int opcode) {
- if (!MethodPredicate.testContext(predicate, getContext())) {
- super.visitInsn(opcode);
- }
- }
- });
- }
-
public ClassFileTransformer transformInvokeDynamicInsnInMethod(
String methodName, InvokeDynamicInsnTransform transform) {
return addMethodTransformer(