Revert "L8 Cf to Cf"
This reverts commit 49dbca6424489d4320727bbd731175a310d7aa35.
Reason for revert: potential NPE in LambdaClass$Target.holderIsInterface, resulting in total failures in bots and AOSP build
Change-Id: Ifa34a817c549afa2cff7d50f9ace6d83b14cc111
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 23e4e09..1088e60 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -153,7 +153,7 @@
final CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
IRConverter converter = new IRConverter(appInfo, options, timing, printer);
- app = converter.convert(app, executor);
+ app = converter.convertToDex(app, executor);
if (options.printCfg) {
if (options.printCfgFile == null || options.printCfgFile.isEmpty()) {
@@ -225,7 +225,7 @@
final CfgPrinter printer = options.printCfg ? new CfgPrinter() : null;
IRConverter converter = new IRConverter(appInfo, options, timing, printer);
- application = converter.convert(application, executor);
+ application = converter.convertToDex(application, executor);
if (options.printCfg) {
if (options.printCfgFile == null || options.printCfgFile.isEmpty()) {
diff --git a/src/main/java/com/android/tools/r8/L8.java b/src/main/java/com/android/tools/r8/L8.java
index 2ea9573..4bf785c 100644
--- a/src/main/java/com/android/tools/r8/L8.java
+++ b/src/main/java/com/android/tools/r8/L8.java
@@ -6,19 +6,20 @@
import static com.android.tools.r8.utils.ExceptionUtils.unwrapExecutionException;
import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.dex.ApplicationWriter;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.ir.conversion.IRConverter;
-import com.android.tools.r8.jar.CfApplicationWriter;
import com.android.tools.r8.naming.PrefixRewritingNamingLens;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
+import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -59,24 +60,24 @@
AppView<?> appView = AppView.createForL8(appInfo, options);
IRConverter converter = new IRConverter(appView, timing);
-
- app = converter.convert(app, executor);
+ app = converter.convertToDex(app, executor);
assert appView.appInfo() == appInfo;
// Close any internal archive providers now the application is fully processed.
inputApp.closeInternalArchiveProviders();
- new CfApplicationWriter(
+ new ApplicationWriter(
app,
- appView,
+ null,
options,
- options.getMarker(Tool.L8),
+ ImmutableList.of(options.getMarker(Tool.L8)),
+ null,
null,
GraphLense.getIdentityLense(),
PrefixRewritingNamingLens.createPrefixRewritingNamingLens(
options, converter.getAdditionalRewritePrefix()),
null)
- .write(options.getClassFileConsumer(), executor);
+ .write(executor);
options.printWarnings();
} catch (ExecutionException e) {
throw unwrapExecutionException(e);
diff --git a/src/main/java/com/android/tools/r8/L8Command.java b/src/main/java/com/android/tools/r8/L8Command.java
index 944c2bd..3b23ef5 100644
--- a/src/main/java/com/android/tools/r8/L8Command.java
+++ b/src/main/java/com/android/tools/r8/L8Command.java
@@ -72,8 +72,8 @@
} else if (!getSpecialLibraryConfiguration().equals("default")) {
reporter.error("L8 currently requires the special library configuration to be \"default\"");
}
- if (getProgramConsumer() instanceof DexIndexedConsumer) {
- reporter.error("L8 does not support compiling to dex");
+ if (getProgramConsumer() instanceof ClassFileConsumer) {
+ reporter.error("L8 does not support compiling to Java class files");
}
if (getProgramConsumer() instanceof DexFilePerClassFileConsumer) {
reporter.error("L8 does not support compiling to dex per class");
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 4b3ace9..5912651 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -40,7 +40,6 @@
public class CfCode extends Code implements CfOrJarCode {
public static class LocalVariableInfo {
-
private final int index;
private final DebugLocalInfo local;
private final CfLabel start;
@@ -208,7 +207,8 @@
for (CfInstruction instruction : instructions) {
if (instruction instanceof CfFrame
&& (classFileVersion <= 49
- || (classFileVersion == 50 && !options.shouldKeepStackMapTable()))) {
+ || (classFileVersion == 50
+ && !options.getProguardConfiguration().getKeepAttributes().stackMapTable))) {
continue;
}
instruction.write(visitor, namingLens);
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index fc5874f..90c15c6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -78,7 +78,6 @@
import org.objectweb.asm.Opcodes;
public class DexEncodedMethod extends KeyedDexItem<DexMethod> implements ResolutionResult {
-
public static final String CONFIGURATION_DEBUGGING_PREFIX = "Shaking error: Missing method in ";
/**
@@ -680,18 +679,6 @@
}
}
- public static void setDebugInfoWithFakeThisParameter(Code code, int arity, AppView<?> appView) {
- if (code.isDexCode()) {
- DexCode dexCode = code.asDexCode();
- dexCode.setDebugInfo(dexCode.debugInfoWithFakeThisParameter(appView.dexItemFactory()));
- assert (dexCode.getDebugInfo() == null)
- || (arity == dexCode.getDebugInfo().parameters.length);
- } else {
- // TODO(b/134732760): Patch Cf debug info.
- assert appView.options().coreLibraryCompilation;
- }
- }
-
private DexEncodedMethod toMethodThatLogsErrorDexCode(DexItemFactory itemFactory) {
checkIfObsolete();
Signature signature = MethodSignature.fromDexMethod(method);
@@ -1079,7 +1066,6 @@
}
public static class ClassInlinerEligibility {
-
public final boolean returnsReceiver;
public ClassInlinerEligibility(boolean returnsReceiver) {
@@ -1088,14 +1074,12 @@
}
public static class TrivialInitializer {
-
private TrivialInitializer() {
}
// Defines instance trivial initialized, see details in comments
// to CodeRewriter::computeInstanceInitializerInfo(...)
public static final class TrivialInstanceInitializer extends TrivialInitializer {
-
public static final TrivialInstanceInitializer INSTANCE =
new TrivialInstanceInitializer();
}
@@ -1103,7 +1087,6 @@
// Defines class trivial initialized, see details in comments
// to CodeRewriter::computeClassInitializerInfo(...)
public static final class TrivialClassInitializer extends TrivialInitializer {
-
public final DexField field;
public TrivialClassInitializer(DexField field) {
@@ -1113,7 +1096,6 @@
}
public static class DefaultMethodOptimizationInfoImpl implements MethodOptimizationInfo {
-
public static final MethodOptimizationInfo DEFAULT_INSTANCE =
new DefaultMethodOptimizationInfoImpl();
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 87c976d..484a529 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
@@ -132,10 +132,6 @@
private final GeneratedMessageLiteShrinker generatedMessageLiteShrinker;
private final LibraryMethodOverrideAnalysis libraryMethodOverrideAnalysis;
private final StringConcatRewriter stringConcatRewriter;
- private final StringOptimizer stringOptimizer;
- private final StringBuilderOptimizer stringBuilderOptimizer;
- private final IdempotentFunctionCallCanonicalizer idempotentFunctionCallCanonicalizer;
- private final List<DexString> neverMergePrefixes;
private final LambdaRewriter lambdaRewriter;
private final D8NestBasedAccessDesugaring d8NestBasedAccessDesugaring;
private final InterfaceMethodRewriter interfaceMethodRewriter;
@@ -155,9 +151,13 @@
private final IdentifierNameStringMarker identifierNameStringMarker;
private final Devirtualizer devirtualizer;
private final CovariantReturnTypeAnnotationTransformer covariantReturnTypeAnnotationTransformer;
+ private final StringOptimizer stringOptimizer;
+ private final StringBuilderOptimizer stringBuilderOptimizer;
private final StringSwitchRemover stringSwitchRemover;
private final UninstantiatedTypeOptimization uninstantiatedTypeOptimization;
private final TypeChecker typeChecker;
+ private final IdempotentFunctionCallCanonicalizer idempotentFunctionCallCanonicalizer;
+ private final List<DexString> neverMergePrefixes;
final DeadCodeRemover deadCodeRemover;
@@ -187,46 +187,6 @@
this.classInitializerDefaultsOptimization =
options.debug ? null : new ClassInitializerDefaultsOptimization(appView, this);
this.stringConcatRewriter = new StringConcatRewriter(appView);
- this.stringOptimizer = new StringOptimizer(appView);
- this.stringBuilderOptimizer = new StringBuilderOptimizer(appView);
- this.deadCodeRemover = new DeadCodeRemover(appView, codeRewriter);
- this.idempotentFunctionCallCanonicalizer = new IdempotentFunctionCallCanonicalizer(appView);
- this.neverMergePrefixes =
- options.neverMergePrefixes.stream()
- .map(prefix -> "L" + DescriptorUtils.getPackageBinaryNameFromJavaType(prefix))
- .map(options.itemFactory::createString)
- .collect(Collectors.toList());
- if (options.coreLibraryCompilation) {
- // Specific L8 Settings.
- // BackportedMethodRewriter is needed for retarget core library members and backports.
- // InterfaceMethodRewriter is needed for emulated interfaces.
- // LambdaRewriter is needed because if it is missing there are invoke custom on
- // default/static interface methods, and this is not supported by the compiler.
- // The rest is nulled out.
- this.backportedMethodRewriter = new BackportedMethodRewriter(appView, this);
- this.interfaceMethodRewriter = new InterfaceMethodRewriter(appView, this);
- this.lambdaRewriter = new LambdaRewriter(appView, this);
- this.twrCloseResourceRewriter = null;
- this.lambdaMerger = null;
- this.covariantReturnTypeAnnotationTransformer = null;
- this.nonNullTracker = null;
- this.classInliner = null;
- this.classStaticizer = null;
- this.dynamicTypeOptimization = null;
- this.generatedMessageLiteShrinker = null;
- this.libraryMethodOverrideAnalysis = null;
- this.inliner = null;
- this.outliner = null;
- this.memberValuePropagation = null;
- this.lensCodeRewriter = null;
- this.identifierNameStringMarker = null;
- this.devirtualizer = null;
- this.uninstantiatedTypeOptimization = null;
- this.typeChecker = null;
- this.d8NestBasedAccessDesugaring = null;
- this.stringSwitchRemover = null;
- return;
- }
this.lambdaRewriter = options.enableDesugaring ? new LambdaRewriter(appView, this) : null;
this.interfaceMethodRewriter =
options.isInterfaceMethodDesugaringEnabled()
@@ -245,6 +205,8 @@
options.processCovariantReturnTypeAnnotations
? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
: null;
+ this.stringOptimizer = new StringOptimizer(appView);
+ this.stringBuilderOptimizer = new StringBuilderOptimizer(appView);
this.nonNullTracker = options.enableNonNullTracking ? new NonNullTracker(appView) : null;
if (appView.enableWholeProgramOptimizations()) {
assert appView.appInfo().hasLiveness();
@@ -303,10 +265,17 @@
this.d8NestBasedAccessDesugaring =
options.shouldDesugarNests() ? new D8NestBasedAccessDesugaring(appView) : null;
}
+ this.deadCodeRemover = new DeadCodeRemover(appView, codeRewriter);
+ this.idempotentFunctionCallCanonicalizer = new IdempotentFunctionCallCanonicalizer(appView);
this.stringSwitchRemover =
options.isStringSwitchConversionEnabled()
? new StringSwitchRemover(appView, identifierNameStringMarker)
: null;
+ this.neverMergePrefixes =
+ options.neverMergePrefixes.stream()
+ .map(prefix -> "L" + DescriptorUtils.getPackageBinaryNameFromJavaType(prefix))
+ .map(options.itemFactory::createString)
+ .collect(Collectors.toList());
}
public Set<DexCallSite> getDesugaredCallSites() {
@@ -421,12 +390,12 @@
}
}
- public DexApplication convert(DexApplication application, ExecutorService executor)
+ public DexApplication convertToDex(DexApplication application, ExecutorService executor)
throws ExecutionException {
removeLambdaDeserializationMethods();
timing.begin("IR conversion");
- convertClasses(application.classes(), executor);
+ convertClassesToDex(application.classes(), executor);
// Build a new application with jumbo string info,
Builder<?> builder = application.builder();
@@ -513,22 +482,22 @@
}
}
- private void convertClasses(Iterable<DexProgramClass> classes, ExecutorService executor)
- throws ExecutionException {
+ private void convertClassesToDex(Iterable<DexProgramClass> classes,
+ ExecutorService executor) throws ExecutionException {
List<Future<?>> futures = new ArrayList<>();
for (DexProgramClass clazz : classes) {
- futures.add(executor.submit(() -> convertMethods(clazz)));
+ futures.add(executor.submit(() -> convertMethodsToDex(clazz)));
}
ThreadUtils.awaitFutures(futures);
}
- private void convertMethods(DexProgramClass clazz) {
+ private void convertMethodsToDex(DexProgramClass clazz) {
boolean isReachabilitySensitive = clazz.hasReachabilitySensitiveAnnotation(options.itemFactory);
// When converting all methods on a class always convert <clinit> first.
for (DexEncodedMethod method : clazz.directMethods()) {
if (method.isClassInitializer()) {
method.getMutableOptimizationInfo().setReachabilitySensitive(isReachabilitySensitive);
- convertMethod(method);
+ convertMethodToDex(method);
break;
}
}
@@ -536,17 +505,17 @@
method -> {
if (!method.isClassInitializer()) {
method.getMutableOptimizationInfo().setReachabilitySensitive(isReachabilitySensitive);
- convertMethod(method);
+ convertMethodToDex(method);
}
});
}
- private void convertMethod(DexEncodedMethod method) {
+ private void convertMethodToDex(DexEncodedMethod method) {
+ assert options.isGeneratingDex();
if (method.getCode() != null) {
boolean matchesMethodFilter = options.methodMatchesFilter(method);
if (matchesMethodFilter) {
- if (options.isGeneratingClassFiles()
- || !(options.passthroughDexCode && method.getCode().isDexCode())) {
+ if (!(options.passthroughDexCode && method.getCode().isDexCode())) {
// We do not process in call graph order, so anything could be a leaf.
rewriteCode(method, simpleOptimizationFeedback, x -> true, CallSiteInformation.empty(),
Outliner::noProcessing);
@@ -561,9 +530,7 @@
}
}
}
- if (!options.isGeneratingClassFiles()) {
- updateHighestSortingStrings(method);
- }
+ updateHighestSortingStrings(method);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index ff771b7..d534cf6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -239,7 +239,8 @@
initializeJava9MethodProviders(factory);
initializeJava11MethodProviders(factory);
- if (!options.retargetCoreLibMember.isEmpty()) {
+ // interface method desugaring also toggles library emulation.
+ if (options.isInterfaceMethodDesugaringEnabled()) {
initializeRetargetCoreLibraryMembers(appView);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 044b50b..752db0e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -126,7 +126,7 @@
.setReceiver(clazz.type)
.setTarget(rewriter.defaultAsMethodOfCompanionClass(method))
.setInvokeType(Invoke.Type.STATIC)
- .setIsInterface(false); // Holder is companion class, not an interface.
+ .setIsInterface(target.isInterface());
return new DexEncodedMethod(
newMethod,
newFlags,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index c5f5e24..e044477 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexLibraryClass;
@@ -86,7 +87,11 @@
MethodAccessFlags newFlags = virtual.accessFlags.copy();
newFlags.unsetBridge();
newFlags.promoteToStatic();
- DexEncodedMethod.setDebugInfoWithFakeThisParameter(code, companionMethod.getArity(), appView);
+ DexCode dexCode = code.asDexCode();
+ dexCode.setDebugInfo(dexCode.debugInfoWithFakeThisParameter(rewriter.factory));
+ assert (dexCode.getDebugInfo() == null)
+ || (companionMethod.getArity() == dexCode.getDebugInfo().parameters.length);
+
DexEncodedMethod implMethod = new DexEncodedMethod(
companionMethod, newFlags, virtual.annotations, virtual.parameterAnnotationsList, code);
virtual.setDefaultInterfaceMethodImplementation(implMethod);
@@ -138,7 +143,11 @@
throw new CompilationError("Code is missing for private instance "
+ "interface method: " + oldMethod.toSourceString(), iface.origin);
}
- DexEncodedMethod.setDebugInfoWithFakeThisParameter(code, companionMethod.getArity(), appView);
+ DexCode dexCode = code.asDexCode();
+ dexCode.setDebugInfo(dexCode.debugInfoWithFakeThisParameter(rewriter.factory));
+ assert (dexCode.getDebugInfo() == null)
+ || (companionMethod.getArity() == dexCode.getDebugInfo().parameters.length);
+
companionMethods.add(new DexEncodedMethod(companionMethod,
newFlags, direct.annotations, direct.parameterAnnotationsList, code));
graphLensBuilder.move(oldMethod, companionMethod);
@@ -223,7 +232,7 @@
forwardSourceCodeBuilder
.setTarget(origMethod)
.setInvokeType(Type.STATIC)
- .setIsInterface(false); // We forward to the Companion class, not an interface.
+ .setIsInterface(true);
DexEncodedMethod newEncodedMethod =
new DexEncodedMethod(
newMethod,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 1c7132a..5be5a81 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
@@ -38,19 +39,22 @@
import java.util.function.Supplier;
/**
- * Represents lambda class generated for a lambda descriptor in context of lambda instantiation
- * point.
+ * Represents lambda class generated for a lambda descriptor in context
+ * of lambda instantiation point.
*
- * <p>Even though call sites, and thus lambda descriptors, are canonicalized across the application,
- * the context may require several lambda classes to be generated for the same lambda descriptor.
+ * Even though call sites, and thus lambda descriptors, are canonicalized
+ * across the application, the context may require several lambda classes
+ * to be generated for the same lambda descriptor.
*
- * <p>One reason is that we always generate a lambda class in the same package lambda instantiation
- * point is located in, so if same call site is used in two classes from different packages (which
- * can happen if same public method is being references via method reference expression) we generate
- * separate lambda classes in those packages.
+ * One reason is that we always generate a lambda class in the same package
+ * lambda instantiation point is located in, so if same call site is used in
+ * two classes from different packages (which can happen if same public method
+ * is being references via method reference expression) we generate separate
+ * lambda classes in those packages.
*
- * <p>Another reason is that if we generate an accessor, we generate it in the class referencing the
- * call site, and thus two such classes will require two separate lambda classes.
+ * Another reason is that if we generate an accessor, we generate it in the
+ * class referencing the call site, and thus two such classes will require two
+ * separate lambda classes.
*/
final class LambdaClass {
@@ -393,11 +397,9 @@
// To avoid potential conflicts on the name of the lambda method once dispatch becomes virtual
// we add the method-holder name as suffix to the lambda-method name.
return new InstanceLambdaImplTarget(
- rewriter.factory.createMethod(
- implMethod.holder,
- implMethod.proto,
- rewriter.factory.createString(
- implMethod.name.toString() + "$" + implMethod.holder.getName())));
+ rewriter.factory.createMethod(implMethod.holder, implMethod.proto,
+ rewriter.factory.createString(
+ implMethod.name.toString() + "$" + implMethod.holder.getName())));
}
}
@@ -508,13 +510,6 @@
DexProgramClass programDefinitionFor(DexType type) {
return rewriter.converter.appView.appInfo().app().programDefinitionFor(type);
}
-
- boolean holderIsInterface() {
- DexMethod implMethod = descriptor.implHandle.asMethod();
- DexClass implMethodHolder = definitionFor(implMethod.holder);
- assert implMethodHolder != null;
- return implMethodHolder.isInterface();
- }
}
// Used for targeting methods referenced directly without creating accessors.
@@ -586,9 +581,10 @@
encodedMethod.getCode());
newMethod.copyMetadata(encodedMethod);
rewriter.methodMapping.put(encodedMethod.method, callTarget);
-
- DexEncodedMethod.setDebugInfoWithFakeThisParameter(
- newMethod.getCode(), callTarget.getArity(), rewriter.converter.appView);
+ DexCode dexCode = newMethod.getCode().asDexCode();
+ dexCode.setDebugInfo(dexCode.debugInfoWithFakeThisParameter(rewriter.factory));
+ assert (dexCode.getDebugInfo() == null)
+ || (callTarget.getArity() == dexCode.getDebugInfo().parameters.length);
implMethodHolder.setDirectMethod(i, newMethod);
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaMainMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaMainMethodSourceCode.java
index a5cf917..99112d7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaMainMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaMainMethodSourceCode.java
@@ -232,7 +232,7 @@
methodToCall.proto,
argValueTypes,
argRegisters,
- target.holderIsInterface()));
+ false /* isInterface */));
// Does the method have return value?
if (enforcedReturnType.isVoidType()) {
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index ed86c65..5699977 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -117,7 +117,7 @@
}
String markerString = marker.toString();
for (DexProgramClass clazz : application.classes()) {
- if (clazz.getSynthesizedFrom().isEmpty() || options.coreLibraryCompilation) {
+ if (clazz.getSynthesizedFrom().isEmpty()) {
writeClass(clazz, consumer, markerString);
} else {
throw new Unimplemented("No support for synthetics in the Java bytecode backend.");
@@ -205,8 +205,7 @@
if (!method.hasClassFileVersion()) {
// In this case bridges have been introduced for the Cf back-end,
// which do not have class file version.
- assert options.testing.enableForceNestBasedAccessDesugaringForTest
- || options.coreLibraryCompilation;
+ assert options.testing.enableForceNestBasedAccessDesugaringForTest;
return 0;
}
return method.getClassFileVersion();
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 7e788e1..b914026 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -286,10 +286,6 @@
throw new UnsupportedOperationException("Cannot find internal output mode.");
}
- public boolean shouldKeepStackMapTable() {
- return coreLibraryCompilation || getProguardConfiguration().getKeepAttributes().stackMapTable;
- }
-
public boolean isGeneratingDex() {
return isGeneratingDexIndexed() || isGeneratingDexFilePerClassFile();
}
diff --git a/src/test/examplesJava9/stream/ProgramRewritingTestClass.java b/src/test/examplesJava9/stream/TestClass.java
similarity index 98%
rename from src/test/examplesJava9/stream/ProgramRewritingTestClass.java
rename to src/test/examplesJava9/stream/TestClass.java
index 7eedeb9..f29a4c8 100644
--- a/src/test/examplesJava9/stream/ProgramRewritingTestClass.java
+++ b/src/test/examplesJava9/stream/TestClass.java
@@ -17,7 +17,7 @@
import java.util.Set;
import java.util.stream.IntStream;
-public class ProgramRewritingTestClass {
+public class TestClass {
// Each print to the console is immediately followed by the expected result so the tests
// can assert the results by checking the lines 2 by 2.
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
index ab28e74..fc2e5df 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
@@ -10,22 +10,15 @@
import com.android.tools.r8.L8Command;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
public class CoreLibDesugarTestBase extends TestBase {
- private static Map<CacheEntry, TestCompileResult> computedLibraryCache =
- new ConcurrentHashMap<>();
-
protected boolean requiresCoreLibDesugaring(TestParameters parameters) {
// TODO(b/134732760): Use the two other APIS instead.
return requiresEmulatedInterfaceCoreLibDesugaring(parameters)
@@ -40,45 +33,10 @@
return parameters.getApiLevel().getLevel() < AndroidApiLevel.P.getLevel();
}
- protected Path buildDesugaredLibrary(AndroidApiLevel apiLevel) throws RuntimeException {
- return buildDesugaredLibrary(apiLevel, "", false);
- }
-
- protected Path buildDesugaredLibrary(AndroidApiLevel apiLevel, String keepRules)
- throws RuntimeException {
- return buildDesugaredLibrary(apiLevel, keepRules, true);
- }
-
- protected Path buildDesugaredLibrary(AndroidApiLevel apiLevel, String keepRules, boolean shrink)
- throws RuntimeException {
- return buildDesugaredLibrary(apiLevel, keepRules, shrink, ImmutableList.of());
- }
-
protected Path buildDesugaredLibrary(
- AndroidApiLevel apiLevel, String keepRules, boolean shrink, List<Path> additionalProgramFiles)
- throws RuntimeException {
- // We wrap exceptions in a RuntimeException to call this from a lambda.
+ AndroidApiLevel apiLevel, List<Path> additionalProgramFiles) {
try {
- Path output = temp.newFolder().toPath().resolve("desugar_jdk_libs_dex.zip");
- CacheEntry cacheEntry = new CacheEntry(apiLevel, keepRules, shrink, additionalProgramFiles);
- TestCompileResult testCompileResult =
- computedLibraryCache.computeIfAbsent(
- cacheEntry,
- key -> compileDesugaredLibrary(apiLevel, keepRules, shrink, additionalProgramFiles));
- testCompileResult.writeToZip(output);
- return output;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private TestCompileResult compileDesugaredLibrary(
- AndroidApiLevel apiLevel, String keepRules, boolean shrink, List<Path> additionalProgramFiles)
- throws RuntimeException {
- // We wrap exceptions in a RuntimeException to call this from a lambda.
- try {
- // TODO(b/138922694): Known performance issue here.
- Path cfDesugaredLib = temp.newFolder().toPath().resolve("desugar_jdk_libs_cf.zip");
+ Path output = temp.newFolder().toPath().resolve("desugar_jdk_libs.zip");
L8.run(
L8Command.builder()
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
@@ -86,64 +44,16 @@
.addProgramFiles(additionalProgramFiles)
.addSpecialLibraryConfiguration("default")
.setMinApiLevel(apiLevel.getLevel())
- .setOutput(cfDesugaredLib, OutputMode.ClassFile)
+ .setOutput(output, OutputMode.DexIndexed)
.build());
- if (shrink) {
- return testForR8(Backend.DEX)
- .addProgramFiles(cfDesugaredLib)
- .noMinification()
- .addKeepRules(keepRules)
- // We still need P+ library files to resolve classes.
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
- .setMinApi(apiLevel)
- .compile();
- }
- return testForD8()
- .addProgramFiles(cfDesugaredLib)
- .setMinApi(apiLevel)
- // We still need P+ library files to resolve classes.
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
- .compile();
+ return output;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
- private static class CacheEntry {
-
- private int apiLevel;
- private String keepRules;
- private boolean shrink;
- private List<Path> additionalProgramFiles;
-
- private CacheEntry(
- AndroidApiLevel apiLevel,
- String keepRules,
- boolean shrink,
- List<Path> additionalProgramFiles) {
- this.apiLevel = apiLevel.getLevel();
- this.keepRules = keepRules;
- this.shrink = shrink;
- this.additionalProgramFiles = additionalProgramFiles;
- }
-
- @Override
- public int hashCode() {
- // In practice there are only 2 sets of additionalProgramFiles with different sizes.
- return Objects.hash(apiLevel, keepRules, shrink, additionalProgramFiles.size());
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof CacheEntry)) {
- return false;
- }
- CacheEntry other = (CacheEntry) o;
- return apiLevel == other.apiLevel
- && keepRules.equals(other.keepRules)
- && shrink == other.shrink
- && additionalProgramFiles.equals(other.additionalProgramFiles);
- }
+ protected Path buildDesugaredLibrary(AndroidApiLevel apiLevel) {
+ return buildDesugaredLibrary(apiLevel, ImmutableList.of());
}
protected void assertLines2By2Correct(String stdOut) {
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/DesugaredLibraryContentTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/DesugaredLibraryContentTest.java
index 20d4868..5d803bd 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/DesugaredLibraryContentTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/DesugaredLibraryContentTest.java
@@ -19,7 +19,6 @@
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import com.google.common.collect.ImmutableSet;
import java.util.stream.Collectors;
-import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -40,7 +39,6 @@
@Test
public void test() throws Exception {
- Assume.assumeTrue(requiresCoreLibDesugaring(parameters));
CodeInspector inspector = new CodeInspector(buildDesugaredLibrary(parameters.getApiLevel()));
assertThat(inspector.clazz("j$.util.Optional"), isPresent());
assertThat(inspector.clazz("j$.util.OptionalInt"), isPresent());
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/ProgramRewritingTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/EmulateLibraryInterfaceTest.java
similarity index 76%
rename from src/test/java/com/android/tools/r8/desugar/corelib/ProgramRewritingTest.java
rename to src/test/java/com/android/tools/r8/desugar/corelib/EmulateLibraryInterfaceTest.java
index 8aeddab..19763ad 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/ProgramRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/EmulateLibraryInterfaceTest.java
@@ -16,111 +16,80 @@
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
-public class ProgramRewritingTest extends CoreLibDesugarTestBase {
-
- private static final String TEST_CLASS = "stream.ProgramRewritingTestClass";
+public class EmulateLibraryInterfaceTest extends CoreLibDesugarTestBase {
private final TestParameters parameters;
- private final boolean shrinkCoreLibrary;
- @Parameters(name = "{1}, shrinkCoreLibrary: {0}")
- public static List<Object[]> data() {
- return buildParameters(
- BooleanUtils.values(), getTestParameters().withDexRuntimes().withAllApiLevels().build());
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
}
- public ProgramRewritingTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
- this.shrinkCoreLibrary = shrinkDesugaredLibrary;
+ public EmulateLibraryInterfaceTest(TestParameters parameters) {
this.parameters = parameters;
}
@Test
- public void testProgramD8() throws Exception {
- Assume.assumeTrue("No desugaring for high API levels", requiresCoreLibDesugaring(parameters));
- Box<String> keepRulesHolder = new Box<>("");
- D8TestRunResult d8TestRunResult =
- testForD8()
- .addProgramFiles(Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "stream.jar"))
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
- .setMinApi(parameters.getApiLevel())
- .addOptionsModification(
- options ->
- options.testing.desugaredLibraryKeepRuleConsumer =
- (string, handler) -> keepRulesHolder.set(keepRulesHolder.get() + string))
- .enableCoreLibraryDesugaring()
- .compile()
- .inspect(this::checkRewrittenInvokes)
- .addRunClasspathFiles(
- buildDesugaredLibrary(
- parameters.getApiLevel(), keepRulesHolder.get(), shrinkCoreLibrary))
- .run(parameters.getRuntime(), TEST_CLASS)
- .assertSuccess();
- assertLines2By2Correct(d8TestRunResult.getStdOut());
- assertGeneratedKeepRulesAreCorrect(keepRulesHolder.get());
- String stdErr = d8TestRunResult.getStdErr();
- if (parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST)) {
- // Flaky: There might be a missing method on lambda deserialization.
+ public void testDispatchClasses() throws Exception {
+ CodeInspector inspector = new CodeInspector(buildDesugaredLibrary(parameters.getApiLevel()));
+ List<FoundClassSubject> dispatchClasses =
+ inspector.allClasses().stream()
+ .filter(
+ clazz ->
+ clazz
+ .getOriginalName()
+ .contains(InterfaceMethodRewriter.EMULATE_LIBRARY_CLASS_NAME_SUFFIX))
+ .collect(Collectors.toList());
+ int numDispatchClasses = requiresCoreLibDesugaring(parameters) ? 9 : 0;
+ assertEquals(numDispatchClasses, dispatchClasses.size());
+ for (FoundClassSubject clazz : dispatchClasses) {
assertTrue(
- !stdErr.contains("Could not find method")
- || stdErr.contains("Could not find method java.lang.invoke.SerializedLambda"));
- } else {
- assertFalse(stdErr.contains("Could not find method"));
+ clazz.allMethods().stream()
+ .allMatch(
+ method ->
+ method.isStatic()
+ && method
+ .streamInstructions()
+ .anyMatch(InstructionSubject::isInstanceOf)));
}
- }
-
- @Test
- public void testProgramR8() throws Exception {
- Assume.assumeTrue("No desugaring for high API levels", requiresCoreLibDesugaring(parameters));
- for (Boolean minifying : BooleanUtils.values()) {
- Box<String> keepRulesHolder = new Box<>("");
- R8TestRunResult r8TestRunResult =
- testForR8(parameters.getBackend())
- .minification(minifying)
- .addKeepMainRule(TEST_CLASS)
- .addProgramFiles(Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "stream.jar"))
- .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
- .setMinApi(parameters.getApiLevel())
- .addOptionsModification(
- options ->
- options.testing.desugaredLibraryKeepRuleConsumer =
- (string, handler) -> keepRulesHolder.set(keepRulesHolder.get() + string))
- .enableCoreLibraryDesugaring()
- .compile()
- .inspect(this::checkRewrittenInvokes)
- .addRunClasspathFiles(
- buildDesugaredLibrary(
- parameters.getApiLevel(), keepRulesHolder.get(), shrinkCoreLibrary))
- .run(parameters.getRuntime(), TEST_CLASS)
- .assertSuccess();
- assertLines2By2Correct(r8TestRunResult.getStdOut());
- assertGeneratedKeepRulesAreCorrect(keepRulesHolder.get());
- if (parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST)) {
- // Flaky: There might be a missing method on lambda deserialization.
- r8TestRunResult.assertStderrMatches(
- anyOf(
- not(containsString("Could not find method")),
- containsString("Could not find method java.lang.invoke.SerializedLambda")));
- } else {
- r8TestRunResult.assertStderrMatches(not(containsString("Could not find method")));
+ if (requiresCoreLibDesugaring(parameters)) {
+ DexClass collectionDispatch = inspector.clazz("j$.util.Collection$-EL").getDexClass();
+ for (DexEncodedMethod method : collectionDispatch.methods()) {
+ int numCheckCast =
+ (int)
+ Stream.of(method.getCode().asDexCode().instructions)
+ .filter(Instruction::isCheckCast)
+ .count();
+ if (method.qualifiedName().contains("spliterator")) {
+ assertEquals(5, numCheckCast);
+ } else {
+ assertEquals(1, numCheckCast);
+ }
}
}
}
@@ -129,7 +98,7 @@
if (!requiresCoreLibDesugaring(parameters)) {
return;
}
- ClassSubject classSubject = inspector.clazz(TEST_CLASS);
+ ClassSubject classSubject = inspector.clazz("stream.TestClass");
assertThat(classSubject, isPresent());
List<InstructionSubject> invokes =
classSubject
@@ -171,6 +140,74 @@
assertTrue(invokes.get(i).toString().contains(s));
}
+ @Test
+ public void testProgramD8() throws Exception {
+ Assume.assumeTrue("No desugaring for high API levels", requiresCoreLibDesugaring(parameters));
+ Box<String> keepRulesHolder = new Box<>("");
+ D8TestRunResult d8TestRunResult =
+ testForD8()
+ .addProgramFiles(Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "stream.jar"))
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(
+ options ->
+ options.testing.desugaredLibraryKeepRuleConsumer =
+ (string, handler) -> keepRulesHolder.set(keepRulesHolder.get() + string))
+ .enableCoreLibraryDesugaring()
+ .compile()
+ .inspect(this::checkRewrittenInvokes)
+ .addRunClasspathFiles(buildDesugaredLibrary(parameters.getApiLevel()))
+ .run(parameters.getRuntime(), "stream.TestClass")
+ .assertSuccess();
+ assertLines2By2Correct(d8TestRunResult.getStdOut());
+ assertGeneratedKeepRulesAreCorrect(keepRulesHolder.get());
+ String stdErr = d8TestRunResult.getStdErr();
+ if (parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST)) {
+ // Flaky: There might be a missing method on lambda deserialization.
+ assertTrue(
+ !stdErr.contains("Could not find method")
+ || stdErr.contains("Could not find method java.lang.invoke.SerializedLambda"));
+ } else {
+ assertFalse(stdErr.contains("Could not find method"));
+ }
+ }
+
+ @Test
+ public void testProgramR8() throws Exception {
+ Assume.assumeTrue("No desugaring for high API levels", requiresCoreLibDesugaring(parameters));
+ for (Boolean minifying : BooleanUtils.values()) {
+ Box<String> keepRulesHolder = new Box<>("");
+ R8TestRunResult r8TestRunResult =
+ testForR8(parameters.getBackend())
+ .minification(minifying)
+ .addKeepMainRule("stream.TestClass")
+ .addProgramFiles(Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "stream.jar"))
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(
+ options ->
+ options.testing.desugaredLibraryKeepRuleConsumer =
+ (string, handler) -> keepRulesHolder.set(keepRulesHolder.get() + string))
+ .enableCoreLibraryDesugaring()
+ .compile()
+ .inspect(this::checkRewrittenInvokes)
+ .addRunClasspathFiles(buildDesugaredLibrary(parameters.getApiLevel()))
+ .run(parameters.getRuntime(), "stream.TestClass")
+ .assertSuccess();
+ assertLines2By2Correct(r8TestRunResult.getStdOut());
+ assertGeneratedKeepRulesAreCorrect(keepRulesHolder.get());
+ if (parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST)) {
+ // Flaky: There might be a missing method on lambda deserialization.
+ r8TestRunResult.assertStderrMatches(
+ anyOf(
+ not(containsString("Could not find method")),
+ containsString("Could not find method java.lang.invoke.SerializedLambda")));
+ } else {
+ r8TestRunResult.assertStderrMatches(not(containsString("Could not find method")));
+ }
+ }
+ }
+
private void assertGeneratedKeepRulesAreCorrect(String keepRules) {
String expectedResult =
StringUtils.lines(
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/EmulatedInterfacesTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/EmulatedInterfacesTest.java
deleted file mode 100644
index cc3a1b0..0000000
--- a/src/test/java/com/android/tools/r8/desugar/corelib/EmulatedInterfacesTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2019, 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.desugar.corelib;
-
-import static junit.framework.TestCase.assertEquals;
-import static junit.framework.TestCase.assertTrue;
-
-import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.code.Instruction;
-import com.android.tools.r8.graph.DexClass;
-import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
-import com.android.tools.r8.utils.BooleanUtils;
-import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
-import com.android.tools.r8.utils.codeinspector.InstructionSubject;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import org.junit.Assume;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class EmulatedInterfacesTest extends CoreLibDesugarTestBase {
-
- private final TestParameters parameters;
- private final boolean shrinkCoreLibrary;
-
- @Parameters(name = "{1}, shrinkCoreLibrary: {0}")
- public static List<Object[]> data() {
- return buildParameters(
- BooleanUtils.values(), getTestParameters().withDexRuntimes().withAllApiLevels().build());
- }
-
- public EmulatedInterfacesTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
- this.shrinkCoreLibrary = shrinkDesugaredLibrary;
- this.parameters = parameters;
- }
-
- @Test
- public void testEmulatedInterface() throws Exception {
- Assume.assumeTrue((requiresCoreLibDesugaring(parameters)));
- CodeInspector inspector =
- new CodeInspector(
- buildDesugaredLibrary(
- parameters.getApiLevel(), "-keep class **$-EL", shrinkCoreLibrary));
- assertEmulateInterfaceClassesPresentWithDispatchMethods(inspector);
- assertCollectionMethodsPresentWithCorrectDispatch(inspector);
- }
-
- private void assertEmulateInterfaceClassesPresentWithDispatchMethods(CodeInspector inspector) {
- List<FoundClassSubject> dispatchClasses =
- inspector.allClasses().stream()
- .filter(
- clazz ->
- clazz
- .getOriginalName()
- .contains(InterfaceMethodRewriter.EMULATE_LIBRARY_CLASS_NAME_SUFFIX))
- .collect(Collectors.toList());
- int numDispatchClasses = 9;
- assertEquals(numDispatchClasses, dispatchClasses.size());
- for (FoundClassSubject clazz : dispatchClasses) {
- assertTrue(
- clazz.allMethods().stream()
- .allMatch(
- method ->
- method.isStatic()
- && method
- .streamInstructions()
- .anyMatch(InstructionSubject::isInstanceOf)));
- }
- }
-
- private void assertCollectionMethodsPresentWithCorrectDispatch(CodeInspector inspector) {
- DexClass collectionDispatch = inspector.clazz("j$.util.Collection$-EL").getDexClass();
- for (DexEncodedMethod method : collectionDispatch.methods()) {
- int numCheckCast =
- (int)
- Stream.of(method.getCode().asDexCode().instructions)
- .filter(Instruction::isCheckCast)
- .count();
- if (method.qualifiedName().contains("spliterator")) {
- assertEquals(5, numCheckCast);
- } else {
- assertEquals(1, numCheckCast);
- }
- }
- }
-}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java b/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
index f4f5807..36561cb 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/MergingJ$Test.java
@@ -47,27 +47,20 @@
}
private Path buildSplitDesugaredLibraryPart1() throws Exception {
- Path outputCf = temp.newFolder().toPath().resolve("merger-input-cf.zip");
- Path outputDex = temp.newFolder().toPath().resolve("merger-input-dex.zip");
+ Path output = temp.newFolder().toPath().resolve("merger-input.zip");
L8.run(
L8Command.builder()
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(ToolHelper.getDesugarJDKLibs())
.addSpecialLibraryConfiguration("default")
.setMinApiLevel(AndroidApiLevel.B.getLevel())
- .setOutput(outputCf, OutputMode.ClassFile)
+ .setOutput(output, OutputMode.DexIndexed)
.build());
- testForD8()
- .addProgramFiles(outputCf)
- .setMinApi(AndroidApiLevel.B)
- .compile()
- .writeToZip(outputDex);
- return outputDex;
+ return output;
}
private Path buildSplitDesugaredLibraryPart2() throws Exception {
- Path outputCf = temp.newFolder().toPath().resolve("merger-input-split-cf.zip");
- Path outputDex = temp.newFolder().toPath().resolve("merger-input-split-dex.zip");
+ Path output = temp.newFolder().toPath().resolve("merger-input-split.zip");
L8.run(
L8Command.builder()
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
@@ -75,13 +68,8 @@
.addClasspathFiles(ToolHelper.getDesugarJDKLibs())
.addSpecialLibraryConfiguration("default")
.setMinApiLevel(AndroidApiLevel.B.getLevel())
- .setOutput(outputCf, OutputMode.ClassFile)
+ .setOutput(output, OutputMode.DexIndexed)
.build());
- testForD8()
- .addProgramFiles(outputCf)
- .setMinApi(AndroidApiLevel.B)
- .compile()
- .writeToZip(outputDex);
- return outputDex;
+ return output;
}
}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11CoreLibTestBase.java b/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11CoreLibTestBase.java
index 169c7f9..f77099a 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11CoreLibTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11CoreLibTestBase.java
@@ -103,6 +103,6 @@
protected Path buildDesugaredLibraryWithJavaBaseExtension(AndroidApiLevel apiLevel)
throws Exception {
return buildDesugaredLibrary(
- apiLevel, "", false, ImmutableList.copyOf(JDK_11_JAVA_BASE_EXTENSION_COMPILED_FILES));
+ apiLevel, ImmutableList.copyOf(JDK_11_JAVA_BASE_EXTENSION_COMPILED_FILES));
}
}