Merge commit '54a1c60229a9124084ddcfba5bc4521b10825ce3' into dev-release
diff --git a/.gitignore b/.gitignore
index 24eead1..d78f4a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -121,6 +121,16 @@
third_party/openjdk/desugar_jdk_libs.tar.gz
third_party/openjdk/desugar_jdk_libs_11
third_party/openjdk/desugar_jdk_libs_11.tar.gz
+third_party/openjdk/desugar_jdk_libs_releases/1.0.9
+third_party/openjdk/desugar_jdk_libs_releases/1.0.9.tar.gz
+third_party/openjdk/desugar_jdk_libs_releases/1.0.10
+third_party/openjdk/desugar_jdk_libs_releases/1.0.10.tar.gz
+third_party/openjdk/desugar_jdk_libs_releases/1.1.0
+third_party/openjdk/desugar_jdk_libs_releases/1.1.0.tar.gz
+third_party/openjdk/desugar_jdk_libs_releases/1.1.1
+third_party/openjdk/desugar_jdk_libs_releases/1.1.1.tar.gz
+third_party/openjdk/desugar_jdk_libs_releases/1.1.5
+third_party/openjdk/desugar_jdk_libs_releases/1.1.5.tar.gz
third_party/openjdk/jdk-15/linux
third_party/openjdk/jdk-15/linux.tar.gz
third_party/openjdk/jdk-15/osx
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index faa8808..c3902b8 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -82,7 +82,10 @@
return results
def CopyRightInContents(f, contents):
- expected = ('#' if f.LocalPath().endswith('.py') else '//') + ' Copyright'
+ expected = '//'
+ if f.LocalPath().endswith('.py') or f.LocalPath().endswith('.sh'):
+ expected = '#'
+ expected = expected + ' Copyright'
for content_line in contents:
if expected in content_line:
return True
diff --git a/build.gradle b/build.gradle
index f69b505..7f0d08f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -336,6 +336,11 @@
"openjdk/openjdk-rt-1.8",
"openjdk/desugar_jdk_libs",
"openjdk/desugar_jdk_libs_11",
+ "openjdk/desugar_jdk_libs_releases/1.0.9",
+ "openjdk/desugar_jdk_libs_releases/1.0.10",
+ "openjdk/desugar_jdk_libs_releases/1.1.0",
+ "openjdk/desugar_jdk_libs_releases/1.1.1",
+ "openjdk/desugar_jdk_libs_releases/1.1.5",
"openjdk/jdk-11-test",
"proguard/proguard5.2.1",
"proguard/proguard6.0.1",
diff --git a/scripts/import_released_desugar_jdk_libs.sh b/scripts/import_released_desugar_jdk_libs.sh
new file mode 100755
index 0000000..6f02117
--- /dev/null
+++ b/scripts/import_released_desugar_jdk_libs.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+#
+# Copyright (c) 2021, 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.
+
+set -e
+set -x
+
+if [[ -z "$1" ]]; then
+ echo "No version argument supplied"
+ exit -1
+fi
+
+VERSION=$1
+
+RELEASES_ROOT=third_party/openjdk/desugar_jdk_libs_releases
+mkdir -p $RELEASES_ROOT
+RELEASED_VERSION_DIR=$RELEASES_ROOT/$VERSION
+if [[ -d $RELEASED_VERSION_DIR ]]; then
+ echo "$RELEASED_VERSION_DIR already exists"
+ exit -1
+fi
+
+MAVEN_REPO_DIR=/tmp/maven_repo_local
+rm -rf $MAVEN_REPO_DIR
+
+DOWNLOAD_DIR=/tmp/desugar_jdk_libs_download
+rm -rf $DOWNLOAD_DIR
+mkdir -p $DOWNLOAD_DIR
+
+mvn \
+ org.apache.maven.plugins:maven-dependency-plugin:2.4:get \
+ -Dmaven.repo.local=$MAVEN_REPO_DIR \
+ -DremoteRepositories=http://maven.google.com \
+ -Dartifact=com.android.tools:desugar_jdk_libs:$VERSION \
+ -Ddest=$DOWNLOAD_DIR/desugar_jdk_libs.jar
+
+mvn \
+ org.apache.maven.plugins:maven-dependency-plugin:2.4:get \
+ -Dmaven.repo.local=$MAVEN_REPO_DIR \
+ -DremoteRepositories=http://maven.google.com \
+ -Dartifact=com.android.tools:desugar_jdk_libs_configuration:$VERSION \
+ -Ddest=$DOWNLOAD_DIR/desugar_jdk_libs_configuration.jar
+
+ unzip $DOWNLOAD_DIR/desugar_jdk_libs_configuration.jar META-INF/desugar/d8/desugar.json -d $DOWNLOAD_DIR
+
+ mkdir $RELEASED_VERSION_DIR
+ cp $DOWNLOAD_DIR/desugar_jdk_libs.jar $RELEASED_VERSION_DIR
+ cp $DOWNLOAD_DIR/desugar_jdk_libs_configuration.jar $RELEASED_VERSION_DIR
+ cp $DOWNLOAD_DIR/META-INF/desugar/d8/desugar.json $RELEASED_VERSION_DIR/desugar.json
+ cp third_party/openjdk/desugar_jdk_libs/README.google $RELEASED_VERSION_DIR
+
+ (cd $RELEASES_ROOT && \
+ upload_to_google_storage.py -a --bucket r8-deps $VERSION && \
+ git add $VERSION.tar.gz.sha1)
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index e02ccfb..6edb405 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -344,6 +344,18 @@
options.getProguardConfiguration().getRules(), synthesizedProguardRules))
.build(executorService));
+ // Compute the main dex rootset that will be the base of first and final main dex tracing
+ // before building a new appview with only live classes (and invalidating subtypingInfo).
+ if (!options.mainDexKeepRules.isEmpty()) {
+ assert appView.graphLens().isIdentityLens();
+ // Find classes which may have code executed before secondary dex files installation.
+ MainDexRootSet mainDexRootSet =
+ MainDexRootSet.builder(appView, subtypingInfo, options.mainDexKeepRules)
+ .build(executorService);
+ appView.setMainDexRootSet(mainDexRootSet);
+ appView.appInfo().unsetObsolete();
+ }
+
AnnotationRemover.Builder annotationRemoverBuilder =
options.isShrinking() ? AnnotationRemover.builder() : null;
AppView<AppInfoWithLiveness> appViewWithLiveness =
@@ -423,6 +435,7 @@
// Build conservative main dex content after first round of tree shaking. This is used
// by certain optimizations to avoid introducing additional class references into main dex
// classes, as that can cause the final number of main dex methods to grow.
+ // TODO(b/190941270): See if we can move this up before treepruning.
performInitialMainDexTracing(appView, executorService);
// The class type lattice elements include information about the interfaces that a class
@@ -853,16 +866,12 @@
return;
}
assert appView.graphLens().isIdentityLens();
- // Find classes which may have code executed before secondary dex files installation.
- SubtypingInfo subtypingInfo = new SubtypingInfo(appView);
- MainDexRootSet mainDexRootSet =
- MainDexRootSet.builder(appView, subtypingInfo, options.mainDexKeepRules)
- .build(executorService);
- appView.setMainDexRootSet(mainDexRootSet);
- appView.appInfo().unsetObsolete();
- // Live types is the tracing result.
+
+ // Find classes which may have code executed before secondary dex files installation by
+ // computing from the initially computed main dex root set.
MainDexInfo mainDexInfo =
- EnqueuerFactory.createForInitialMainDexTracing(appView, executorService, subtypingInfo)
+ EnqueuerFactory.createForInitialMainDexTracing(
+ appView, executorService, new SubtypingInfo(appView))
.traceMainDex(executorService, timing);
appView.setAppInfo(appView.appInfo().rebuildWithMainDexInfo(mainDexInfo));
}
diff --git a/src/main/java/com/android/tools/r8/ResourceShrinker.java b/src/main/java/com/android/tools/r8/ResourceShrinker.java
index bf4f471..bf40d89 100644
--- a/src/main/java/com/android/tools/r8/ResourceShrinker.java
+++ b/src/main/java/com/android/tools/r8/ResourceShrinker.java
@@ -259,7 +259,7 @@
.flatMap(f -> f.annotations().stream());
Stream<DexAnnotation> methodAnnotations =
Streams.stream(classDef.methods())
- .filter(DexEncodedMethod::hasAnnotation)
+ .filter(DexEncodedMethod::hasAnyAnnotations)
.flatMap(m -> m.annotations().stream());
Streams.concat(classAnnotations, fieldAnnotations, methodAnnotations)
diff --git a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
index bc57c25..02aebd3 100644
--- a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
@@ -352,7 +352,7 @@
@Override
public void print(CfConstNull constNull) {
- throw new Unimplemented(constNull.getClass().getSimpleName());
+ printNewInstruction("CfConstNull");
}
@Override
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index eee2f72..3b2c1df 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -557,7 +557,7 @@
clazz.annotations().annotations,
annotations.toArray(DexAnnotation.EMPTY_ARRAY),
DexAnnotation.class);
- clazz.setAnnotations(new DexAnnotationSet(copy));
+ clazz.setAnnotations(DexAnnotationSet.create(copy));
}
// Clear the attribute structures now that they are represented in annotations.
@@ -572,7 +572,7 @@
}
// Append the annotations to annotations array of the field.
field.setAnnotations(
- new DexAnnotationSet(
+ DexAnnotationSet.create(
ArrayUtils.appendSingleElement(
field.annotations().annotations,
DexAnnotation.createSignatureAnnotation(
@@ -587,7 +587,7 @@
}
// Append the annotations to annotations array of the method.
method.setAnnotations(
- new DexAnnotationSet(
+ DexAnnotationSet.create(
ArrayUtils.appendSingleElement(
method.annotations().annotations,
DexAnnotation.createSignatureAnnotation(
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index e2b7f93..b279333 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -396,7 +396,7 @@
for (int i = 0; i < size; i++) {
values[i] = annotationSetAt(annotationOffsets[i]);
}
- return new ParameterAnnotationsList(values);
+ return ParameterAnnotationsList.create(values);
}
private DexParameterAnnotation[] parseParameterAnnotations(int size) {
@@ -485,7 +485,7 @@
throw new CompilationError(
"Multiple annotations of type `" + dupType.toSourceString() + "`");
}
- return new DexAnnotationSet(result);
+ return DexAnnotationSet.create(result);
}
private boolean retainAnnotation(DexAnnotation annotation) {
@@ -1375,7 +1375,7 @@
int size = lazyAnnotations.size();
return size == 0
? DexAnnotationSet.empty()
- : new DexAnnotationSet(lazyAnnotations.toArray(DexAnnotation.EMPTY_ARRAY));
+ : DexAnnotationSet.create(lazyAnnotations.toArray(DexAnnotation.EMPTY_ARRAY));
}
return originalAnnotations;
}
diff --git a/src/main/java/com/android/tools/r8/graph/ClasspathClass.java b/src/main/java/com/android/tools/r8/graph/ClasspathClass.java
index 9ae72e4..3801ef8 100644
--- a/src/main/java/com/android/tools/r8/graph/ClasspathClass.java
+++ b/src/main/java/com/android/tools/r8/graph/ClasspathClass.java
@@ -4,4 +4,10 @@
package com.android.tools.r8.graph;
-public interface ClasspathClass extends ClasspathDefinition, ClasspathOrLibraryClass {}
+public interface ClasspathClass extends ClasspathDefinition, ClasspathOrLibraryClass {
+
+ @Override
+ default DexClass asDexClass() {
+ return asClasspathClass();
+ }
+}
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 cf385e0..da19912 100644
--- a/src/main/java/com/android/tools/r8/graph/ClasspathOrLibraryClass.java
+++ b/src/main/java/com/android/tools/r8/graph/ClasspathOrLibraryClass.java
@@ -4,4 +4,6 @@
package com.android.tools.r8.graph;
-public interface ClasspathOrLibraryClass extends ClassDefinition, ClasspathOrLibraryDefinition {}
+public interface ClasspathOrLibraryClass extends ClassDefinition, ClasspathOrLibraryDefinition {
+ DexClass asDexClass();
+}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
index 454be57..40ff50e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
@@ -30,8 +30,7 @@
public static final DexAnnotationSet[] EMPTY_ARRAY = {};
private static final int UNSORTED = 0;
- private static final DexAnnotationSet THE_EMPTY_ANNOTATIONS_SET =
- new DexAnnotationSet(DexAnnotation.EMPTY_ARRAY);
+ private static final DexAnnotationSet THE_EMPTY_ANNOTATIONS_SET = new DexAnnotationSet();
public final DexAnnotation[] annotations;
private int sorted = UNSORTED;
@@ -40,11 +39,16 @@
spec.withItemArray(a -> a.annotations);
}
- public DexAnnotationSet(DexAnnotation[] annotations) {
+ private DexAnnotationSet() {
+ this.annotations = DexAnnotation.EMPTY_ARRAY;
+ }
+
+ private DexAnnotationSet(DexAnnotation[] annotations) {
+ assert !ArrayUtils.isEmpty(annotations);
this.annotations = annotations;
}
- public DexAnnotationSet create(DexAnnotation[] annotations) {
+ public static DexAnnotationSet create(DexAnnotation[] annotations) {
return ArrayUtils.isEmpty(annotations) ? empty() : new DexAnnotationSet(annotations);
}
@@ -160,7 +164,7 @@
if (index < reducedArray.length) {
System.arraycopy(annotations, index + 1, reducedArray, index, reducedArray.length - index);
}
- return new DexAnnotationSet(reducedArray);
+ return DexAnnotationSet.create(reducedArray);
}
++index;
}
@@ -180,7 +184,7 @@
if (annotation.annotation.type == newAnnotation.annotation.type) {
DexAnnotation[] modifiedArray = annotations.clone();
modifiedArray[index] = newAnnotation;
- return new DexAnnotationSet(modifiedArray);
+ return DexAnnotationSet.create(modifiedArray);
}
++index;
}
@@ -189,7 +193,7 @@
DexAnnotation[] extendedArray = new DexAnnotation[annotations.length + 1];
System.arraycopy(annotations, 0, extendedArray, 0, annotations.length);
extendedArray[annotations.length] = newAnnotation;
- return new DexAnnotationSet(extendedArray);
+ return DexAnnotationSet.create(extendedArray);
}
public DexAnnotationSet keepIf(Predicate<DexAnnotation> filter) {
@@ -242,7 +246,7 @@
}
}
}
- return newAnnotations == null ? this : new DexAnnotationSet(newAnnotations);
+ return newAnnotations == null ? this : DexAnnotationSet.create(newAnnotations);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexClassAndField.java b/src/main/java/com/android/tools/r8/graph/DexClassAndField.java
index e2deec9..2c78b93 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClassAndField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClassAndField.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.graph;
+import com.android.tools.r8.ir.optimize.info.FieldOptimizationInfo;
import com.android.tools.r8.references.FieldReference;
public abstract class DexClassAndField extends DexClassAndMember<DexEncodedField, DexField> {
@@ -35,6 +36,11 @@
return getReference().asFieldReference();
}
+ @Override
+ public FieldOptimizationInfo getOptimizationInfo() {
+ return getDefinition().getOptimizationInfo();
+ }
+
public DexType getType() {
return getReference().getType();
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClassAndMember.java b/src/main/java/com/android/tools/r8/graph/DexClassAndMember.java
index 2ac7ced..4aebe97 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClassAndMember.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClassAndMember.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.ir.optimize.info.MemberOptimizationInfo;
import com.android.tools.r8.origin.Origin;
public abstract class DexClassAndMember<D extends DexEncodedMember<D, R>, R extends DexMember<D, R>>
@@ -49,6 +50,10 @@
return definition.getReference();
}
+ public MemberOptimizationInfo<?> getOptimizationInfo() {
+ return getDefinition().getOptimizationInfo();
+ }
+
@Override
public Origin getOrigin() {
return holder.origin;
diff --git a/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java b/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
index ccc7dbc..53cbfe8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClassAndMethod.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.graph;
+import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
import com.android.tools.r8.references.MethodReference;
public abstract class DexClassAndMethod extends DexClassAndMember<DexEncodedMethod, DexMethod>
@@ -52,6 +53,11 @@
return getReference().getSignature();
}
+ @Override
+ public MethodOptimizationInfo getOptimizationInfo() {
+ return getDefinition().getOptimizationInfo();
+ }
+
public DexType getParameter(int index) {
return getReference().getParameter(index);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinition.java b/src/main/java/com/android/tools/r8/graph/DexDefinition.java
index 2695b1f..c2e8fae 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDefinition.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinition.java
@@ -25,6 +25,11 @@
return !annotations().isEmpty();
}
+ // Also returns true if a method has parameter annotations.
+ public boolean hasAnyAnnotations() {
+ return hasAnnotations();
+ }
+
public DexAnnotationSet annotations() {
return annotations;
}
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 f8a2537..36cb33c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -48,7 +48,6 @@
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraint;
import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.Invoke;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -63,16 +62,14 @@
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
-import com.android.tools.r8.ir.synthetic.FieldAccessorBuilder;
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
-import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
-import com.android.tools.r8.ir.synthetic.SynthesizedCode;
import com.android.tools.r8.kotlin.KotlinMethodLevelInfo;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.position.MethodPosition;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
@@ -890,6 +887,11 @@
}
@Override
+ public boolean hasAnyAnnotations() {
+ return hasAnnotations() || hasParameterAnnotations();
+ }
+
+ @Override
public void clearAllAnnotations() {
clearAnnotations();
clearParameterAnnotations();
@@ -917,6 +919,10 @@
return parameterAnnotationsList;
}
+ public boolean hasParameterAnnotations() {
+ return !getParameterAnnotations().isEmpty();
+ }
+
public void setParameterAnnotations(ParameterAnnotationsList parameterAnnotations) {
this.parameterAnnotationsList = parameterAnnotations;
}
@@ -1220,89 +1226,12 @@
return builder.build();
}
- public ProgramMethod toInitializerForwardingBridge(
- DexProgramClass holder, DexMethod newMethod, DexItemFactory dexItemFactory) {
- assert isPrivate()
- : "Expected to create bridge for private constructor as part of nest-based access"
- + " desugaring";
- assert !holder.isInterface();
- return new ProgramMethod(
- holder,
- syntheticBuilder(this)
- .setMethod(newMethod)
- .setCode(
- ForwardMethodBuilder.builder(dexItemFactory)
- .setNonStaticSourceWithExtraUnusedParameter(newMethod)
- .setConstructorTarget(getReference())
- .build())
- .modifyAccessFlags(
- accessFlags -> {
- assert !accessFlags.isStatic();
- accessFlags.unsetPrivate();
- accessFlags.setSynthetic();
- accessFlags.setConstructor();
- })
- .build());
- }
-
- public static ProgramMethod createFieldAccessorBridge(
- ProgramField field, boolean isGet, DexMethod newMethod) {
- MethodAccessFlags accessFlags =
- MethodAccessFlags.fromSharedAccessFlags(
- Constants.ACC_SYNTHETIC
- | Constants.ACC_STATIC
- | (field.getHolder().isInterface() ? Constants.ACC_PUBLIC : 0),
- false);
- CfCode code =
- FieldAccessorBuilder.builder()
- .apply(isGet ? FieldAccessorBuilder::setGetter : FieldAccessorBuilder::setSetter)
- .setField(field)
- .setSourceMethod(newMethod)
- .build();
- return new ProgramMethod(
- field.getHolder(),
- new DexEncodedMethod(
- newMethod,
- accessFlags,
- MethodTypeSignature.noSignature(),
- DexAnnotationSet.empty(),
- ParameterAnnotationsList.empty(),
- code,
- true));
- }
-
public DexEncodedMethod toRenamedHolderMethod(DexType newHolderType, DexItemFactory factory) {
DexEncodedMethod.Builder builder = DexEncodedMethod.builder(this);
builder.setMethod(getReference().withHolder(newHolderType, factory));
return builder.build();
}
- public ProgramMethod toStaticForwardingBridge(
- DexProgramClass holder, DexMethod newMethod, DexItemFactory dexItemFactory) {
- assert isPrivate()
- : "Expected to create bridge for private method as part of nest-based access desugaring";
- return new ProgramMethod(
- holder,
- syntheticBuilder(this)
- .setMethod(newMethod)
- .setCode(
- ForwardMethodBuilder.builder(dexItemFactory)
- .setStaticSource(newMethod)
- .applyIf(
- isStatic(),
- builder -> builder.setStaticTarget(getReference(), holder.isInterface()),
- builder -> builder.setDirectTarget(getReference(), holder.isInterface()))
- .build())
- .setAccessFlags(
- MethodAccessFlags.builder()
- .setBridge()
- .setPublic(holder.isInterface())
- .setStatic()
- .setSynthetic()
- .build())
- .build());
- }
-
public ProgramMethod toPrivateSyntheticMethod(DexProgramClass holder, DexMethod method) {
assert !isStatic();
assert !isPrivate();
@@ -1381,31 +1310,28 @@
// Some debuggers (like IntelliJ) automatically skip synthetic methods on single step.
newFlags.setSynthetic();
newFlags.unsetAbstract();
- ForwardMethodSourceCode.Builder forwardSourceCodeBuilder =
- ForwardMethodSourceCode.builder(newMethod);
- forwardSourceCodeBuilder
- .setReceiver(clazz.type)
- .setTarget(forwardMethod)
- .setInvokeType(Invoke.Type.STATIC)
- .setIsInterface(false); // Holder is companion class, or retarget method, not an interface.
return new DexEncodedMethod(
newMethod,
newFlags,
MethodTypeSignature.noSignature(),
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
- new SynthesizedCode(forwardSourceCodeBuilder::build),
+ ForwardMethodBuilder.builder(factory)
+ .setNonStaticSource(newMethod)
+ // Holder is companion class, or retarget method, not an interface.
+ .setStaticTarget(forwardMethod, false)
+ .build(),
true);
}
- public DexEncodedMethod toStaticMethodWithoutThis() {
+ public DexEncodedMethod toStaticMethodWithoutThis(AppView<AppInfoWithLiveness> appView) {
checkIfObsolete();
assert !accessFlags.isStatic();
Builder builder =
builder(this)
.promoteToStatic()
.withoutThisParameter()
- .adjustOptimizationInfoAfterRemovingThisParameter()
+ .adjustOptimizationInfoAfterRemovingThisParameter(appView)
.setGenericSignature(MethodTypeSignature.noSignature());
DexEncodedMethod method = builder.build();
method.copyMetadata(this);
@@ -1462,11 +1388,6 @@
return this;
}
- public boolean hasAnnotation() {
- checkIfObsolete();
- return !annotations().isEmpty() || !parameterAnnotationsList.isEmpty();
- }
-
public static int slowCompare(DexEncodedMethod m1, DexEncodedMethod m2) {
return m1.getReference().compareTo(m2.getReference());
}
@@ -1535,26 +1456,34 @@
return new Builder(from, true);
}
+ public static Builder builder() {
+ return new Builder();
+ }
+
private static Builder builder(DexEncodedMethod from) {
return new Builder(from);
}
public static class Builder {
- private DexMethod method;
private MethodAccessFlags accessFlags;
- private MethodTypeSignature genericSignature;
- private final DexAnnotationSet annotations;
- private OptionalBool isLibraryMethodOverride = OptionalBool.UNKNOWN;
- private ParameterAnnotationsList parameterAnnotations;
private Code code;
- private CompilationState compilationState;
- private MethodOptimizationInfo optimizationInfo;
- private KotlinMethodLevelInfo kotlinMemberInfo;
- private final CfVersion classFileVersion;
- private boolean d8R8Synthesized;
+ private DexMethod method;
+
+ private MethodTypeSignature genericSignature = MethodTypeSignature.noSignature();
+ private DexAnnotationSet annotations = DexAnnotationSet.empty();
+ private OptionalBool isLibraryMethodOverride = OptionalBool.UNKNOWN;
+ private ParameterAnnotationsList parameterAnnotations = ParameterAnnotationsList.empty();
+ private CompilationState compilationState = CompilationState.NOT_PROCESSED;
+ private MethodOptimizationInfo optimizationInfo = DefaultMethodOptimizationInfo.getInstance();
+ private KotlinMethodLevelInfo kotlinInfo = getNoKotlinInfo();
+ private CfVersion classFileVersion = null;
+ private boolean d8R8Synthesized = false;
+
private Consumer<DexEncodedMethod> buildConsumer = ConsumerUtils.emptyConsumer();
+ private Builder() {}
+
private Builder(DexEncodedMethod from) {
this(from, from.isD8R8Synthesized());
}
@@ -1562,26 +1491,25 @@
private Builder(DexEncodedMethod from, boolean d8R8Synthesized) {
// Copy all the mutable state of a DexEncodedMethod here.
method = from.getReference();
- accessFlags = from.accessFlags.copy();
+ accessFlags = from.getAccessFlags().copy();
genericSignature = from.getGenericSignature();
annotations = from.annotations();
- code = from.code;
- compilationState = CompilationState.NOT_PROCESSED;
+ code = from.getCode();
optimizationInfo =
- from.optimizationInfo.isMutableOptimizationInfo()
- ? from.optimizationInfo.asMutableMethodOptimizationInfo().mutableCopy()
- : from.optimizationInfo;
- kotlinMemberInfo = from.kotlinMemberInfo;
+ from.getOptimizationInfo().isMutableOptimizationInfo()
+ ? from.getOptimizationInfo().asMutableMethodOptimizationInfo().mutableCopy()
+ : from.getOptimizationInfo();
+ kotlinInfo = from.getKotlinInfo();
classFileVersion = from.classFileVersion;
this.d8R8Synthesized = d8R8Synthesized;
- if (from.parameterAnnotationsList.isEmpty()
- || from.parameterAnnotationsList.size() == method.proto.parameters.size()) {
- parameterAnnotations = from.parameterAnnotationsList;
+ if (from.getParameterAnnotations().isEmpty()
+ || from.getParameterAnnotations().size() == from.getParameters().size()) {
+ parameterAnnotations = from.getParameterAnnotations();
} else {
// If the there are missing parameter annotations populate these when creating the builder.
parameterAnnotations =
- from.parameterAnnotationsList.withParameterCount(method.proto.parameters.size());
+ from.getParameterAnnotations().withParameterCount(from.getParameters().size());
}
}
@@ -1625,6 +1553,11 @@
return this;
}
+ public Builder setD8R8Synthesized() {
+ this.d8R8Synthesized = true;
+ return this;
+ }
+
public Builder setMethod(DexMethod method) {
this.method = method;
return this;
@@ -1684,7 +1617,7 @@
}
return setParameterAnnotations(
- new ParameterAnnotationsList(
+ ParameterAnnotationsList.create(
newParameterAnnotations.toArray(DexAnnotationSet.EMPTY_ARRAY),
newNumberOfMissingParameterAnnotations));
}
@@ -1704,11 +1637,12 @@
return this;
}
- public Builder adjustOptimizationInfoAfterRemovingThisParameter() {
+ public Builder adjustOptimizationInfoAfterRemovingThisParameter(
+ AppView<AppInfoWithLiveness> appView) {
if (optimizationInfo.isMutableOptimizationInfo()) {
optimizationInfo
.asMutableMethodOptimizationInfo()
- .adjustOptimizationInfoAfterRemovingThisParameter();
+ .adjustOptimizationInfoAfterRemovingThisParameter(appView);
}
return this;
}
@@ -1735,7 +1669,7 @@
code,
d8R8Synthesized,
classFileVersion);
- result.setKotlinMemberInfo(kotlinMemberInfo);
+ result.setKotlinMemberInfo(kotlinInfo);
result.compilationState = compilationState;
result.optimizationInfo = optimizationInfo;
if (!isLibraryMethodOverride.isUnknown()) {
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index 3c01abb..0b179ac 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -610,7 +610,7 @@
"Multiple annotations of type `" + dupType.toSourceString() + "`");
}
}
- return new DexAnnotationSet(annotations.toArray(DexAnnotation.EMPTY_ARRAY));
+ return DexAnnotationSet.create(annotations.toArray(DexAnnotation.EMPTY_ARRAY));
}
private static class CreateFieldVisitor extends FieldVisitor {
@@ -885,7 +885,7 @@
for (int i = 0; i < parameterAnnotationsLists.size(); i++) {
sets[i] = createAnnotationSet(parameterAnnotationsLists.get(i), options);
}
- parameterAnnotationsList = new ParameterAnnotationsList(sets);
+ parameterAnnotationsList = ParameterAnnotationsList.create(sets);
}
if (parameterNames != null) {
assert parameterFlags != null;
diff --git a/src/main/java/com/android/tools/r8/graph/LibraryClass.java b/src/main/java/com/android/tools/r8/graph/LibraryClass.java
index f4a7081..a45c77f 100644
--- a/src/main/java/com/android/tools/r8/graph/LibraryClass.java
+++ b/src/main/java/com/android/tools/r8/graph/LibraryClass.java
@@ -4,4 +4,10 @@
package com.android.tools.r8.graph;
-public interface LibraryClass extends LibraryDefinition, ClasspathOrLibraryClass {}
+public interface LibraryClass extends LibraryDefinition, ClasspathOrLibraryClass {
+
+ @Override
+ default DexClass asDexClass() {
+ return asLibraryClass();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodCollection.java b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
index 635132f..2412ea7 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodCollection.java
@@ -322,7 +322,7 @@
public boolean hasAnnotations() {
return traverse(
method ->
- method.hasAnnotation()
+ method.hasAnyAnnotations()
? TraversalContinuation.BREAK
: TraversalContinuation.CONTINUE)
.shouldBreak();
diff --git a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
index ba98190..fdda61b 100644
--- a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
+++ b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
@@ -60,23 +60,34 @@
this.missingParameterAnnotations = 0;
}
- public ParameterAnnotationsList(DexAnnotationSet[] values) {
- this(values, 0);
- }
-
- public ParameterAnnotationsList(DexAnnotationSet[] values, int missingParameterAnnotations) {
- assert values != null && values.length > 0;
+ private ParameterAnnotationsList(DexAnnotationSet[] values, int missingParameterAnnotations) {
+ assert values != null;
+ assert values.length > 0;
+ assert !isAllEmpty(values);
this.values = values;
this.missingParameterAnnotations = missingParameterAnnotations;
}
+ public static ParameterAnnotationsList create(DexAnnotationSet[] values) {
+ return create(values, 0);
+ }
+
public static ParameterAnnotationsList create(
DexAnnotationSet[] values, int missingParameterAnnotations) {
- return ArrayUtils.isEmpty(values)
+ return ArrayUtils.isEmpty(values) || isAllEmpty(values)
? empty()
: new ParameterAnnotationsList(values, missingParameterAnnotations);
}
+ private static boolean isAllEmpty(DexAnnotationSet[] values) {
+ for (int i = 0; i < values.length; i++) {
+ if (!values[i].isEmpty()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
@Override
public ParameterAnnotationsList self() {
return this;
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
index 4291896..ee41edb 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/DesugaredLibraryConversionWrapperAnalysis.java
@@ -6,14 +6,11 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramDefinition;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter;
import com.android.tools.r8.ir.desugar.DesugaredLibraryAPIConverter.Mode;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
-import java.util.IdentityHashMap;
-import java.util.Map;
import java.util.function.Consumer;
public class DesugaredLibraryConversionWrapperAnalysis extends EnqueuerAnalysis
@@ -21,7 +18,6 @@
private final AppView<?> appView;
private final DesugaredLibraryAPIConverter converter;
- private Map<DexType, DexClasspathClass> synthesizedWrappers = new IdentityHashMap<>();
public DesugaredLibraryConversionWrapperAnalysis(AppView<?> appView) {
this.appView = appView;
@@ -68,6 +64,6 @@
}
public void generateWrappers(Consumer<DexClasspathClass> synthesizedCallback) {
- converter.synthesizeWrappers(synthesizedWrappers, synthesizedCallback);
+ converter.synthesizeWrappers(synthesizedCallback);
}
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
index 8f59c36..6e9e19f 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/RespectPackageBoundaries.java
@@ -6,12 +6,16 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.horizontalclassmerging.MergeGroup;
import com.android.tools.r8.horizontalclassmerging.MultiClassPolicy;
import com.android.tools.r8.shaking.VerticalClassMerger.IllegalAccessDetector;
import com.android.tools.r8.utils.TraversalContinuation;
+import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
@@ -31,6 +35,26 @@
return true;
}
+ // Annotations may access non-public items (or themselves be non-public), so for now we
+ // conservatively restrict class merging when annotations are present.
+ //
+ // Note that in non-compat mode we should never see any annotations here, since we only merge
+ // non-kept classes with non-kept members.
+ if (clazz.hasAnnotations()
+ || Iterables.any(clazz.members(), DexDefinition::hasAnyAnnotations)) {
+ return true;
+ }
+
+ // Check that each implemented interface is public.
+ for (DexType interfaceType : clazz.getInterfaces()) {
+ if (clazz.getType().isSamePackage(interfaceType)) {
+ DexClass interfaceClass = appView.definitionFor(interfaceType);
+ if (interfaceClass == null || !interfaceClass.isPublic()) {
+ return true;
+ }
+ }
+ }
+
// If any members are package private or protected, then their access depends on the package.
for (DexEncodedMember<?, ?> member : clazz.members()) {
if (member.getAccessFlags().isPackagePrivateOrProtected()) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/AlwaysSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/AlwaysSimpleInliningConstraint.java
index 32e01d8..a164607 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/AlwaysSimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/AlwaysSimpleInliningConstraint.java
@@ -30,6 +30,12 @@
}
@Override
+ public SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory) {
+ return this;
+ }
+
+ @Override
public SimpleInliningConstraint rewrittenWithUnboxedArguments(IntList unboxedArgumentIndices) {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanFalseSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanFalseSimpleInliningConstraint.java
index a4a6a73..351d51d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanFalseSimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanFalseSimpleInliningConstraint.java
@@ -34,6 +34,13 @@
}
@Override
+ public SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory) {
+ assert getArgumentIndex() > 0;
+ return factory.createBooleanFalseConstraint(getArgumentIndex() - 1);
+ }
+
+ @Override
public SimpleInliningConstraint rewrittenWithUnboxedArguments(IntList unboxedArgumentIndices) {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanTrueSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanTrueSimpleInliningConstraint.java
index f69381f..bf3fde3 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanTrueSimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/BooleanTrueSimpleInliningConstraint.java
@@ -34,6 +34,13 @@
}
@Override
+ public SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory) {
+ assert getArgumentIndex() > 0;
+ return factory.createBooleanTrueConstraint(getArgumentIndex() - 1);
+ }
+
+ @Override
public SimpleInliningConstraint rewrittenWithUnboxedArguments(IntList unboxedArgumentIndices) {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NeverSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NeverSimpleInliningConstraint.java
index 9407b7b..4568e5f 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NeverSimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NeverSimpleInliningConstraint.java
@@ -29,6 +29,12 @@
}
@Override
+ public SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory) {
+ return this;
+ }
+
+ @Override
public SimpleInliningConstraint rewrittenWithUnboxedArguments(IntList unboxedArgumentIndices) {
return this;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NotNullSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NotNullSimpleInliningConstraint.java
index ea41ccb..0834cba 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NotNullSimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NotNullSimpleInliningConstraint.java
@@ -34,6 +34,13 @@
}
@Override
+ public SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory) {
+ assert getArgumentIndex() > 0;
+ return factory.createNotNullConstraint(getArgumentIndex() - 1);
+ }
+
+ @Override
public SimpleInliningConstraint rewrittenWithUnboxedArguments(IntList unboxedArgumentIndices) {
if (unboxedArgumentIndices.contains(getArgumentIndex())) {
// TODO(b/176067541): Could be refined to an argument-equals-int constraint.
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NullSimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NullSimpleInliningConstraint.java
index 76d075d..2dce46e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/NullSimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/NullSimpleInliningConstraint.java
@@ -34,6 +34,13 @@
}
@Override
+ public SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory) {
+ assert getArgumentIndex() > 0;
+ return factory.createNullConstraint(getArgumentIndex() - 1);
+ }
+
+ @Override
public SimpleInliningConstraint rewrittenWithUnboxedArguments(IntList unboxedArgumentIndices) {
if (unboxedArgumentIndices.contains(getArgumentIndex())) {
// TODO(b/176067541): Could be refined to an argument-equals-int constraint.
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraint.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraint.java
index b411c8b..df108ac 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraint.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraint.java
@@ -106,6 +106,9 @@
return new SimpleInliningConstraintDisjunction(ImmutableList.of(this, other));
}
+ public abstract SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory);
+
public abstract SimpleInliningConstraint rewrittenWithUnboxedArguments(
IntList unboxedArgumentIndices);
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintConjunction.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintConjunction.java
index 02a8536..c993b12 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintConjunction.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintConjunction.java
@@ -66,15 +66,25 @@
}
@Override
+ public SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory) {
+ List<SimpleInliningConstraint> rewrittenConstraints =
+ ListUtils.mapOrElse(
+ constraints, constraint -> constraint.fixupAfterRemovingThisParameter(factory), null);
+ return rewrittenConstraints != null
+ ? new SimpleInliningConstraintConjunction(rewrittenConstraints)
+ : this;
+ }
+
+ @Override
public SimpleInliningConstraint rewrittenWithUnboxedArguments(IntList unboxedArgumentIndices) {
List<SimpleInliningConstraint> rewrittenConstraints =
ListUtils.mapOrElse(
constraints,
constraint -> constraint.rewrittenWithUnboxedArguments(unboxedArgumentIndices),
null);
- if (rewrittenConstraints != null) {
- return new SimpleInliningConstraintConjunction(rewrittenConstraints);
- }
- return this;
+ return rewrittenConstraints != null
+ ? new SimpleInliningConstraintConjunction(rewrittenConstraints)
+ : this;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintDisjunction.java b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintDisjunction.java
index c069f37..a6b418d 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintDisjunction.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/inlining/SimpleInliningConstraintDisjunction.java
@@ -66,15 +66,25 @@
}
@Override
+ public SimpleInliningConstraint fixupAfterRemovingThisParameter(
+ SimpleInliningConstraintFactory factory) {
+ List<SimpleInliningConstraint> rewrittenConstraints =
+ ListUtils.mapOrElse(
+ constraints, constraint -> constraint.fixupAfterRemovingThisParameter(factory), null);
+ return rewrittenConstraints != null
+ ? new SimpleInliningConstraintDisjunction(rewrittenConstraints)
+ : this;
+ }
+
+ @Override
public SimpleInliningConstraint rewrittenWithUnboxedArguments(IntList unboxedArgumentIndices) {
List<SimpleInliningConstraint> rewrittenConstraints =
ListUtils.mapOrElse(
constraints,
constraint -> constraint.rewrittenWithUnboxedArguments(unboxedArgumentIndices),
null);
- if (rewrittenConstraints != null) {
- return new SimpleInliningConstraintDisjunction(rewrittenConstraints);
- }
- return this;
+ return rewrittenConstraints != null
+ ? new SimpleInliningConstraintDisjunction(rewrittenConstraints)
+ : this;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Invoke.java b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
index 02c1ad0..27f9d4b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Invoke.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Invoke.java
@@ -178,6 +178,7 @@
}
public Value getArgument(int index) {
+ assert index < arguments().size();
return arguments().get(index);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
index 39f52cb..6a83961 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
@@ -269,6 +269,6 @@
}
}
- return optimizationInfo.mayHaveSideEffects();
+ return optimizationInfo.mayHaveSideEffects(this, appView.options());
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index 1b3aef3..9313b59 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -216,11 +216,11 @@
}
// Verify that the target method does not have side-effects.
- if (appViewWithLiveness.appInfo().noSideEffects.containsKey(singleTarget.getReference())) {
+ if (appViewWithLiveness.appInfo().isAssumeNoSideEffectsMethod(singleTarget)) {
return false;
}
- if (singleTarget.getDefinition().getOptimizationInfo().mayHaveSideEffects()) {
+ if (singleTarget.getOptimizationInfo().mayHaveSideEffects(this, appView.options())) {
return true;
}
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 f68c904..3f52f3d 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
@@ -894,6 +894,9 @@
if (appView.options().protoShrinking().enableRemoveProtoEnumSwitchMap()) {
appView.protoShrinker().protoEnumSwitchMapRemover.updateVisibleStaticFieldValues();
}
+ if (enumUnboxer != null) {
+ enumUnboxer.updateEnumUnboxingCandidatesInfo();
+ }
assert delayedOptimizationFeedback.noUpdatesLeft();
onWaveDoneActions.forEach(com.android.tools.r8.utils.Action::execute);
onWaveDoneActions = null;
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 021ffa2..b287221 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
@@ -199,6 +199,12 @@
initializeStreamMethodProviders(factory);
}
+ if (appView.rewritePrefix.hasRewrittenType(factory.supplierType, appView)) {
+ // TODO(b/191188594): Consider adding the Objects method from R here, or instead
+ // rely on desugared library to support them.
+ initializeObjectsMethodProviders(factory);
+ }
+
// These are currently not implemented at any API level in Android.
initializeJava9MethodProviders(factory);
initializeJava10MethodProviders(factory);
@@ -1347,6 +1353,19 @@
new MethodGenerator(method, BackportedMethods::StreamMethods_ofNullable, "ofNullable"));
}
+ private void initializeObjectsMethodProviders(DexItemFactory factory) {
+ // Objects
+ DexType type = factory.objectsType;
+
+ // Objects.requireNonNull(Object, Supplier)
+ DexString name = factory.createString("requireNonNull");
+ DexProto proto =
+ factory.createProto(factory.objectType, factory.objectType, factory.supplierType);
+ DexMethod method = factory.createMethod(type, proto, name);
+ addProvider(
+ new MethodGenerator(method, BackportedMethods::ObjectsMethods_requireNonNullSupplier));
+ }
+
private void addProvider(MethodProvider generator) {
if (appView.options().desugaredLibraryConfiguration.isSupported(generator.method, appView)) {
// TODO(b/174453232): Remove this after the configuration file format has bee updated
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
index 6394d39..5fc1537 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryAPIConverter.java
@@ -107,7 +107,7 @@
public void desugar(IRCode code) {
- if (wrapperSynthesizor.hasSynthesized(code.method().getHolderType())) {
+ if (wrapperSynthesizor.isSyntheticWrapper(code.method().getHolderType())) {
return;
}
@@ -310,7 +310,7 @@
SortedProgramMethodSet callbacks = generateCallbackMethods();
irConverter.processMethodsConcurrently(callbacks, executorService);
if (appView.options().isDesugaredLibraryCompilation()) {
- wrapperSynthesizor.finalizeWrappersForL8(builder, irConverter, executorService);
+ wrapperSynthesizor.finalizeWrappersForL8();
}
}
@@ -337,10 +337,8 @@
return allCallbackMethods;
}
- public void synthesizeWrappers(
- Map<DexType, DexClasspathClass> synthesizedWrappers,
- Consumer<DexClasspathClass> synthesizedCallback) {
- wrapperSynthesizor.synthesizeWrappersForClasspath(synthesizedWrappers, synthesizedCallback);
+ public void synthesizeWrappers(Consumer<DexClasspathClass> synthesizedCallback) {
+ wrapperSynthesizor.synthesizeWrappersForClasspath(synthesizedCallback);
}
private ProgramMethod generateCallbackMethod(
@@ -409,11 +407,11 @@
}
DexType returnType = invokedMethod.proto.returnType;
if (appView.rewritePrefix.hasRewrittenType(returnType, appView) && canConvert(returnType)) {
- registerConversionWrappers(returnType, vivifiedTypeFor(returnType, appView));
+ registerConversionWrappers(returnType);
}
for (DexType argType : invokedMethod.proto.parameters.values) {
if (appView.rewritePrefix.hasRewrittenType(argType, appView) && canConvert(argType)) {
- registerConversionWrappers(argType, argType);
+ registerConversionWrappers(argType);
}
}
}
@@ -549,7 +547,7 @@
private Instruction createParameterConversion(
IRCode code, DexType argType, DexType argVivifiedType, Value inValue) {
- DexMethod conversionMethod = createConversionMethod(argType, argType, argVivifiedType);
+ DexMethod conversionMethod = ensureConversionMethod(argType, argType, argVivifiedType);
// The value is null only if the input is null.
Value convertedValue =
createConversionValue(code, inValue.getType().nullability(), argVivifiedType, null);
@@ -558,7 +556,7 @@
private Instruction createReturnConversionAndReplaceUses(
IRCode code, InvokeMethod invokeMethod, DexType returnType, DexType returnVivifiedType) {
- DexMethod conversionMethod = createConversionMethod(returnType, returnVivifiedType, returnType);
+ DexMethod conversionMethod = ensureConversionMethod(returnType, returnVivifiedType, returnType);
Value outValue = invokeMethod.outValue();
Value convertedValue =
createConversionValue(code, Nullability.maybeNull(), returnType, outValue.getLocalInfo());
@@ -569,17 +567,13 @@
return new InvokeStatic(conversionMethod, convertedValue, Collections.singletonList(outValue));
}
- private void registerConversionWrappers(DexType type, DexType srcType) {
+ private void registerConversionWrappers(DexType type) {
if (appView.options().desugaredLibraryConfiguration.getCustomConversions().get(type) == null) {
- if (type == srcType) {
- wrapperSynthesizor.getTypeWrapper(type);
- } else {
- wrapperSynthesizor.getVivifiedTypeWrapper(type);
- }
+ wrapperSynthesizor.registerWrapper(type);
}
}
- public DexMethod createConversionMethod(DexType type, DexType srcType, DexType destType) {
+ public DexMethod ensureConversionMethod(DexType type, DexType srcType, DexType destType) {
// ConversionType holds the methods "rewrittenType convert(type)" and the other way around.
// But everything is going to be rewritten, so we need to use vivifiedType and type".
DexType conversionHolder =
@@ -587,8 +581,8 @@
if (conversionHolder == null) {
conversionHolder =
type == srcType
- ? wrapperSynthesizor.getTypeWrapper(type)
- : wrapperSynthesizor.getVivifiedTypeWrapper(type);
+ ? wrapperSynthesizor.ensureTypeWrapper(type)
+ : wrapperSynthesizor.ensureVivifiedTypeWrapper(type);
}
assert conversionHolder != null;
return factory.createMethod(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
index a0153a0..eb354b0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryRetargeter.java
@@ -367,14 +367,6 @@
}
private InvokeRetargetingResult computeRetargetLibraryMember(DexMethod method) {
- Map<DexType, DexType> backportCoreLibraryMembers =
- appView.options().desugaredLibraryConfiguration.getBackportCoreLibraryMember();
- if (backportCoreLibraryMembers.containsKey(method.holder)) {
- DexType newHolder = backportCoreLibraryMembers.get(method.holder);
- DexMethod newMethod =
- appView.dexItemFactory().createMethod(newHolder, method.proto, method.name);
- return InvokeRetargetingResult.createInvokeRetargetingResult(newMethod);
- }
DexClassAndMethod emulatedMethod = emulatedDispatchMethods.get(method);
if (emulatedMethod != null) {
assert !emulatedMethod.getAccessFlags().isStatic();
@@ -517,7 +509,12 @@
List<DexClassAndMethod> found = new ArrayList<>();
clazz.forEachClassMethodMatching(
definition -> definition.getName() == methodName, found::add);
- assert !found.isEmpty() : "Should have found a method (library specifications).";
+ assert !found.isEmpty()
+ : "Should have found a method (library specifications) for "
+ + clazz.toSourceString()
+ + "."
+ + methodName
+ + ". Maybe the library used for the compilation should be newer.";
return found;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
index e0c6d41..00c8bff 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/DesugaredLibraryWrapperSynthesizer.java
@@ -4,16 +4,14 @@
package com.android.tools.r8.ir.desugar;
-import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
-import com.android.tools.r8.graph.ClassAccessFlags;
-import com.android.tools.r8.graph.ClassKind;
+import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -21,38 +19,33 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
-import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.FieldAccessFlags;
-import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.graph.GenericSignature.FieldTypeSignature;
import com.android.tools.r8.graph.GenericSignature.MethodTypeSignature;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
-import com.android.tools.r8.ir.conversion.IRConverter;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterConstructorCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterThrowRuntimeExceptionCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterVivifiedWrapperCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperConversionCfCodeProvider;
-import com.android.tools.r8.origin.SynthesizedOrigin;
+import com.android.tools.r8.synthesis.SyntheticClassBuilder;
+import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
-import java.util.IdentityHashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.function.BiConsumer;
import java.util.function.Consumer;
+import java.util.function.Function;
// I am responsible for the generation of wrappers used to call library APIs when desugaring
// libraries. Wrappers can be both ways, wrapping the desugarType as a type, or the type as
@@ -99,16 +92,8 @@
// }
public class DesugaredLibraryWrapperSynthesizer {
- public static final String WRAPPER_PACKAGE = "wrappers/";
- public static final String WRAPPER_PREFIX = "$r8$wrapper$";
- public static final String TYPE_WRAPPER_SUFFIX = "$-WRP";
- public static final String VIVIFIED_TYPE_WRAPPER_SUFFIX = "$-V-WRP";
-
private final AppView<?> appView;
- private final String dexWrapperPrefixString;
- private final DexString dexWrapperPrefixDexString;
- private final Map<DexType, DexType> typeWrappers = new ConcurrentHashMap<>();
- private final Map<DexType, DexType> vivifiedTypeWrappers = new ConcurrentHashMap<>();
+ private final Set<DexType> wrappersToGenerate = Sets.newConcurrentHashSet();
// The invalidWrappers are wrappers with incorrect behavior because of final methods that could
// not be overridden. Such wrappers are awful because the runtime behavior is undefined and does
// not raise explicit errors. So we register them here and conversion methods for such wrappers
@@ -120,55 +105,29 @@
DesugaredLibraryWrapperSynthesizer(AppView<?> appView, DesugaredLibraryAPIConverter converter) {
this.appView = appView;
this.factory = appView.dexItemFactory();
- dexWrapperPrefixString =
- "L"
- + appView
- .options()
- .desugaredLibraryConfiguration
- .getSynthesizedLibraryClassesPackagePrefix()
- + WRAPPER_PACKAGE
- + WRAPPER_PREFIX;
- dexWrapperPrefixDexString = factory.createString(dexWrapperPrefixString);
this.converter = converter;
}
- boolean hasSynthesized(DexType type) {
- return type.descriptor.startsWith(dexWrapperPrefixDexString);
+ public boolean isSyntheticWrapper(DexType type) {
+ return appView.getSyntheticItems().isSyntheticOfKind(type, SyntheticKind.WRAPPER)
+ || appView.getSyntheticItems().isSyntheticOfKind(type, SyntheticKind.VIVIFIED_WRAPPER);
}
boolean canGenerateWrapper(DexType type) {
return appView.options().desugaredLibraryConfiguration.getWrapperConversions().contains(type);
}
- DexType getTypeWrapper(DexType type) {
- // Force create the reverse wrapper.
- getWrapper(type, VIVIFIED_TYPE_WRAPPER_SUFFIX, vivifiedTypeWrappers);
- return getWrapper(type, TYPE_WRAPPER_SUFFIX, typeWrappers);
+ DexType ensureTypeWrapper(DexType type) {
+ return ensureWrappers(type).getWrapper().type;
}
- DexType getVivifiedTypeWrapper(DexType type) {
- // Force create the reverse wrapper.
- getWrapper(type, TYPE_WRAPPER_SUFFIX, typeWrappers);
- return getWrapper(type, VIVIFIED_TYPE_WRAPPER_SUFFIX, vivifiedTypeWrappers);
+ DexType ensureVivifiedTypeWrapper(DexType type) {
+ return ensureWrappers(type).getVivifiedWrapper().type;
}
- private DexType createWrapperType(DexType type, String suffix) {
- return factory.createType(
- dexWrapperPrefixString + type.toString().replace('.', '$') + suffix + ";");
- }
-
- private DexType getWrapper(DexType type, String suffix, Map<DexType, DexType> wrappers) {
- assert !type.toString().startsWith(DesugaredLibraryAPIConverter.VIVIFIED_PREFIX);
- return wrappers.computeIfAbsent(
- type,
- t -> {
- assert canGenerateWrapper(type) : type;
- DexType wrapperType = createWrapperType(type, suffix);
- assert converter.canGenerateWrappersAndCallbacks()
- || appView.definitionFor(wrapperType).isClasspathClass()
- : "Wrapper " + wrapperType + " should have been generated in the enqueuer.";
- return wrapperType;
- });
+ public void registerWrapper(DexType type) {
+ wrappersToGenerate.add(type);
+ assert getValidClassToWrap(type) != null;
}
private DexClass getValidClassToWrap(DexType type) {
@@ -184,68 +143,242 @@
return DesugaredLibraryAPIConverter.vivifiedTypeFor(type, appView);
}
- private DexClass generateTypeWrapper(
- ClassKind<?> classKind, DexClass dexClass, DexType typeWrapperType) {
- DexType type = dexClass.type;
- DexEncodedField wrapperField = synthesizeWrappedValueEncodedField(typeWrapperType, type);
- return synthesizeWrapper(
- classKind,
- vivifiedTypeFor(type),
- dexClass,
- synthesizeVirtualMethodsForTypeWrapper(dexClass, wrapperField),
- generateTypeConversion(type, typeWrapperType),
- wrapperField);
+ static class Wrappers {
+ private final DexClass wrapper;
+ private final DexClass vivifiedWrapper;
+
+ Wrappers(DexClass wrapper, DexClass vivifiedWrapper) {
+ this.wrapper = wrapper;
+ this.vivifiedWrapper = vivifiedWrapper;
+ }
+
+ public DexClass getWrapper() {
+ return wrapper;
+ }
+
+ public DexClass getVivifiedWrapper() {
+ return vivifiedWrapper;
+ }
}
- private DexClass generateVivifiedTypeWrapper(
- ClassKind<?> classKind, DexClass dexClass, DexType vivifiedTypeWrapperType) {
- DexType type = dexClass.type;
- DexEncodedField wrapperField =
- synthesizeWrappedValueEncodedField(vivifiedTypeWrapperType, vivifiedTypeFor(type));
- return synthesizeWrapper(
- classKind,
- type,
- dexClass,
- synthesizeVirtualMethodsForVivifiedTypeWrapper(dexClass, wrapperField),
- generateVivifiedTypeConversion(type, vivifiedTypeWrapperType),
- wrapperField);
+ private Wrappers ensureWrappers(DexType type) {
+ assert canGenerateWrapper(type) : type;
+ DexClass dexClass = getValidClassToWrap(type);
+ return ensureWrappers(dexClass, ignored -> {});
}
- private DexClass synthesizeWrapper(
- ClassKind<?> classKind,
+ private Wrappers ensureWrappers(DexClass context, Consumer<DexClasspathClass> creationCallback) {
+ DexType type = context.type;
+ DexClass wrapper;
+ DexClass vivifiedWrapper;
+ if (context.isProgramClass()) {
+ assert appView.options().isDesugaredLibraryCompilation();
+ DexProgramClass programContext = context.asProgramClass();
+ wrapper =
+ ensureProgramWrapper(
+ SyntheticKind.WRAPPER,
+ vivifiedTypeFor(type),
+ type,
+ programContext,
+ wrapperField -> synthesizeVirtualMethodsForTypeWrapper(programContext, wrapperField));
+ vivifiedWrapper =
+ ensureProgramWrapper(
+ SyntheticKind.VIVIFIED_WRAPPER,
+ type,
+ vivifiedTypeFor(type),
+ programContext,
+ wrapperField ->
+ synthesizeVirtualMethodsForVivifiedTypeWrapper(programContext, wrapperField));
+ DexField wrapperField = getWrapperUniqueField(wrapper);
+ DexField vivifiedWrapperField = getWrapperUniqueField(vivifiedWrapper);
+ ensureProgramConversionMethod(
+ SyntheticKind.WRAPPER, programContext, wrapperField, vivifiedWrapperField);
+ ensureProgramConversionMethod(
+ SyntheticKind.VIVIFIED_WRAPPER, programContext, vivifiedWrapperField, wrapperField);
+ } else {
+ assert context.isNotProgramClass();
+ ClasspathOrLibraryClass classpathOrLibraryContext = context.asClasspathOrLibraryClass();
+ wrapper =
+ ensureClasspathWrapper(
+ SyntheticKind.WRAPPER,
+ vivifiedTypeFor(type),
+ type,
+ classpathOrLibraryContext,
+ creationCallback,
+ wrapperField -> synthesizeVirtualMethodsForTypeWrapper(context, wrapperField));
+ vivifiedWrapper =
+ ensureClasspathWrapper(
+ SyntheticKind.VIVIFIED_WRAPPER,
+ type,
+ vivifiedTypeFor(type),
+ classpathOrLibraryContext,
+ creationCallback,
+ wrapperField ->
+ synthesizeVirtualMethodsForVivifiedTypeWrapper(context, wrapperField));
+ DexField wrapperField = getWrapperUniqueField(wrapper);
+ DexField vivifiedWrapperField = getWrapperUniqueField(vivifiedWrapper);
+ ensureClasspathConversionMethod(
+ SyntheticKind.WRAPPER, classpathOrLibraryContext, wrapperField, vivifiedWrapperField);
+ ensureClasspathConversionMethod(
+ SyntheticKind.VIVIFIED_WRAPPER,
+ classpathOrLibraryContext,
+ vivifiedWrapperField,
+ wrapperField);
+ }
+ return new Wrappers(wrapper, vivifiedWrapper);
+ }
+
+ private DexEncodedField getWrapperUniqueEncodedField(DexClass wrapper) {
+ assert wrapper.instanceFields().size() == 1;
+ return wrapper.instanceFields().get(0);
+ }
+
+ private DexField getWrapperUniqueField(DexClass wrapper) {
+ return getWrapperUniqueEncodedField(wrapper).getReference();
+ }
+
+ private DexProgramClass ensureProgramWrapper(
+ SyntheticKind kind,
DexType wrappingType,
+ DexType wrappedType,
+ DexProgramClass programContext,
+ Function<DexEncodedField, DexEncodedMethod[]> virtualMethodProvider) {
+ return appView
+ .getSyntheticItems()
+ .ensureFixedClass(
+ kind,
+ programContext,
+ appView,
+ builder -> buildWrapper(wrappingType, wrappedType, programContext, builder),
+ // The creation of virtual methods may require new wrappers, this needs to happen
+ // once the wrapper is created to avoid infinite recursion.
+ wrapper ->
+ wrapper.setVirtualMethods(
+ virtualMethodProvider.apply(getWrapperUniqueEncodedField(wrapper))));
+ }
+
+ private DexClasspathClass ensureClasspathWrapper(
+ SyntheticKind kind,
+ DexType wrappingType,
+ DexType wrappedType,
+ ClasspathOrLibraryClass classpathOrLibraryContext,
+ Consumer<DexClasspathClass> creationCallback,
+ Function<DexEncodedField, DexEncodedMethod[]> virtualMethodProvider) {
+ return appView
+ .getSyntheticItems()
+ .ensureFixedClasspathClass(
+ kind,
+ classpathOrLibraryContext,
+ appView,
+ builder ->
+ buildWrapper(
+ wrappingType, wrappedType, classpathOrLibraryContext.asDexClass(), builder),
+ // The creation of virtual methods may require new wrappers, this needs to happen
+ // once the wrapper is created to avoid infinite recursion.
+ wrapper -> {
+ wrapper.setVirtualMethods(
+ virtualMethodProvider.apply(getWrapperUniqueEncodedField(wrapper)));
+ creationCallback.accept(wrapper);
+ });
+ }
+
+ private ProgramMethod ensureProgramConversionMethod(
+ SyntheticKind kind,
+ DexProgramClass context,
+ DexField wrapperField,
+ DexField reverseWrapperField) {
+ return appView
+ .getSyntheticItems()
+ .ensureFixedClassMethod(
+ factory.convertMethodName,
+ factory.createProto(reverseWrapperField.type, wrapperField.type),
+ kind,
+ context,
+ appView,
+ ignored -> {},
+ methodBuilder ->
+ buildConversionMethod(
+ methodBuilder, wrapperField, reverseWrapperField, context.type));
+ }
+
+ private DexClassAndMethod ensureClasspathConversionMethod(
+ SyntheticKind kind,
+ ClasspathOrLibraryClass context,
+ DexField wrapperField,
+ DexField reverseWrapperField) {
+ return appView
+ .getSyntheticItems()
+ .ensureFixedClasspathClassMethod(
+ factory.convertMethodName,
+ factory.createProto(reverseWrapperField.type, wrapperField.type),
+ kind,
+ context,
+ appView,
+ ignored -> {},
+ methodBuilder ->
+ buildConversionMethod(
+ methodBuilder, wrapperField, reverseWrapperField, context.getType()));
+ }
+
+ private void buildConversionMethod(
+ SyntheticMethodBuilder methodBuilder,
+ DexField wrapperField,
+ DexField reverseWrapperField,
+ DexType reportingType) {
+ CfCode cfCode;
+ if (invalidWrappers.contains(wrapperField.holder)) {
+ cfCode =
+ new APIConverterThrowRuntimeExceptionCfCodeProvider(
+ appView,
+ factory.createString(
+ "Unsupported conversion for "
+ + reportingType
+ + ". See compilation time warnings for more details."),
+ wrapperField.holder)
+ .generateCfCode();
+ } else {
+ cfCode =
+ new APIConverterWrapperConversionCfCodeProvider(
+ appView, reverseWrapperField, wrapperField)
+ .generateCfCode();
+ }
+ methodBuilder
+ .setAccessFlags(
+ MethodAccessFlags.fromCfAccessFlags(
+ Constants.ACC_SYNTHETIC | Constants.ACC_STATIC | Constants.ACC_PUBLIC, false))
+ .setCode(methodSignature -> cfCode);
+ }
+
+ private void buildWrapper(
+ DexType wrappingType,
+ DexType wrappedType,
DexClass clazz,
- DexEncodedMethod[] virtualMethods,
- DexEncodedMethod conversionMethod,
- DexEncodedField wrapperField) {
+ SyntheticClassBuilder<?, ?> builder) {
boolean isItf = clazz.isInterface();
DexType superType = isItf ? factory.objectType : wrappingType;
- DexTypeList interfaces =
- isItf ? new DexTypeList(new DexType[] {wrappingType}) : DexTypeList.empty();
- return classKind.create(
- wrapperField.getHolderType(),
- Kind.CF,
- new SynthesizedOrigin("Desugared library API Converter", getClass()),
- ClassAccessFlags.fromSharedAccessFlags(
- Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC),
- superType,
- interfaces,
- clazz.sourceFile,
- null,
- Collections.emptyList(),
- null,
- Collections.emptyList(),
- ClassSignature.noSignature(),
- DexAnnotationSet.empty(),
- DexEncodedField.EMPTY_ARRAY, // No static fields.
- new DexEncodedField[] {wrapperField},
- new DexEncodedMethod[] {
- synthesizeConstructor(wrapperField.getReference()), conversionMethod
- },
- virtualMethods,
- factory.getSkipNameValidationForTesting(),
- DexProgramClass::checksumFromType,
- null);
+ List<DexType> interfaces =
+ isItf ? Collections.singletonList(wrappingType) : Collections.emptyList();
+ DexEncodedField wrapperField =
+ synthesizeWrappedValueEncodedField(builder.getType(), wrappedType);
+ builder
+ .setInterfaces(interfaces)
+ .setSuperType(superType)
+ .setInstanceFields(Collections.singletonList(wrapperField))
+ .addMethod(methodBuilder -> buildWrapperConstructor(wrapperField, methodBuilder));
+ }
+
+ private void buildWrapperConstructor(
+ DexEncodedField wrappedValueField, SyntheticMethodBuilder methodBuilder) {
+ methodBuilder
+ .setName(factory.constructorMethodName)
+ .setProto(factory.createProto(factory.voidType, wrappedValueField.getType()))
+ .setAccessFlags(
+ MethodAccessFlags.fromCfAccessFlags(
+ Constants.ACC_PRIVATE | Constants.ACC_SYNTHETIC, true))
+ .setCode(
+ codeSynthesizor ->
+ new APIConverterConstructorCfCodeProvider(appView, wrappedValueField.getReference())
+ .generateCfCode());
}
private DexEncodedMethod[] synthesizeVirtualMethodsForVivifiedTypeWrapper(
@@ -441,166 +574,33 @@
field, fieldAccessFlags, FieldTypeSignature.noSignature(), DexAnnotationSet.empty(), null);
}
- private DexEncodedMethod synthesizeConstructor(DexField field) {
- DexMethod method =
- factory.createMethod(
- field.holder,
- factory.createProto(factory.voidType, field.type),
- factory.constructorMethodName);
- return newSynthesizedMethod(
- method,
- Constants.ACC_PRIVATE | Constants.ACC_SYNTHETIC,
- true,
- new APIConverterConstructorCfCodeProvider(appView, field).generateCfCode());
- }
-
- private DexEncodedMethod newSynthesizedMethod(
- DexMethod methodToInstall, int flags, boolean constructor, Code code) {
- MethodAccessFlags accessFlags = MethodAccessFlags.fromSharedAccessFlags(flags, constructor);
- return new DexEncodedMethod(
- methodToInstall,
- accessFlags,
- MethodTypeSignature.noSignature(),
- DexAnnotationSet.empty(),
- ParameterAnnotationsList.empty(),
- code,
- true);
- }
-
- void finalizeWrappersForL8(
- DexApplication.Builder<?> builder, IRConverter irConverter, ExecutorService executorService)
- throws ExecutionException {
- List<DexProgramClass> synthesizedWrappers = synthesizeWrappers();
- registerAndProcessWrappers(builder, irConverter, executorService, synthesizedWrappers);
- }
-
- private List<DexProgramClass> synthesizeWrappers() {
+ void finalizeWrappersForL8() {
DesugaredLibraryConfiguration conf = appView.options().desugaredLibraryConfiguration;
for (DexType type : conf.getWrapperConversions()) {
assert !conf.getCustomConversions().containsKey(type);
- getTypeWrapper(type);
- }
- Map<DexType, DexClass> synthesizedWrappers = new IdentityHashMap<>();
- List<DexProgramClass> additions = new ArrayList<>();
- int total = typeWrappers.size() + vivifiedTypeWrappers.size();
- generateWrappers(
- ClassKind.PROGRAM,
- synthesizedWrappers.keySet(),
- (type, wrapper) -> {
- synthesizedWrappers.put(type, wrapper);
- additions.add(wrapper.asProgramClass());
- });
- assert total == typeWrappers.size() + vivifiedTypeWrappers.size() : "unexpected additions";
- return additions;
- }
-
- void synthesizeWrappersForClasspath(
- Map<DexType, DexClasspathClass> synthesizedWrappers,
- Consumer<DexClasspathClass> synthesizedCallback) {
- generateWrappers(
- ClassKind.CLASSPATH,
- synthesizedWrappers.keySet(),
- (type, wrapper) -> {
- DexClasspathClass classpathWrapper = wrapper.asClasspathClass();
- synthesizedWrappers.put(type, classpathWrapper);
- synthesizedCallback.accept(classpathWrapper);
- });
- }
-
- private void generateWrappers(
- ClassKind<?> classKind,
- Set<DexType> synthesized,
- BiConsumer<DexType, DexClass> generatedCallback) {
- while (synthesized.size() != typeWrappers.size() + vivifiedTypeWrappers.size()) {
- for (DexType type : typeWrappers.keySet()) {
- DexType typeWrapperType = typeWrappers.get(type);
- if (!synthesized.contains(typeWrapperType)) {
- DexClass wrapper =
- generateTypeWrapper(classKind, getValidClassToWrap(type), typeWrapperType);
- generatedCallback.accept(typeWrapperType, wrapper);
- }
- }
- for (DexType type : vivifiedTypeWrappers.keySet()) {
- DexType vivifiedTypeWrapperType = vivifiedTypeWrappers.get(type);
- if (!synthesized.contains(vivifiedTypeWrapperType)) {
- DexClass wrapper =
- generateVivifiedTypeWrapper(
- classKind, getValidClassToWrap(type), vivifiedTypeWrapperType);
- generatedCallback.accept(vivifiedTypeWrapperType, wrapper);
- }
+ DexClass validClassToWrap = getValidClassToWrap(type);
+ // In broken set-ups we can end up having a json files containing wrappers of non desugared
+ // classes. Such wrappers are not required since the class won't be rewritten.
+ if (validClassToWrap.isProgramClass()) {
+ ensureWrappers(validClassToWrap, ignored -> {});
}
}
}
- private void registerAndProcessWrappers(
- DexApplication.Builder<?> builder,
- IRConverter irConverter,
- ExecutorService executorService,
- Collection<DexProgramClass> wrappers)
- throws ExecutionException {
- for (DexProgramClass wrapper : wrappers) {
- builder.addSynthesizedClass(wrapper);
- appView.appInfo().addSynthesizedClassForLibraryDesugaring(wrapper);
+ void synthesizeWrappersForClasspath(Consumer<DexClasspathClass> synthesizedCallback) {
+ BooleanBox changed = new BooleanBox(true);
+ while (changed.get()) {
+ changed.set(false);
+ Set<DexType> copy = new HashSet<>(wrappersToGenerate);
+ for (DexType type : copy) {
+ DexClass validClassToWrap = getValidClassToWrap(type);
+ ensureWrappers(
+ validClassToWrap,
+ classpathWrapper -> {
+ changed.set(true);
+ synthesizedCallback.accept(classpathWrapper);
+ });
+ }
}
- irConverter.optimizeSynthesizedClasses(wrappers, executorService);
- }
-
- private DexEncodedMethod generateTypeConversion(DexType type, DexType typeWrapperType) {
- DexType reverse = vivifiedTypeWrappers.get(type);
- assert reverse != null;
- return synthesizeConversionMethod(
- typeWrapperType,
- type,
- type,
- vivifiedTypeFor(type),
- wrappedValueField(reverse, vivifiedTypeFor(type)));
- }
-
- private DexEncodedMethod generateVivifiedTypeConversion(
- DexType type, DexType vivifiedTypeWrapperType) {
- DexType reverse = typeWrappers.get(type);
- assert reverse != null;
- return synthesizeConversionMethod(
- vivifiedTypeWrapperType,
- type,
- vivifiedTypeFor(type),
- type,
- wrappedValueField(reverse, type));
- }
-
- private DexEncodedMethod synthesizeConversionMethod(
- DexType holder,
- DexType type,
- DexType argType,
- DexType returnType,
- DexField reverseField) {
- DexMethod method =
- factory.createMethod(
- holder, factory.createProto(returnType, argType), factory.convertMethodName);
- CfCode cfCode;
- if (invalidWrappers.contains(holder)) {
- cfCode =
- new APIConverterThrowRuntimeExceptionCfCodeProvider(
- appView,
- factory.createString(
- "Unsupported conversion for "
- + type
- + ". See compilation time warnings for more details."),
- holder)
- .generateCfCode();
- } else {
- cfCode =
- new APIConverterWrapperConversionCfCodeProvider(
- appView,
- argType,
- reverseField,
- factory.createField(holder, returnType, factory.wrapperFieldName))
- .generateCfCode();
- }
- return newSynthesizedMethod(
- method,
- Constants.ACC_SYNTHETIC | Constants.ACC_STATIC | Constants.ACC_PUBLIC,
- false,
- cfCode);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index bb345a4..ba7cbc0b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -276,6 +276,8 @@
&& desugaring instanceof InterfaceMethodRewriter)
: "Desugaring of "
+ instruction
+ + " in method "
+ + context.toSourceString()
+ " has multiple matches: "
+ appliedDesugaring.getClass().getName()
+ " and "
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index 3f7a705..9413849 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -1,4 +1,4 @@
-// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// Copyright (c) 2021, 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.
@@ -14,6 +14,7 @@
import com.android.tools.r8.cf.code.CfArrayStore;
import com.android.tools.r8.cf.code.CfCheckCast;
import com.android.tools.r8.cf.code.CfCmp;
+import com.android.tools.r8.cf.code.CfConstNull;
import com.android.tools.r8.cf.code.CfConstNumber;
import com.android.tools.r8.cf.code.CfConstString;
import com.android.tools.r8.cf.code.CfFrame;
@@ -6803,6 +6804,89 @@
ImmutableList.of());
}
+ public static CfCode ObjectsMethods_requireNonNullSupplier(
+ InternalOptions options, DexMethod method) {
+ CfLabel label0 = new CfLabel();
+ CfLabel label1 = new CfLabel();
+ CfLabel label2 = new CfLabel();
+ CfLabel label3 = new CfLabel();
+ CfLabel label4 = new CfLabel();
+ CfLabel label5 = new CfLabel();
+ CfLabel label6 = new CfLabel();
+ return new CfCode(
+ method.holder,
+ 3,
+ 3,
+ ImmutableList.of(
+ label0,
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfIf(If.Type.NE, ValueType.OBJECT, label5),
+ label1,
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfIf(If.Type.EQ, ValueType.OBJECT, label2),
+ new CfLoad(ValueType.OBJECT, 1),
+ new CfInvoke(
+ 185,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/util/function/Supplier;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
+ options.itemFactory.createString("get")),
+ true),
+ new CfCheckCast(options.itemFactory.stringType),
+ new CfGoto(label3),
+ label2,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/Supplier;"))
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfConstNull(),
+ label3,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/Supplier;"))
+ }),
+ new ArrayDeque<>(
+ Arrays.asList(FrameType.initialized(options.itemFactory.stringType)))),
+ new CfStore(ValueType.OBJECT, 2),
+ label4,
+ new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+ new CfStackInstruction(CfStackInstruction.Opcode.Dup),
+ new CfLoad(ValueType.OBJECT, 2),
+ new CfInvoke(
+ 183,
+ options.itemFactory.createMethod(
+ options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+ options.itemFactory.createProto(
+ options.itemFactory.voidType, options.itemFactory.stringType),
+ options.itemFactory.createString("<init>")),
+ false),
+ new CfThrow(),
+ label5,
+ new CfFrame(
+ new Int2ReferenceAVLTreeMap<>(
+ new int[] {0, 1},
+ new FrameType[] {
+ FrameType.initialized(options.itemFactory.objectType),
+ FrameType.initialized(
+ options.itemFactory.createType("Ljava/util/function/Supplier;"))
+ }),
+ new ArrayDeque<>(Arrays.asList())),
+ new CfLoad(ValueType.OBJECT, 0),
+ new CfReturn(ValueType.OBJECT),
+ label6),
+ ImmutableList.of(),
+ ImmutableList.of());
+ }
+
public static CfCode ObjectsMethods_toString(InternalOptions options, DexMethod method) {
CfLabel label0 = new CfLabel();
CfLabel label1 = new CfLabel();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
index 4c784f0..3381ece 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ClassProcessor.java
@@ -4,9 +4,15 @@
package com.android.tools.r8.ir.desugar.itf;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfNew;
+import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
+import com.android.tools.r8.cf.code.CfThrow;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
@@ -24,10 +30,9 @@
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ResolutionResult;
-import com.android.tools.r8.ir.synthetic.ExceptionThrowingSourceCode;
-import com.android.tools.r8.ir.synthetic.SynthesizedCode;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.utils.BooleanBox;
+import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.WorkList;
@@ -756,21 +761,43 @@
if (!clazz.isProgramClass()) {
return;
}
- DexMethod newMethod = dexItemFactory.createMethod(clazz.type, method.proto, method.name);
+ MethodAccessFlags accessFlags = MethodAccessFlags.builder().setPublic().build();
+ DexMethod newMethod = method.withHolder(clazz.getType(), dexItemFactory);
DexEncodedMethod newEncodedMethod =
new DexEncodedMethod(
newMethod,
- MethodAccessFlags.fromCfAccessFlags(Opcodes.ACC_PUBLIC, false),
+ accessFlags,
MethodTypeSignature.noSignature(),
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
- new SynthesizedCode(
- (ignored, callerPosition) ->
- new ExceptionThrowingSourceCode(clazz.type, method, callerPosition, errorType)),
+ createExceptionThrowingCfCode(newMethod, accessFlags, errorType, dexItemFactory),
true);
addSyntheticMethod(clazz.asProgramClass(), newEncodedMethod);
}
+ private static CfCode createExceptionThrowingCfCode(
+ DexMethod method,
+ MethodAccessFlags accessFlags,
+ DexType exceptionType,
+ DexItemFactory dexItemFactory) {
+ DexMethod instanceInitializer =
+ dexItemFactory.createMethod(
+ exceptionType,
+ dexItemFactory.createProto(dexItemFactory.voidType),
+ dexItemFactory.constructorMethodName);
+ int maxStack = 2;
+ int maxLocals = method.getParameters().size() + BooleanUtils.intValue(!accessFlags.isStatic());
+ return new CfCode(
+ method.getHolderType(),
+ maxStack,
+ maxLocals,
+ ImmutableList.of(
+ new CfNew(exceptionType),
+ new CfStackInstruction(Opcode.Dup),
+ new CfInvoke(Opcodes.INVOKESPECIAL, instanceInitializer, false),
+ new CfThrow()));
+ }
+
// Note: The parameter 'target' may be a public method on a class in case of desugared
// library retargeting (See below target.isInterface check).
private void addForwardingMethod(DexClassAndMethod target, DexClass clazz) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index ae334dc..97af733 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -9,8 +9,6 @@
import static com.android.tools.r8.ir.code.Invoke.Type.STATIC;
import static com.android.tools.r8.ir.code.Invoke.Type.SUPER;
import static com.android.tools.r8.ir.code.Invoke.Type.VIRTUAL;
-import static com.android.tools.r8.ir.desugar.DesugaredLibraryWrapperSynthesizer.TYPE_WRAPPER_SUFFIX;
-import static com.android.tools.r8.ir.desugar.DesugaredLibraryWrapperSynthesizer.VIVIFIED_TYPE_WRAPPER_SUFFIX;
import com.android.tools.r8.DesugarGraphConsumer;
import com.android.tools.r8.cf.CfVersion;
@@ -1401,18 +1399,12 @@
private Predicate<DexType> getShouldIgnoreFromReportsPredicate(AppView<?> appView) {
DexItemFactory dexItemFactory = appView.dexItemFactory();
InternalOptions options = appView.options();
- DexString typeWrapperClassNameDescriptorSuffix =
- dexItemFactory.createString(TYPE_WRAPPER_SUFFIX + ';');
- DexString vivifiedTypeWrapperClassNameDescriptorSuffix =
- dexItemFactory.createString(VIVIFIED_TYPE_WRAPPER_SUFFIX + ';');
DexString companionClassNameDescriptorSuffix =
dexItemFactory.createString(COMPANION_CLASS_NAME_SUFFIX + ";");
return type -> {
DexString descriptor = type.getDescriptor();
return appView.rewritePrefix.hasRewrittenType(type, appView)
- || descriptor.endsWith(typeWrapperClassNameDescriptorSuffix)
- || descriptor.endsWith(vivifiedTypeWrapperClassNameDescriptorSuffix)
|| descriptor.endsWith(companionClassNameDescriptorSuffix)
|| emulatedInterfaces.containsValue(type)
|| options.desugaredLibraryConfiguration.getCustomConversions().containsValue(type)
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/AccessBridgeFactory.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/AccessBridgeFactory.java
new file mode 100644
index 0000000..9266ad9
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/AccessBridgeFactory.java
@@ -0,0 +1,93 @@
+// Copyright (c) 2021, 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.ir.desugar.nest;
+
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ProgramField;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.synthetic.FieldAccessorBuilder;
+import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
+
+public class AccessBridgeFactory {
+
+ static ProgramMethod createFieldAccessorBridge(
+ DexMethod bridgeMethodReference, ProgramField field, boolean isGet) {
+ assert bridgeMethodReference.getHolderType() == field.getHolderType();
+ assert field.getAccessFlags().isPrivate();
+ return new ProgramMethod(
+ field.getHolder(),
+ DexEncodedMethod.builder()
+ .setAccessFlags(
+ MethodAccessFlags.builder()
+ .setBridge()
+ .setPublic(field.getHolder().isInterface())
+ .setStatic()
+ .setSynthetic()
+ .build())
+ .setCode(
+ FieldAccessorBuilder.builder()
+ .applyIf(
+ isGet, FieldAccessorBuilder::setGetter, FieldAccessorBuilder::setSetter)
+ .setField(field)
+ .setSourceMethod(bridgeMethodReference)
+ .build())
+ .setMethod(bridgeMethodReference)
+ .setD8R8Synthesized()
+ .build());
+ }
+
+ static ProgramMethod createInitializerAccessorBridge(
+ DexMethod bridgeMethodReference, ProgramMethod method, DexItemFactory dexItemFactory) {
+ assert bridgeMethodReference.getHolderType() == method.getHolderType();
+ assert method.getAccessFlags().isConstructor();
+ assert method.getAccessFlags().isPrivate();
+ assert !method.getHolder().isInterface();
+ return new ProgramMethod(
+ method.getHolder(),
+ DexEncodedMethod.builder()
+ // Not setting the 'bridge' flag as this fails verification.
+ .setAccessFlags(MethodAccessFlags.builder().setConstructor().setSynthetic().build())
+ .setCode(
+ ForwardMethodBuilder.builder(dexItemFactory)
+ .setNonStaticSourceWithExtraUnusedParameter(bridgeMethodReference)
+ .setConstructorTarget(method.getReference())
+ .build())
+ .setMethod(bridgeMethodReference)
+ .setD8R8Synthesized()
+ .build());
+ }
+
+ static ProgramMethod createMethodAccessorBridge(
+ DexMethod bridgeMethodReference, ProgramMethod method, DexItemFactory dexItemFactory) {
+ assert bridgeMethodReference.getHolderType() == method.getHolderType();
+ assert !method.getAccessFlags().isConstructor();
+ assert method.getAccessFlags().isPrivate();
+ boolean isInterface = method.getHolder().isInterface();
+ return new ProgramMethod(
+ method.getHolder(),
+ DexEncodedMethod.builder()
+ .setAccessFlags(
+ MethodAccessFlags.builder()
+ .setBridge()
+ .setPublic(isInterface)
+ .setStatic()
+ .setSynthetic()
+ .build())
+ .setCode(
+ ForwardMethodBuilder.builder(dexItemFactory)
+ .setStaticSource(bridgeMethodReference)
+ .applyIf(
+ method.getAccessFlags().isStatic(),
+ builder -> builder.setStaticTarget(method.getReference(), isInterface),
+ builder -> builder.setDirectTarget(method.getReference(), isInterface))
+ .build())
+ .setMethod(bridgeMethodReference)
+ .setD8R8Synthesized()
+ .build());
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
index a7f094e..b052672 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
@@ -235,7 +235,7 @@
synchronized (field.getHolder().getMethodCollection()) {
ProgramMethod bridge = field.getHolder().lookupProgramMethod(bridgeReference);
if (bridge == null) {
- bridge = DexEncodedMethod.createFieldAccessorBridge(field, isGet, bridgeReference);
+ bridge = AccessBridgeFactory.createFieldAccessorBridge(bridgeReference, field, isGet);
bridge.getHolder().addDirectMethod(bridge.getDefinition());
if (eventConsumer != null) {
if (isGet) {
@@ -300,10 +300,10 @@
DexEncodedMethod definition = method.getDefinition();
bridge =
definition.isInstanceInitializer()
- ? definition.toInitializerForwardingBridge(
- method.getHolder(), bridgeReference, dexItemFactory)
- : definition.toStaticForwardingBridge(
- method.getHolder(), bridgeReference, dexItemFactory);
+ ? AccessBridgeFactory.createInitializerAccessorBridge(
+ bridgeReference, method, dexItemFactory)
+ : AccessBridgeFactory.createMethodAccessorBridge(
+ bridgeReference, method, dexItemFactory);
bridge.getHolder().addDirectMethod(bridge.getDefinition());
if (eventConsumer != null) {
eventConsumer.acceptNestMethodBridge(method, bridge);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java b/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
index 50443c6..b3dd6b6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/IdempotentFunctionCallCanonicalizer.java
@@ -160,7 +160,7 @@
}
MethodOptimizationInfo optimizationInfo = target.getDefinition().getOptimizationInfo();
- if (optimizationInfo.mayHaveSideEffects()
+ if (optimizationInfo.mayHaveSideEffects(invoke, appViewWithLiveness.options())
|| !optimizationInfo.returnValueOnlyDependsOnArguments()) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index edd774e..e9b1e25 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -127,6 +127,7 @@
// Map the enum candidates with their dependencies, i.e., the methods to reprocess for the given
// enum if the optimization eventually decides to unbox it.
private final EnumUnboxingCandidateInfoCollection enumUnboxingCandidatesInfo;
+ private final Set<DexProgramClass> candidatesToRemoveInWave = Sets.newConcurrentHashSet();
private final Map<DexType, EnumStaticFieldValues> staticFieldValuesMap =
new ConcurrentHashMap<>();
private final ProgramMethodSet methodsDependingOnLibraryModelisation =
@@ -165,6 +166,13 @@
return ordinal + 1;
}
+ public void updateEnumUnboxingCandidatesInfo() {
+ for (DexProgramClass candidate : candidatesToRemoveInWave) {
+ enumUnboxingCandidatesInfo.removeCandidate(candidate);
+ }
+ candidatesToRemoveInWave.clear();
+ }
+
/**
* Returns true if {@param enumClass} was marked as being unboxable.
*
@@ -175,7 +183,7 @@
assert enumClass.isEnum();
if (!reportFailure(enumClass, reason)) {
// The failure was not reported, meaning debug logging is disabled.
- enumUnboxingCandidatesInfo.removeCandidate(enumClass);
+ candidatesToRemoveInWave.add(enumClass);
return true;
}
return false;
@@ -461,7 +469,9 @@
ExecutorService executorService,
OptimizationFeedbackDelayed feedback)
throws ExecutionException {
+ assert candidatesToRemoveInWave.isEmpty();
EnumDataMap enumDataMap = finishAnalysis();
+ assert candidatesToRemoveInWave.isEmpty();
// At this point the enum unboxing candidates are no longer candidates, they will all be
// unboxed. We extract the now immutable enums to unbox information and clear the candidate
// info.
@@ -540,6 +550,7 @@
public EnumDataMap finishAnalysis() {
analyzeInitializers();
+ updateEnumUnboxingCandidatesInfo();
EnumDataMap enumDataMap = analyzeEnumInstances();
if (debugLogEnabled) {
// Remove all enums that have been reported as being unboxable.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
index 0aed133..a98bc38 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfo.java
@@ -12,11 +12,13 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.DefaultInstanceInitializerInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableSet;
import java.util.BitSet;
import java.util.Set;
@@ -134,6 +136,11 @@
}
@Override
+ public SimpleInliningConstraint getNopInliningConstraint(InternalOptions options) {
+ return NeverSimpleInliningConstraint.getInstance();
+ }
+
+ @Override
public SimpleInliningConstraint getSimpleInliningConstraint() {
return NeverSimpleInliningConstraint.getInstance();
}
@@ -169,6 +176,11 @@
}
@Override
+ public boolean mayHaveSideEffects(InvokeMethod invoke, InternalOptions options) {
+ return UNKNOWN_MAY_HAVE_SIDE_EFFECTS;
+ }
+
+ @Override
public boolean returnValueOnlyDependsOnArguments() {
return UNKNOWN_RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
index 748d82d..a25eabb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfo.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
@@ -78,6 +79,8 @@
public abstract AbstractValue getAbstractReturnValue();
+ public abstract SimpleInliningConstraint getNopInliningConstraint(InternalOptions options);
+
public abstract SimpleInliningConstraint getSimpleInliningConstraint();
public abstract boolean forceInline();
@@ -90,6 +93,9 @@
public abstract boolean mayHaveSideEffects();
+ /** Context sensitive version of {@link #mayHaveSideEffects()}. */
+ public abstract boolean mayHaveSideEffects(InvokeMethod invoke, InternalOptions options);
+
public abstract boolean returnValueOnlyDependsOnArguments();
public abstract boolean returnValueHasBeenPropagated();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
index 1b47801..5b99126 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
@@ -24,6 +25,7 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.InternalOptions;
import java.util.BitSet;
import java.util.Optional;
import java.util.Set;
@@ -322,6 +324,15 @@
}
@Override
+ public SimpleInliningConstraint getNopInliningConstraint(InternalOptions options) {
+ // We currently require that having a simple inlining constraint implies that the method becomes
+ // empty after inlining. Therefore, an invoke is a nop if the simple inlining constraint is
+ // satisfied (if the invoke does not trigger other side effects, such as class initialization).
+ assert options.simpleInliningConstraintThreshold == 0;
+ return getSimpleInliningConstraint();
+ }
+
+ @Override
public SimpleInliningConstraint getSimpleInliningConstraint() {
return simpleInliningConstraint;
}
@@ -357,6 +368,17 @@
}
@Override
+ public boolean mayHaveSideEffects(InvokeMethod invoke, InternalOptions options) {
+ if (!mayHaveSideEffects()) {
+ return false;
+ }
+ if (getNopInliningConstraint(options).isSatisfied(invoke)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
public boolean returnValueOnlyDependsOnArguments() {
return isFlagSet(RETURN_VALUE_ONLY_DEPENDS_ON_ARGUMENTS_FLAG);
}
@@ -529,8 +551,12 @@
return new MutableMethodOptimizationInfo(this);
}
- public void adjustOptimizationInfoAfterRemovingThisParameter() {
+ public void adjustOptimizationInfoAfterRemovingThisParameter(
+ AppView<AppInfoWithLiveness> appView) {
classInlinerConstraint = classInlinerConstraint.fixupAfterRemovingThisParameter();
+ simpleInliningConstraint =
+ simpleInliningConstraint.fixupAfterRemovingThisParameter(
+ appView.simpleInliningConstraintFactory());
// cannotBeKept: doesn't depend on `this`
// classInitializerMayBePostponed: `this` could trigger <clinit> of the previous holder.
clearFlag(CLASS_INITIALIZER_MAY_BE_POSTPONED_FLAG);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index 91b334c..3e59aa8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -759,7 +759,7 @@
if (method.isStatic()) {
newDirectMethods.add(method);
} else if (!factory().isConstructor(method.getReference())) {
- DexEncodedMethod staticizedMethod = method.toStaticMethodWithoutThis();
+ DexEncodedMethod staticizedMethod = method.toStaticMethodWithoutThis(appView);
newDirectMethods.add(staticizedMethod);
staticizedMethods.createAndAdd(candidateClass, staticizedMethod);
methodMapping.put(method.getReference(), staticizedMethod.getReference());
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
index 6986b3d..254511e 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/DesugaredLibraryAPIConversionCfCodeProvider.java
@@ -98,7 +98,7 @@
instructions.add(
new CfInvoke(
Opcodes.INVOKESTATIC,
- converter.createConversionMethod(param, param, vivifiedTypeFor(param)),
+ converter.ensureConversionMethod(param, param, vivifiedTypeFor(param)),
false));
newParameters[index - 1] = vivifiedTypeFor(param);
}
@@ -129,7 +129,7 @@
instructions.add(
new CfInvoke(
Opcodes.INVOKESTATIC,
- converter.createConversionMethod(
+ converter.ensureConversionMethod(
returnType, vivifiedTypeFor(returnType), returnType),
false));
}
@@ -185,7 +185,7 @@
instructions.add(
new CfInvoke(
Opcodes.INVOKESTATIC,
- converter.createConversionMethod(param, vivifiedTypeFor(param), param),
+ converter.ensureConversionMethod(param, vivifiedTypeFor(param), param),
false));
}
if (param == factory.longType || param == factory.doubleType) {
@@ -205,7 +205,7 @@
instructions.add(
new CfInvoke(
Opcodes.INVOKESTATIC,
- converter.createConversionMethod(
+ converter.ensureConversionMethod(
returnType, returnType, vivifiedTypeFor(returnType)),
false));
returnType = vivifiedTypeFor(returnType);
@@ -221,14 +221,12 @@
public static class APIConverterWrapperConversionCfCodeProvider extends SyntheticCfCodeProvider {
- DexType argType;
DexField reverseWrapperField;
DexField wrapperField;
public APIConverterWrapperConversionCfCodeProvider(
- AppView<?> appView, DexType argType, DexField reverseWrapperField, DexField wrapperField) {
+ AppView<?> appView, DexField reverseWrapperField, DexField wrapperField) {
super(appView, wrapperField.holder);
- this.argType = argType;
this.reverseWrapperField = reverseWrapperField;
this.wrapperField = wrapperField;
}
@@ -238,6 +236,7 @@
DexItemFactory factory = appView.dexItemFactory();
List<CfInstruction> instructions = new ArrayList<>();
+ DexType argType = wrapperField.type;
ImmutableInt2ReferenceSortedMap<FrameType> locals =
ImmutableInt2ReferenceSortedMap.<FrameType>builder()
.put(0, FrameType.initialized(argType))
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/FieldAccessorBuilder.java b/src/main/java/com/android/tools/r8/ir/synthetic/FieldAccessorBuilder.java
index 1f3c6d0..d6794c6 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/FieldAccessorBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/FieldAccessorBuilder.java
@@ -40,6 +40,13 @@
return this;
}
+ public FieldAccessorBuilder applyIf(
+ boolean condition,
+ Consumer<FieldAccessorBuilder> thenConsumer,
+ Consumer<FieldAccessorBuilder> elseConsumer) {
+ return apply(condition ? thenConsumer : elseConsumer);
+ }
+
public FieldAccessorBuilder setField(DexClassAndField field) {
return field.getAccessFlags().isStatic()
? setStaticField(field.getReference())
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
index c89cb3e..eb56742 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
@@ -17,7 +17,7 @@
this(sourceCodeProvider, SynthesizedCode::registerReachableDefinitionsDefault);
}
- public SynthesizedCode(SourceCodeProvider sourceCodeProvider, Consumer<UseRegistry> callback) {
+ private SynthesizedCode(SourceCodeProvider sourceCodeProvider, Consumer<UseRegistry> callback) {
this.sourceCodeProvider = sourceCodeProvider;
this.registryCallback = callback;
}
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 75bb5f5..abb6523 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -3155,7 +3155,7 @@
return empty;
}
- void addClasspathClass(DexClasspathClass clazz) {
+ void addLiveClasspathClass(DexClasspathClass clazz) {
DexClasspathClass old = syntheticClasspathClasses.put(clazz.type, clazz);
assert old == null;
}
@@ -3172,11 +3172,6 @@
liveMethodsWithKeepActions.add(new Pair<>(method, keepAction));
}
- void amendApplication(Builder appBuilder) {
- assert !isEmpty();
- appBuilder.addClasspathClasses(syntheticClasspathClasses.values());
- }
-
void enqueueWorkItems(Enqueuer enqueuer) {
assert !isEmpty();
assert enqueuer.mode.isInitialTreeShaking();
@@ -3214,14 +3209,8 @@
return;
}
- // Now all additions are computed, the application is atomically extended with those additions.
- appInfo =
- appInfo.rebuildWithClassHierarchy(
- app -> {
- Builder appBuilder = app.asDirect().builder();
- additions.amendApplication(appBuilder);
- return appBuilder.build();
- });
+ // Commit the pending synthetics and recompute subtypes.
+ appInfo = appInfo.rebuildWithClassHierarchy(app -> app);
appView.setAppInfo(appInfo);
subtypingInfo = new SubtypingInfo(appView);
@@ -3528,7 +3517,7 @@
callbacks.forEach(additions::addLiveMethod);
// Generate wrappers on classpath so types are defined.
- desugaredLibraryWrapperAnalysis.generateWrappers(additions::addClasspathClass);
+ desugaredLibraryWrapperAnalysis.generateWrappers(additions::addLiveClasspathClass);
}
diff --git a/src/main/java/com/android/tools/r8/shaking/GraphReporter.java b/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
index 6146c2c..fabdd04 100644
--- a/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
+++ b/src/main/java/com/android/tools/r8/shaking/GraphReporter.java
@@ -333,13 +333,17 @@
}
}
+ private boolean hasKeptGraphConsumer() {
+ return keptGraphConsumer != null;
+ }
+
private boolean skipReporting(KeepReason reason) {
assert reason != null;
if (reason == KeepReasonWitness.INSTANCE) {
return true;
}
assert getSourceNode(reason) != null;
- return keptGraphConsumer == null;
+ return !hasKeptGraphConsumer();
}
public KeepReasonWitness registerInterface(DexProgramClass iface, KeepReason reason) {
@@ -359,11 +363,15 @@
public KeepReasonWitness registerAnnotation(
DexAnnotation annotation, ProgramDefinition annotatedItem) {
- KeepReason reason = KeepReason.annotatedOn(annotatedItem.getDefinition());
- if (skipReporting(reason)) {
- return KeepReasonWitness.INSTANCE;
+ if (hasKeptGraphConsumer()) {
+ registerEdge(
+ getAnnotationGraphNode(annotation, annotatedItem),
+ KeepReason.annotatedOn(annotatedItem.getDefinition()));
+ registerEdge(
+ getClassGraphNode(annotation.getAnnotationType()),
+ KeepReason.referencedInAnnotation(annotation, annotatedItem));
}
- return registerEdge(getAnnotationGraphNode(annotation, annotatedItem), reason);
+ return KeepReasonWitness.INSTANCE;
}
public KeepReasonWitness registerMethod(DexEncodedMethod method, KeepReason reason) {
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index 72a0a0b..e4890a0 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -149,6 +149,10 @@
this(appView, subtypingInfo, null);
}
+ boolean isMainDexRootSetBuilder() {
+ return false;
+ }
+
void handleMatchedAnnotation(AnnotationMatchResult annotation) {
// Intentionally empty.
}
@@ -517,7 +521,8 @@
// fullmode.
if (clazz.isProgramClass()
&& rule.isProguardKeepRule()
- && !rule.asProguardKeepRule().getModifiers().allowsShrinking) {
+ && !rule.asProguardKeepRule().getModifiers().allowsShrinking
+ && !isMainDexRootSetBuilder()) {
new SynthesizeMissingInterfaceMethodsForMemberRules(
clazz.asProgramClass(), memberKeepRules, rule, preconditionSupplier, ifRule)
.run();
@@ -2241,6 +2246,11 @@
}
@Override
+ boolean isMainDexRootSetBuilder() {
+ return true;
+ }
+
+ @Override
public MainDexRootSet build(ExecutorService executorService) throws ExecutionException {
// Call the super builder to have if-tests calculated automatically.
RootSet rootSet = super.build(executorService);
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 e0837dd..d43f32a 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1206,7 +1206,7 @@
}
holder =
holder.superType != null
- ? appInfo.definitionFor(holder.superType).asProgramClass()
+ ? asProgramClassOrNull(appInfo.definitionFor(holder.superType))
: null;
}
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
index cd80b53..fd7437e 100644
--- a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
+++ b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.PrunedItems;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.IterableUtils;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -215,6 +216,19 @@
return containsLegacyType(type) || containsNonLegacyType(type);
}
+ boolean containsTypeOfKind(DexType type, SyntheticKind kind) {
+ List<SyntheticProgramClassReference> synthetics = nonLegacyClasses.get(type);
+ if (synthetics == null) {
+ return false;
+ }
+ for (SyntheticProgramClassReference synthetic : synthetics) {
+ if (synthetic.getKind() == kind) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public boolean containsLegacyType(DexType type) {
return legacyTypes.containsKey(type);
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
index 737ffa6..6a6aef4 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
@@ -98,6 +98,11 @@
return self();
}
+ public B setSuperType(DexType superType) {
+ this.superType = superType;
+ return self();
+ }
+
public B setOriginKind(Kind originKind) {
this.originKind = originKind;
return self();
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index 3bd99a2..f7e235f 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -76,6 +76,11 @@
return legacyClasses.containsKey(type) || nonLegacyDefinitions.containsKey(type);
}
+ boolean containsTypeOfKind(DexType type, SyntheticKind kind) {
+ SyntheticDefinition<?, ?, ?> definition = nonLegacyDefinitions.get(type);
+ return definition != null && definition.getKind() == kind;
+ }
+
boolean verifyNotRewritten(NonIdentityGraphLens lens) {
assert legacyClasses.keySet().equals(lens.rewriteTypes(legacyClasses.keySet()));
assert nonLegacyDefinitions.keySet().equals(lens.rewriteTypes(nonLegacyDefinitions.keySet()));
@@ -291,6 +296,10 @@
return isSyntheticClass(clazz.type);
}
+ public boolean isSyntheticOfKind(DexType type, SyntheticKind kind) {
+ return pending.containsTypeOfKind(type, kind) || committed.containsTypeOfKind(type, kind);
+ }
+
boolean isSyntheticInput(DexProgramClass clazz) {
return committed.containsSyntheticInput(clazz.getType());
}
@@ -609,8 +618,8 @@
new SyntheticClasspathClassBuilder(type, kind, outerContext, appView.dexItemFactory());
classConsumer.accept(classBuilder);
DexClasspathClass clazz = classBuilder.build();
- onCreationConsumer.accept(clazz);
addPendingDefinition(new SyntheticClasspathClassDefinition(kind, outerContext, clazz));
+ onCreationConsumer.accept(clazz);
return clazz;
}
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index 33530e6..c142281 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -28,6 +28,8 @@
EMULATED_INTERFACE_CLASS("$-EL", 3, false, true),
RETARGET_CLASS("RetargetClass", 20, false, true),
RETARGET_INTERFACE("RetargetInterface", 21, false, true),
+ WRAPPER("$Wrapper", 22, false, true),
+ VIVIFIED_WRAPPER("$VivifiedWrapper", 23, false, true),
LAMBDA("Lambda", 4, false),
INIT_TYPE_ARGUMENT("-IA", 5, false, true),
HORIZONTAL_INIT_TYPE_ARGUMENT_1(SYNTHETIC_CLASS_SEPARATOR + "IA$1", 6, false, true),
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 b75ac5a..0a1fcc7 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -263,7 +263,7 @@
public boolean enableInliningOfInvokesWithNullableReceivers = true;
public boolean disableInliningOfLibraryMethodOverrides = true;
public boolean enableSimpleInliningConstraints = true;
- public int simpleInliningConstraintThreshold = 0;
+ public final int simpleInliningConstraintThreshold = 0;
public boolean enableClassInlining = true;
public boolean enableClassStaticizer = true;
public boolean enableInitializedClassesAnalysis = true;
diff --git a/src/test/java/com/android/tools/r8/D8TestBuilder.java b/src/test/java/com/android/tools/r8/D8TestBuilder.java
index 1cae06b..2ada4dd 100644
--- a/src/test/java/com/android/tools/r8/D8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/D8TestBuilder.java
@@ -65,9 +65,15 @@
D8TestCompileResult internalCompile(
Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
throws CompilationFailedException {
+ libraryDesugaringTestConfiguration.configure(builder);
ToolHelper.runD8(builder, optionsConsumer);
return new D8TestCompileResult(
- getState(), app.get(), minApiLevel, getOutputMode(), getMapContent());
+ getState(),
+ app.get(),
+ minApiLevel,
+ getOutputMode(),
+ libraryDesugaringTestConfiguration,
+ getMapContent());
}
private String getMapContent() {
@@ -87,7 +93,6 @@
if (minApiLevel.getLevel() < AndroidApiLevel.O.getLevel()) {
super.enableCoreLibraryDesugaring(
minApiLevel, keepRuleConsumer, desugaredLibraryConfiguration);
- builder.setDesugaredLibraryKeepRuleConsumer(keepRuleConsumer);
}
return self();
}
diff --git a/src/test/java/com/android/tools/r8/D8TestCompileResult.java b/src/test/java/com/android/tools/r8/D8TestCompileResult.java
index 7e8e572..6d7634c 100644
--- a/src/test/java/com/android/tools/r8/D8TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/D8TestCompileResult.java
@@ -11,8 +11,13 @@
private final String proguardMap;
D8TestCompileResult(
- TestState state, AndroidApp app, int minApiLevel, OutputMode outputMode, String proguardMap) {
- super(state, app, minApiLevel, outputMode);
+ TestState state,
+ AndroidApp app,
+ int minApiLevel,
+ OutputMode outputMode,
+ LibraryDesugaringTestConfiguration libraryDesugaringTestConfiguration,
+ String proguardMap) {
+ super(state, app, minApiLevel, outputMode, libraryDesugaringTestConfiguration);
this.proguardMap = proguardMap;
}
diff --git a/src/test/java/com/android/tools/r8/DXTestBuilder.java b/src/test/java/com/android/tools/r8/DXTestBuilder.java
index 30917a7..2459f1d 100644
--- a/src/test/java/com/android/tools/r8/DXTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/DXTestBuilder.java
@@ -46,6 +46,7 @@
DXTestCompileResult internalCompile(
Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
throws CompilationFailedException {
+ assert !libraryDesugaringTestConfiguration.isEnabled();
try {
Path dxOutputFolder = getState().getNewTempFolder();
Path outJar = dxOutputFolder.resolve("output.jar");
diff --git a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
index ca3e2f0..73c4623 100644
--- a/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ExternalR8TestBuilder.java
@@ -112,6 +112,7 @@
ExternalR8TestCompileResult internalCompile(
Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
throws CompilationFailedException {
+ assert !libraryDesugaringTestConfiguration.isEnabled();
try {
Path outputFolder = getState().getNewTempFolder();
Path outputJar = outputFolder.resolve("output.jar");
diff --git a/src/test/java/com/android/tools/r8/L8TestBuilder.java b/src/test/java/com/android/tools/r8/L8TestBuilder.java
new file mode 100644
index 0000000..567d471
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/L8TestBuilder.java
@@ -0,0 +1,201 @@
+// Copyright (c) 2021, 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;
+
+import static junit.framework.Assert.assertNull;
+import static junit.framework.TestCase.assertTrue;
+
+import com.android.tools.r8.TestBase.Backend;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.AndroidAppConsumers;
+import com.android.tools.r8.utils.ConsumerUtils;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+
+public class L8TestBuilder {
+
+ private final AndroidApiLevel apiLevel;
+ private final Backend backend;
+ private final TestState state;
+
+ private CompilationMode mode = CompilationMode.RELEASE;
+ private String generatedKeepRules = null;
+ private List<String> keepRules = new ArrayList<>();
+ private List<Path> additionalProgramFiles = new ArrayList<>();
+ private List<byte[]> additionalProgramClassFileData = new ArrayList<>();
+ private Consumer<InternalOptions> optionsModifier = ConsumerUtils.emptyConsumer();
+ private Path desugarJDKLibs = ToolHelper.getDesugarJDKLibs();
+ private Path desugarJDKLibsConfiguration = null;
+ private StringResource desugaredLibraryConfiguration =
+ StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting());
+ private List<Path> libraryFiles = new ArrayList<>();
+
+ private L8TestBuilder(AndroidApiLevel apiLevel, Backend backend, TestState state) {
+ this.apiLevel = apiLevel;
+ this.backend = backend;
+ this.state = state;
+ }
+
+ public static L8TestBuilder create(AndroidApiLevel apiLevel, Backend backend, TestState state) {
+ return new L8TestBuilder(apiLevel, backend, state);
+ }
+
+ public L8TestBuilder addProgramFiles(Collection<Path> programFiles) {
+ this.additionalProgramFiles.addAll(programFiles);
+ return this;
+ }
+
+ public L8TestBuilder addProgramClassFileData(byte[]... classes) {
+ this.additionalProgramClassFileData.addAll(Arrays.asList(classes));
+ return this;
+ }
+
+ public L8TestBuilder addLibraryFiles(Path... libraryFiles) {
+ Collections.addAll(this.libraryFiles, libraryFiles);
+ return this;
+ }
+
+ public L8TestBuilder addGeneratedKeepRules(String generatedKeepRules) {
+ assertNull(this.generatedKeepRules);
+ this.generatedKeepRules = generatedKeepRules;
+ return this;
+ }
+
+ public L8TestBuilder addKeepRuleFile(Path keepRuleFile) throws IOException {
+ this.keepRules.add(FileUtils.readTextFile(keepRuleFile, StandardCharsets.UTF_8));
+ return this;
+ }
+
+ public L8TestBuilder addKeepRuleFiles(Collection<Path> keepRuleFiles) throws IOException {
+ for (Path keepRuleFile : keepRuleFiles) {
+ addKeepRuleFile(keepRuleFile);
+ }
+ return this;
+ }
+
+ public L8TestBuilder addOptionsModifier(Consumer<InternalOptions> optionsModifier) {
+ this.optionsModifier = this.optionsModifier.andThen(optionsModifier);
+ return this;
+ }
+
+ public L8TestBuilder applyIf(boolean condition, ThrowableConsumer<L8TestBuilder> thenConsumer) {
+ return applyIf(condition, thenConsumer, ThrowableConsumer.empty());
+ }
+
+ public L8TestBuilder applyIf(
+ boolean condition,
+ ThrowableConsumer<L8TestBuilder> thenConsumer,
+ ThrowableConsumer<L8TestBuilder> elseConsumer) {
+ if (condition) {
+ thenConsumer.acceptWithRuntimeException(this);
+ } else {
+ elseConsumer.acceptWithRuntimeException(this);
+ }
+ return this;
+ }
+
+ public L8TestBuilder setDebug() {
+ this.mode = CompilationMode.DEBUG;
+ return this;
+ }
+
+ public L8TestBuilder setDesugarJDKLibs(Path desugarJDKLibs) {
+ assert desugarJDKLibs != null : "Use noDefaultDesugarJDKLibs to clear the default.";
+ this.desugarJDKLibs = desugarJDKLibs;
+ return this;
+ }
+
+ public L8TestBuilder noDefaultDesugarJDKLibs() {
+ this.desugarJDKLibs = null;
+ return this;
+ }
+
+ public L8TestBuilder setDesugarJDKLibsConfiguration(Path desugarJDKLibsConfiguration) {
+ this.desugarJDKLibsConfiguration = desugarJDKLibsConfiguration;
+ return this;
+ }
+
+ public L8TestBuilder setDesugaredLibraryConfiguration(Path path) {
+ this.desugaredLibraryConfiguration = StringResource.fromFile(path);
+ return this;
+ }
+
+ public L8TestBuilder setDisableL8AnnotationRemoval(boolean disableL8AnnotationRemoval) {
+ return addOptionsModifier(
+ options -> options.testing.disableL8AnnotationRemoval = disableL8AnnotationRemoval);
+ }
+
+ public L8TestCompileResult compile()
+ throws IOException, CompilationFailedException, ExecutionException {
+ // We wrap exceptions in a RuntimeException to call this from a lambda.
+ AndroidAppConsumers sink = new AndroidAppConsumers();
+ L8Command.Builder l8Builder =
+ L8Command.builder(state.getDiagnosticsHandler())
+ .addProgramFiles(getProgramFiles())
+ .addLibraryFiles(getLibraryFiles())
+ .setMode(mode)
+ .addDesugaredLibraryConfiguration(desugaredLibraryConfiguration)
+ .setMinApiLevel(apiLevel.getLevel())
+ .setProgramConsumer(
+ backend.isCf()
+ ? sink.wrapProgramConsumer(ClassFileConsumer.emptyConsumer())
+ : sink.wrapProgramConsumer(DexIndexedConsumer.emptyConsumer()));
+ addProgramClassFileData(l8Builder);
+ Path mapping = null;
+ if (!keepRules.isEmpty() || generatedKeepRules != null) {
+ mapping = state.getNewTempFile("mapping.txt");
+ l8Builder
+ .addProguardConfiguration(
+ ImmutableList.<String>builder()
+ .addAll(keepRules)
+ .addAll(
+ generatedKeepRules != null
+ ? ImmutableList.of(generatedKeepRules)
+ : Collections.emptyList())
+ .build(),
+ Origin.unknown())
+ .setProguardMapOutputPath(mapping);
+ }
+ ToolHelper.runL8(l8Builder.build(), optionsModifier);
+ return new L8TestCompileResult(sink.build(), apiLevel, generatedKeepRules, mapping, state)
+ .inspect(
+ inspector ->
+ inspector.forAllClasses(
+ clazz -> assertTrue(clazz.getFinalName().startsWith("j$."))));
+ }
+
+ private Collection<Path> getProgramFiles() {
+ ImmutableList.Builder<Path> builder = ImmutableList.builder();
+ if (desugarJDKLibs != null) {
+ builder.add(desugarJDKLibs);
+ }
+ if (desugarJDKLibsConfiguration != null) {
+ builder.add(desugarJDKLibsConfiguration);
+ }
+ return builder.addAll(additionalProgramFiles).build();
+ }
+
+ private L8Command.Builder addProgramClassFileData(L8Command.Builder builder) {
+ additionalProgramClassFileData.forEach(
+ data -> builder.addClassProgramData(data, Origin.unknown()));
+ return builder;
+ }
+
+ private Collection<Path> getLibraryFiles() {
+ return libraryFiles;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/LibraryDesugaringTestConfiguration.java b/src/test/java/com/android/tools/r8/LibraryDesugaringTestConfiguration.java
new file mode 100644
index 0000000..79dc2c9
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/LibraryDesugaringTestConfiguration.java
@@ -0,0 +1,316 @@
+// Copyright (c) 2021, 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;
+
+import static com.android.tools.r8.LibraryDesugaringTestConfiguration.Configuration.DEFAULT;
+import static junit.framework.TestCase.assertNotNull;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.TestBase.Backend;
+import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase.KeepRuleConsumer;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+public class LibraryDesugaringTestConfiguration {
+
+ private static final String RELEASES_DIR = "third_party/openjdk/desugar_jdk_libs_releases/";
+
+ public enum Configuration {
+ DEFAULT(
+ ToolHelper.getDesugarJDKLibs(),
+ ToolHelper.DESUGAR_LIB_CONVERSIONS,
+ ToolHelper.getDesugarLibJsonForTesting()),
+ DEFAULT_JDK11(
+ Paths.get("third_party/openjdk/desugar_jdk_libs_11/desugar_jdk_libs.jar"),
+ ToolHelper.DESUGAR_LIB_CONVERSIONS,
+ Paths.get("src/library_desugar/jdk11/desugar_jdk_libs.json")),
+ RELEASED_1_0_9("1.0.9"),
+ RELEASED_1_0_10("1.0.10"),
+ RELEASED_1_1_0("1.1.0"),
+ RELEASED_1_1_1("1.1.1"),
+ RELEASED_1_1_5("1.1.5");
+
+ private final Path desugarJdkLibs;
+ private final Path customConversions;
+ private final Path configuration;
+
+ Configuration(Path desugarJdkLibs, Path customConversions, Path configuration) {
+ this.desugarJdkLibs = desugarJdkLibs;
+ this.customConversions = customConversions;
+ this.configuration = configuration;
+ }
+
+ Configuration(String version) {
+ this(
+ Paths.get(RELEASES_DIR, version, "desugar_jdk_libs.jar"),
+ Paths.get(RELEASES_DIR, version, "desugar_jdk_libs_configuration.jar"),
+ Paths.get(RELEASES_DIR, version, "desugar.json"));
+ }
+
+ public static List<Configuration> getReleased() {
+ return ImmutableList.of(
+ RELEASED_1_0_9, RELEASED_1_0_10, RELEASED_1_1_0, RELEASED_1_1_1, RELEASED_1_1_5);
+ }
+ }
+
+ private final AndroidApiLevel minApiLevel;
+ private final Path desugarJdkLibs;
+ private final Path customConversions;
+ private final List<StringResource> desugaredLibraryConfigurationResources;
+ private final boolean withKeepRuleConsumer;
+ private final KeepRuleConsumer keepRuleConsumer;
+ private final CompilationMode mode;
+ private final boolean addRunClassPath;
+
+ public static final LibraryDesugaringTestConfiguration DISABLED =
+ new LibraryDesugaringTestConfiguration();
+
+ private LibraryDesugaringTestConfiguration() {
+ this.minApiLevel = null;
+ this.desugarJdkLibs = null;
+ this.customConversions = null;
+ this.keepRuleConsumer = null;
+ this.withKeepRuleConsumer = false;
+ this.desugaredLibraryConfigurationResources = null;
+ this.mode = null;
+ this.addRunClassPath = false;
+ }
+
+ private LibraryDesugaringTestConfiguration(
+ AndroidApiLevel minApiLevel,
+ Path desugarJdkLibs,
+ Path customConversions,
+ List<StringResource> desugaredLibraryConfigurationResources,
+ boolean withKeepRuleConsumer,
+ KeepRuleConsumer keepRuleConsumer,
+ CompilationMode mode,
+ boolean addRunClassPath) {
+ this.minApiLevel = minApiLevel;
+ this.desugarJdkLibs = desugarJdkLibs;
+ this.customConversions = customConversions;
+ this.desugaredLibraryConfigurationResources = desugaredLibraryConfigurationResources;
+ this.withKeepRuleConsumer = withKeepRuleConsumer;
+ this.keepRuleConsumer = keepRuleConsumer;
+ this.mode = mode;
+ this.addRunClassPath = addRunClassPath;
+ }
+
+ public static class Builder {
+
+ AndroidApiLevel minApiLevel;
+ private Path desugarJdkLibs;
+ private Path customConversions;
+ private final List<StringResource> desugaredLibraryConfigurationResources = new ArrayList<>();
+ boolean withKeepRuleConsumer = false;
+ KeepRuleConsumer keepRuleConsumer;
+ private CompilationMode mode = CompilationMode.DEBUG;
+ boolean addRunClassPath = true;
+
+ private Builder() {}
+
+ public Builder setMinApi(AndroidApiLevel minApiLevel) {
+ this.minApiLevel = minApiLevel;
+ return this;
+ }
+
+ public Builder setConfiguration(Configuration configuration) {
+ desugarJdkLibs = configuration.desugarJdkLibs;
+ customConversions = configuration.customConversions;
+ desugaredLibraryConfigurationResources.clear();
+ desugaredLibraryConfigurationResources.add(
+ StringResource.fromFile(configuration.configuration));
+ return this;
+ }
+
+ public Builder withKeepRuleConsumer() {
+ withKeepRuleConsumer = true;
+ return this;
+ }
+
+ public Builder setKeepRuleConsumer(StringConsumer keepRuleConsumer) {
+ withKeepRuleConsumer = false;
+ if (keepRuleConsumer == null) {
+ this.keepRuleConsumer = null;
+ } else {
+ assert keepRuleConsumer instanceof KeepRuleConsumer;
+ this.keepRuleConsumer = (KeepRuleConsumer) keepRuleConsumer;
+ }
+ return this;
+ }
+
+ public Builder addDesugaredLibraryConfiguration(StringResource desugaredLibraryConfiguration) {
+ desugaredLibraryConfigurationResources.add(desugaredLibraryConfiguration);
+ return this;
+ }
+
+ public Builder setMode(CompilationMode mode) {
+ this.mode = mode;
+ return this;
+ }
+
+ public Builder dontAddRunClasspath() {
+ addRunClassPath = false;
+ return this;
+ }
+
+ public LibraryDesugaringTestConfiguration build() {
+ if (desugaredLibraryConfigurationResources.isEmpty()) {
+ desugaredLibraryConfigurationResources.add(
+ StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting()));
+ }
+ if (withKeepRuleConsumer) {
+ this.keepRuleConsumer = createKeepRuleConsumer(minApiLevel);
+ }
+ return new LibraryDesugaringTestConfiguration(
+ minApiLevel,
+ desugarJdkLibs != null ? desugarJdkLibs : DEFAULT.desugarJdkLibs,
+ customConversions != null ? customConversions : DEFAULT.customConversions,
+ desugaredLibraryConfigurationResources,
+ withKeepRuleConsumer,
+ keepRuleConsumer,
+ mode,
+ addRunClassPath);
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public boolean isEnabled() {
+ return this != DISABLED;
+ }
+
+ public boolean isAddRunClassPath() {
+ return addRunClassPath;
+ }
+
+ public void configure(D8Command.Builder builder) {
+ if (!isEnabled()) {
+ return;
+ }
+ if (keepRuleConsumer != null) {
+ builder.setDesugaredLibraryKeepRuleConsumer(keepRuleConsumer);
+ }
+ desugaredLibraryConfigurationResources.forEach(builder::addDesugaredLibraryConfiguration);
+ }
+
+ public void configure(R8Command.Builder builder) {
+ if (!isEnabled()) {
+ return;
+ }
+ if (keepRuleConsumer != null) {
+ builder.setDesugaredLibraryKeepRuleConsumer(keepRuleConsumer);
+ }
+ desugaredLibraryConfigurationResources.forEach(builder::addDesugaredLibraryConfiguration);
+ }
+
+ public Path buildDesugaredLibrary(TestState state) {
+ String generatedKeepRules = null;
+ if (withKeepRuleConsumer) {
+ if (keepRuleConsumer instanceof PresentKeepRuleConsumer) {
+ generatedKeepRules = keepRuleConsumer.get();
+ assertNotNull(generatedKeepRules);
+ } else {
+ assertThat(keepRuleConsumer, instanceOf(AbsentKeepRuleConsumer.class));
+ }
+ }
+ String finalGeneratedKeepRules = generatedKeepRules;
+ try {
+ return L8TestBuilder.create(minApiLevel, Backend.DEX, state)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .setDesugarJDKLibs(desugarJdkLibs)
+ .setDesugarJDKLibsConfiguration(customConversions)
+ .applyIf(
+ mode == CompilationMode.RELEASE,
+ builder -> {
+ if (finalGeneratedKeepRules != null && !finalGeneratedKeepRules.trim().isEmpty()) {
+ builder.addGeneratedKeepRules(finalGeneratedKeepRules);
+ }
+ },
+ L8TestBuilder::setDebug)
+ .compile()
+ .writeToZip();
+ } catch (CompilationFailedException | ExecutionException | IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public KeepRuleConsumer getKeepRuleConsumer() {
+ return keepRuleConsumer;
+ }
+
+ public static KeepRuleConsumer createKeepRuleConsumer(TestParameters parameters) {
+ return createKeepRuleConsumer(parameters.getApiLevel());
+ }
+
+ private static KeepRuleConsumer createKeepRuleConsumer(AndroidApiLevel apiLevel) {
+ if (requiresAnyCoreLibDesugaring(apiLevel)) {
+ return new PresentKeepRuleConsumer();
+ }
+ return new AbsentKeepRuleConsumer();
+ }
+
+ private static boolean requiresAnyCoreLibDesugaring(AndroidApiLevel apiLevel) {
+ return apiLevel.isLessThan(AndroidApiLevel.O);
+ }
+
+ public static class PresentKeepRuleConsumer implements KeepRuleConsumer {
+
+ StringBuilder stringBuilder = new StringBuilder();
+ String result = null;
+
+ @Override
+ public void accept(String string, DiagnosticsHandler handler) {
+ assert stringBuilder != null;
+ assert result == null;
+ stringBuilder.append(string);
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {
+ assert stringBuilder != null;
+ assert result == null;
+ result = stringBuilder.toString();
+ stringBuilder = null;
+ }
+
+ public String get() {
+ // TODO(clement): remove that branch once StringConsumer has finished again.
+ if (stringBuilder != null) {
+ finished(null);
+ }
+
+ assert stringBuilder == null;
+ assert result != null;
+ return result;
+ }
+ }
+
+ public static class AbsentKeepRuleConsumer implements KeepRuleConsumer {
+
+ public String get() {
+ return null;
+ }
+
+ @Override
+ public void accept(String string, DiagnosticsHandler handler) {
+ throw new Unreachable("No desugaring on high API levels");
+ }
+
+ @Override
+ public void finished(DiagnosticsHandler handler) {
+ throw new Unreachable("No desugaring on high API levels");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
index 460246c..830047f 100644
--- a/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/ProguardTestBuilder.java
@@ -66,6 +66,7 @@
ProguardTestCompileResult internalCompile(
Builder builder, Consumer<InternalOptions> optionsConsumer, Supplier<AndroidApp> app)
throws CompilationFailedException {
+ assert !libraryDesugaringTestConfiguration.isEnabled();
try {
Path proguardOutputFolder = getState().getNewTempFolder();
Path outJar = proguardOutputFolder.resolve("output.jar");
diff --git a/src/test/java/com/android/tools/r8/R8TestBuilder.java b/src/test/java/com/android/tools/r8/R8TestBuilder.java
index 0e11c5b..d245c58 100644
--- a/src/test/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/java/com/android/tools/r8/R8TestBuilder.java
@@ -111,6 +111,7 @@
Box box = new Box();
ToolHelper.addSyntheticProguardRulesConsumerForTesting(
builder, rules -> box.syntheticProguardRules = rules);
+ libraryDesugaringTestConfiguration.configure(builder);
ToolHelper.runR8WithoutResult(
builder.build(),
optionsConsumer.andThen(
@@ -119,6 +120,7 @@
new R8TestCompileResult(
getState(),
getOutputMode(),
+ libraryDesugaringTestConfiguration,
app.get(),
box.proguardConfiguration,
box.syntheticProguardRules,
@@ -654,7 +656,6 @@
if (minApiLevel.getLevel() < AndroidApiLevel.O.getLevel()) {
super.enableCoreLibraryDesugaring(
minApiLevel, keepRuleConsumer, desugaredLibraryConfiguration);
- builder.setDesugaredLibraryKeepRuleConsumer(keepRuleConsumer);
}
return self();
}
diff --git a/src/test/java/com/android/tools/r8/R8TestCompileResult.java b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
index a1a5f88..0480694 100644
--- a/src/test/java/com/android/tools/r8/R8TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/R8TestCompileResult.java
@@ -35,6 +35,7 @@
R8TestCompileResult(
TestState state,
OutputMode outputMode,
+ LibraryDesugaringTestConfiguration libraryDesugaringTestConfiguration,
AndroidApp app,
ProguardConfiguration proguardConfiguration,
List<ProguardConfigurationRule> syntheticProguardRules,
@@ -42,7 +43,7 @@
CollectingGraphConsumer graphConsumer,
int minApiLevel,
List<Path> features) {
- super(state, app, minApiLevel, outputMode);
+ super(state, app, minApiLevel, outputMode, libraryDesugaringTestConfiguration);
this.proguardConfiguration = proguardConfiguration;
this.syntheticProguardRules = syntheticProguardRules;
this.proguardMap = proguardMap;
@@ -110,6 +111,12 @@
return self();
}
+ public final <E extends Throwable> R8TestCompileResult inspectGraph(
+ ThrowingConsumer<GraphInspector, E> consumer) throws IOException, E {
+ consumer.accept(graphInspector());
+ return self();
+ }
+
public GraphInspector graphInspector() throws IOException {
assert graphConsumer != null;
return new GraphInspector(graphConsumer, inspector());
diff --git a/src/test/java/com/android/tools/r8/TestCompileResult.java b/src/test/java/com/android/tools/r8/TestCompileResult.java
index 827684d..b80c482 100644
--- a/src/test/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/java/com/android/tools/r8/TestCompileResult.java
@@ -42,6 +42,7 @@
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -58,12 +59,27 @@
final List<String> vmArguments = new ArrayList<>();
private boolean withArt6Plus64BitsLib = false;
private boolean withArtFrameworks = true;
+ private LibraryDesugaringTestConfiguration libraryDesugaringTestConfiguration;
TestCompileResult(TestState state, AndroidApp app, int minApiLevel, OutputMode outputMode) {
super(state);
this.app = app;
this.minApiLevel = minApiLevel;
this.outputMode = outputMode;
+ this.libraryDesugaringTestConfiguration = LibraryDesugaringTestConfiguration.DISABLED;
+ }
+
+ TestCompileResult(
+ TestState state,
+ AndroidApp app,
+ int minApiLevel,
+ OutputMode outputMode,
+ LibraryDesugaringTestConfiguration libraryDesugaringTestConfiguration) {
+ super(state);
+ this.app = app;
+ this.minApiLevel = minApiLevel;
+ this.outputMode = outputMode;
+ this.libraryDesugaringTestConfiguration = libraryDesugaringTestConfiguration;
}
public CR applyIf(boolean condition, ThrowableConsumer<CR> thenConsumer) {
@@ -118,6 +134,12 @@
return self();
}
+ public final CR inspectMainDexClasses(BiConsumer<CodeInspector, Set<String>> consumer)
+ throws IOException {
+ consumer.accept(inspector(), getMainDexClasses());
+ return self();
+ }
+
public abstract String getStdout();
public abstract String getStderr();
@@ -135,6 +157,7 @@
@Deprecated
public RR run(String mainClass) throws ExecutionException, IOException {
+ assert !libraryDesugaringTestConfiguration.isEnabled();
ClassSubject mainClassSubject = inspector().clazz(mainClass);
assertThat(mainClassSubject, isPresent());
switch (getBackend()) {
@@ -169,6 +192,10 @@
public RR run(TestRuntime runtime, String mainClass, String... args)
throws ExecutionException, IOException {
assert getBackend() == runtime.getBackend();
+ if (libraryDesugaringTestConfiguration.isEnabled()
+ && libraryDesugaringTestConfiguration.isAddRunClassPath()) {
+ additionalRunClassPath.add(libraryDesugaringTestConfiguration.buildDesugaredLibrary(state));
+ }
ClassSubject mainClassSubject = inspector().clazz(mainClass);
if (!mainClassSubject.isPresent()) {
for (Path classpathFile : additionalRunClassPath) {
diff --git a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
index 3c5b479..211df9c 100644
--- a/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -75,6 +75,9 @@
private boolean isAndroidBuildVersionAdded = false;
+ LibraryDesugaringTestConfiguration libraryDesugaringTestConfiguration =
+ LibraryDesugaringTestConfiguration.DISABLED;
+
public boolean isTestShrinkerBuilder() {
return false;
}
@@ -445,17 +448,33 @@
StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting()));
}
+ public T enableCoreLibraryDesugaring(LibraryDesugaringTestConfiguration configuration) {
+ this.libraryDesugaringTestConfiguration = configuration;
+ return self();
+ }
+
public T enableCoreLibraryDesugaring(
AndroidApiLevel minApiLevel,
StringConsumer keepRuleConsumer,
StringResource desugaredLibraryConfiguration) {
assert minApiLevel.getLevel() < AndroidApiLevel.O.getLevel();
- builder.addDesugaredLibraryConfiguration(desugaredLibraryConfiguration);
- // TODO(b/158543446): This should not be setting an implicit library file. Doing so causes
- // inconsistent library setup depending on the api level and makes tests hard to read and
- // reason about.
- // Use P to mimic current Android Studio.
- builder.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P));
+ return enableLibraryDesugaring(
+ LibraryDesugaringTestConfiguration.builder()
+ .setMinApi(minApiLevel)
+ .setKeepRuleConsumer(keepRuleConsumer)
+ .addDesugaredLibraryConfiguration(desugaredLibraryConfiguration)
+ .dontAddRunClasspath()
+ .build());
+ }
+
+ public T enableLibraryDesugaring(AndroidApiLevel minApiLevel) {
+ this.libraryDesugaringTestConfiguration =
+ LibraryDesugaringTestConfiguration.builder().setMinApi(minApiLevel).build();
+ return self();
+ }
+
+ public T enableLibraryDesugaring(LibraryDesugaringTestConfiguration configuration) {
+ this.libraryDesugaringTestConfiguration = configuration;
return self();
}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfDefaultInterfaceMethodsTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfDefaultInterfaceMethodsTest.java
new file mode 100644
index 0000000..a19ecec
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfDefaultInterfaceMethodsTest.java
@@ -0,0 +1,103 @@
+// Copyright (c) 2021, 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.apimodel;
+
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
+import static com.android.tools.r8.utils.AndroidApiLevel.L_MR1;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.TestBase;
+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 java.lang.reflect.Method;
+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 ApiModelNoInliningOfDefaultInterfaceMethodsTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public ApiModelNoInliningOfDefaultInterfaceMethodsTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test()
+ public void testR8() throws Exception {
+ Method apiMethod = Api.class.getDeclaredMethod("apiLevel22");
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Main.class, A.class, ApiCaller.class)
+ .addLibraryClasses(Api.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .apply(setMockApiLevelForMethod(apiMethod, L_MR1))
+ .apply(ApiModelingTestHelper::enableApiCallerIdentification)
+ .compile()
+ .inspect(
+ inspector -> {
+ ClassSubject aSubject = inspector.clazz(A.class);
+ assertThat(aSubject, isPresent());
+ aSubject.forAllMethods(
+ method -> {
+ // TODO(b/191013385): callApiLevel is merged into A, but not with method
+ // implementation.
+ // TODO(b/191013233): Check that the bridge is supposed to stay in R8.
+ if (method
+ .getOriginalName()
+ .equals(ApiCaller.class.getTypeName() + ".callApiLevel")
+ && !method.getAccessFlags().isBridge()) {
+ // TODO(b/191008231): Should not invoke api here.
+ assertThat(method, CodeMatchers.invokesMethodWithName("apiLevel22"));
+ return;
+ }
+ assertThat(method, not(CodeMatchers.invokesMethodWithName("apiLevel")));
+ });
+ })
+ .addRunClasspathClasses(Api.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("A::noApiCall", "ApiCaller::callApiLevel", "Api::apiLevel22");
+ }
+
+ public static class Api {
+
+ public static void apiLevel22() {
+ System.out.println("Api::apiLevel22");
+ }
+ }
+
+ public interface ApiCaller {
+ default void callApiLevel() {
+ System.out.println("ApiCaller::callApiLevel");
+ Api.apiLevel22();
+ }
+ }
+
+ public static class A implements ApiCaller {
+
+ public void noApiCall() {
+ System.out.println("A::noApiCall");
+ callApiLevel();
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ new A().noApiCall();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfLambdaTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfLambdaTest.java
new file mode 100644
index 0000000..c8f7caa
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfLambdaTest.java
@@ -0,0 +1,140 @@
+// Copyright (c) 2021, 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.apimodel;
+
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
+import static com.android.tools.r8.utils.AndroidApiLevel.L_MR1;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.StringUtils;
+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 java.lang.reflect.Method;
+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 ApiModelNoInliningOfLambdaTest extends TestBase {
+
+ private final TestParameters parameters;
+ private final String EXPECTED =
+ StringUtils.lines(
+ "ApiCaller::getAction",
+ "Api::apiLevel22",
+ "ApiCaller::callApi",
+ "Api::apiLevel22",
+ "Action::getAction",
+ "Api::apiLevel22");
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public ApiModelNoInliningOfLambdaTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ Method apiMethod = Api.class.getDeclaredMethod("apiLevel22");
+ testForR8(parameters.getBackend())
+ .addProgramClasses(ApiCaller.class, Action.class, Main.class)
+ .addLibraryClasses(Api.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .apply(setMockApiLevelForMethod(apiMethod, L_MR1))
+ .apply(ApiModelingTestHelper::enableApiCallerIdentification)
+ .allowAccessModification()
+ .noMinification()
+ .compile()
+ .inspect(
+ inspector -> {
+ ClassSubject action;
+ if (parameters.canUseDefaultAndStaticInterfaceMethods()) {
+ action = inspector.clazz(Action.class);
+ } else {
+ action = inspector.companionClassFor(Action.class);
+ }
+ assertThat(action, isPresent());
+ MethodSubject action$lambda$getAction$0 =
+ action.uniqueMethodWithName("lambda$getAction$0");
+ assertThat(action$lambda$getAction$0, isPresent());
+ assertThat(
+ action$lambda$getAction$0, CodeMatchers.invokesMethodWithName("apiLevel22"));
+ ClassSubject apiCaller = inspector.clazz(ApiCaller.class);
+ if (parameters.isDexRuntime()
+ && parameters.getApiLevel().isGreaterThanOrEqualTo(L_MR1)) {
+ assertThat(apiCaller, not(isPresent()));
+ } else {
+ assertThat(apiCaller, isPresent());
+ MethodSubject apiCaller$lambdagetAction$0 =
+ apiCaller.uniqueMethodWithName("lambda$getAction$0");
+ assertThat(apiCaller$lambdagetAction$0, isPresent());
+ assertThat(
+ apiCaller$lambdagetAction$0, CodeMatchers.invokesMethodWithName("apiLevel22"));
+ }
+ })
+ .addRunClasspathClasses(Api.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED);
+ }
+
+ public static class Api {
+
+ public static void apiLevel22() {
+ System.out.println("Api::apiLevel22");
+ }
+ }
+
+ public interface Action {
+
+ void doSomething();
+
+ static Action getAction() {
+ return () -> {
+ System.out.println("Action::getAction");
+ Api.apiLevel22();
+ };
+ }
+ }
+
+ public static class ApiCaller {
+
+ public static Action getAction() {
+ return () -> {
+ System.out.println("ApiCaller::getAction");
+ Api.apiLevel22();
+ };
+ }
+
+ public static Action getActionMethodReference() {
+ return ApiCaller::callApi;
+ }
+
+ public static void callApi() {
+ System.out.println("ApiCaller::callApi");
+ Api.apiLevel22();
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ ApiCaller.getAction().doSomething();
+ ApiCaller.getActionMethodReference().doSomething();
+ Action.getAction().doSomething();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfStaticInterfaceMethodsTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfStaticInterfaceMethodsTest.java
new file mode 100644
index 0000000..5ed1708
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoInliningOfStaticInterfaceMethodsTest.java
@@ -0,0 +1,103 @@
+// Copyright (c) 2021, 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.apimodel;
+
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
+import static com.android.tools.r8.utils.AndroidApiLevel.L_MR1;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+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.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeMatchers;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.lang.reflect.Method;
+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 ApiModelNoInliningOfStaticInterfaceMethodsTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public ApiModelNoInliningOfStaticInterfaceMethodsTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ Method apiMethod = Api.class.getDeclaredMethod("apiLevel22");
+ // Method apiCaller = ApiCaller.class.getDeclaredMethod("callApiLevel");
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Main.class, A.class, ApiCaller.class)
+ .addLibraryClasses(Api.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .apply(setMockApiLevelForMethod(apiMethod, L_MR1))
+ .apply(ApiModelingTestHelper::enableApiCallerIdentification)
+ .noMinification()
+ .compile()
+ .inspect(
+ inspector -> {
+ // The call to the api is moved to $-CC (or stays) and is then merged if allowed.
+ if (parameters.isDexRuntime()
+ && parameters.getApiLevel().isGreaterThanOrEqualTo(L_MR1)) {
+ assertEquals(1, inspector.allClasses().size());
+ } else {
+ assertEquals(2, inspector.allClasses().size());
+ ClassSubject aSubject = inspector.clazz(A.class);
+ assertThat(aSubject, isPresent());
+ // TODO(b/191008231): Should not invoke api here but stay on the CC class.
+ assertEquals(1, aSubject.allMethods().size());
+ MethodSubject callApiLevel = aSubject.uniqueMethodWithName("callApiLevel");
+ assertThat(callApiLevel, isPresent());
+ assertThat(callApiLevel, CodeMatchers.invokesMethodWithName("apiLevel22"));
+ }
+ })
+ .addRunClasspathClasses(Api.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("A::noApiCall", "ApiCaller::callApiLevel", "Api::apiLevel22");
+ }
+
+ public static class Api {
+
+ public static void apiLevel22() {
+ System.out.println("Api::apiLevel22");
+ }
+ }
+
+ public interface ApiCaller {
+ static void callApiLevel() {
+ System.out.println("ApiCaller::callApiLevel");
+ Api.apiLevel22();
+ }
+ }
+
+ public static class A implements ApiCaller {
+
+ public static void noApiCall() {
+ System.out.println("A::noApiCall");
+ ApiCaller.callApiLevel();
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ A.noApiCall();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingTest.java
new file mode 100644
index 0000000..e7c41d8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelNoVerticalMergingTest.java
@@ -0,0 +1,106 @@
+// Copyright (c) 2021, 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.apimodel;
+
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForMethod;
+import static com.android.tools.r8.utils.AndroidApiLevel.L_MR1;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertEquals;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+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.FoundMethodSubject;
+import java.lang.reflect.Method;
+import java.util.List;
+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 ApiModelNoVerticalMergingTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public ApiModelNoVerticalMergingTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test()
+ public void testR8() throws Exception {
+ Method apiMethod = Api.class.getDeclaredMethod("apiLevel22");
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Main.class, Base.class, Sub.class)
+ .addLibraryClasses(Api.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .apply(setMockApiLevelForMethod(apiMethod, L_MR1))
+ .apply(ApiModelingTestHelper::enableApiCallerIdentification)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .noMinification()
+ .compile()
+ .inspect(
+ inspector -> {
+ // TODO(b/191013385): Prevent Base merging with Sub.
+ ClassSubject base = inspector.clazz(Base.class);
+ assertThat(base, not(isPresent()));
+ ClassSubject sub = inspector.clazz(Sub.class);
+ List<FoundMethodSubject> callApis =
+ sub.allMethods(
+ method ->
+ method.getOriginalName().equals(Base.class.getTypeName() + ".callApi"));
+ // TODO(b/191013233): Remove synthetic bridge.
+ assertEquals(2, callApis.size());
+ })
+ .addRunClasspathClasses(Api.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("Sub::callCallApi", "Base::callApi", "Api::apiLevel22");
+ }
+
+ public static class Api {
+
+ public static void apiLevel22() {
+ System.out.println("Api::apiLevel22");
+ }
+ }
+
+ public static class Base {
+
+ public void callApi() {
+ System.out.println("Base::callApi");
+ Api.apiLevel22();
+ }
+ }
+
+ @NeverClassInline
+ public static class Sub extends Base {
+
+ @NeverInline
+ public void callCallApi() {
+ System.out.println("Sub::callCallApi");
+ callApi();
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ new Sub().callCallApi();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/InterfacesVisibilityTest.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/InterfacesVisibilityTest.java
new file mode 100644
index 0000000..b03e236
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/InterfacesVisibilityTest.java
@@ -0,0 +1,80 @@
+// Copyright (c) 2021, 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.classmerging.horizontal;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isImplementing;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.classmerging.horizontal.testclasses.InterfacesVisibilityTestClasses;
+import com.android.tools.r8.classmerging.horizontal.testclasses.InterfacesVisibilityTestClasses.ImplementingPackagePrivateInterface;
+import com.android.tools.r8.classmerging.horizontal.testclasses.InterfacesVisibilityTestClasses.Invoker;
+import com.android.tools.r8.utils.codeinspector.HorizontallyMergedClassesInspector;
+import org.junit.Test;
+
+public class InterfacesVisibilityTest extends HorizontalClassMergingTestBase {
+ public InterfacesVisibilityTest(TestParameters parameters) {
+ super(parameters);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ String packagePrivateInterfaceName =
+ InterfacesVisibilityTestClasses.class.getTypeName() + "$PackagePrivateInterface";
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass(), InterfacesVisibilityTestClasses.class)
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .enableNoVerticalClassMergingAnnotations()
+ .enableNoHorizontalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .addHorizontallyMergedClassesInspector(
+ HorizontallyMergedClassesInspector::assertNoClassesMerged)
+ .compile()
+ .inspect(
+ codeInspector -> {
+ // A is present and has no interfaces.
+ assertThat(codeInspector.clazz(A.class), isPresent());
+ assertTrue(
+ codeInspector.clazz(A.class).getDexProgramClass().getInterfaces().isEmpty());
+
+ // ImplementingPackagePrivateInterface is present and implements
+ // PackagePrivateInterface.
+ assertThat(
+ codeInspector.clazz(ImplementingPackagePrivateInterface.class),
+ isImplementing(codeInspector.clazz(packagePrivateInterfaceName)));
+ })
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("foo", "bar");
+ }
+
+ @NeverClassInline
+ public static class A {
+ @NeverInline
+ public void bar() {
+ System.out.println("bar");
+ }
+ }
+
+ public static class Main {
+ @NeverInline
+ public static void foo(ImplementingPackagePrivateInterface o) {
+ Invoker.invokeFoo(o);
+ }
+
+ public static void main(String[] args) {
+ ImplementingPackagePrivateInterface implementingPackagePrivateInterface =
+ new ImplementingPackagePrivateInterface();
+ A a = new A();
+ Invoker.invokeFoo(implementingPackagePrivateInterface);
+ a.bar();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/horizontal/testclasses/InterfacesVisibilityTestClasses.java b/src/test/java/com/android/tools/r8/classmerging/horizontal/testclasses/InterfacesVisibilityTestClasses.java
new file mode 100644
index 0000000..d5a5c14
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/horizontal/testclasses/InterfacesVisibilityTestClasses.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2021, 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.classmerging.horizontal.testclasses;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoHorizontalClassMerging;
+import com.android.tools.r8.NoVerticalClassMerging;
+
+public class InterfacesVisibilityTestClasses {
+ public static class Invoker {
+ @NeverInline
+ public static void invokeFoo(PackagePrivateInterface i) {
+ i.foo();
+ }
+ }
+
+ @NoVerticalClassMerging
+ @NeverClassInline
+ public static class ImplementingPackagePrivateInterface implements PackagePrivateInterface {
+ @Override
+ public void foo() {
+ System.out.println("foo");
+ }
+ }
+
+ @NoHorizontalClassMerging
+ @NoVerticalClassMerging
+ interface PackagePrivateInterface {
+ void foo();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/vertical/ForceInlineConstructorWithRetargetedLibMemberTest.java b/src/test/java/com/android/tools/r8/classmerging/vertical/ForceInlineConstructorWithRetargetedLibMemberTest.java
index 4a81ae5..b2010d7 100644
--- a/src/test/java/com/android/tools/r8/classmerging/vertical/ForceInlineConstructorWithRetargetedLibMemberTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/vertical/ForceInlineConstructorWithRetargetedLibMemberTest.java
@@ -12,6 +12,8 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -36,6 +38,7 @@
public void test() throws Exception {
// Regression test for b/170677722.
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(getClass())
.addKeepMainRule(TestClass.class)
.addVerticallyMergedClassesInspector(
diff --git a/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergingWithMissingSuperClassTest.java b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergingWithMissingSuperClassTest.java
new file mode 100644
index 0000000..53fbaa5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classmerging/vertical/VerticalClassMergingWithMissingSuperClassTest.java
@@ -0,0 +1,72 @@
+// Copyright (c) 2021, 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.classmerging.vertical;
+
+
+import com.android.tools.r8.NoVerticalClassMerging;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+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 VerticalClassMergingWithMissingSuperClassTest extends TestBase {
+
+ @Parameter public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(Main.class, A.class, B.class, C.class)
+ .addKeepMainRule(Main.class)
+ .addDontWarn(MissingClass.class)
+ .addVerticallyMergedClassesInspector(
+ inspector -> inspector.assertMergedIntoSubtype(B.class))
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .addRunClasspathFiles(buildOnDexRuntime(parameters, MissingClass.class))
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("C", "A", "B");
+ }
+
+ static class Main {
+ public static void main(String[] args) {
+ new C().m();
+ }
+ }
+
+ static class MissingClass {}
+
+ @NoVerticalClassMerging
+ static class A extends MissingClass {
+ void m() {
+ System.out.println("A");
+ }
+ }
+
+ static class B extends A {
+ @Override
+ void m() {
+ super.m();
+ System.out.println("B");
+ }
+ }
+
+ static class C extends B {
+ C() {
+ System.out.println("C");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/InvokeSuperToEmulatedDefaultMethodTest.java b/src/test/java/com/android/tools/r8/desugar/InvokeSuperToEmulatedDefaultMethodTest.java
index 9d3d498..8d914a8 100644
--- a/src/test/java/com/android/tools/r8/desugar/InvokeSuperToEmulatedDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/InvokeSuperToEmulatedDefaultMethodTest.java
@@ -8,7 +8,9 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.util.Collection;
import java.util.HashMap;
@@ -51,12 +53,13 @@
@Test
public void testDesugaring() throws Exception {
assumeTrue(needsDefaultInterfaceMethodDesugaring());
+
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(InvokeSuperToEmulatedDefaultMethodTest.class)
.setMinApi(parameters.getApiLevel())
- .enableCoreLibraryDesugaring(parameters.getApiLevel())
+ .enableLibraryDesugaring(parameters.getApiLevel())
.compile()
- .addDesugaredCoreLibraryRunClassPath(this::buildDesugaredLibrary, parameters.getApiLevel())
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(EXPECTED);
}
diff --git a/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java b/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
index 5aa2894..6e82466 100644
--- a/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/InvokeSuperToRewrittenDefaultMethodTest.java
@@ -13,7 +13,6 @@
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
-import com.android.tools.r8.StringResource;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
@@ -69,20 +68,11 @@
testForD8()
.addInnerClasses(InvokeSuperToRewrittenDefaultMethodTest.class)
.setMinApi(parameters.getApiLevel())
- .apply(
- b -> {
- if (rtWithoutConsumer) {
- b.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.B));
- // TODO(b/158543446): Remove this once enableCoreLibraryDesugaring is fixed.
- b.getBuilder()
- .addDesugaredLibraryConfiguration(
- StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting()));
- } else {
- // TODO(b/158543446): Move this out to the shared builder once
- // enableCoreLibraryDesugaring is fixed.
- b.enableCoreLibraryDesugaring(parameters.getApiLevel());
- }
- })
+ .addLibraryFiles(
+ rtWithoutConsumer
+ ? ToolHelper.getAndroidJar(AndroidApiLevel.B)
+ : ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .enableCoreLibraryDesugaring(parameters.getApiLevel())
.compileWithExpectedDiagnostics(
diagnostics -> {
if (rtWithoutConsumer) {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
index 5cc22b7..e0f9136 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/BufferedReaderTest.java
@@ -140,6 +140,7 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addOptionsModification(
options ->
options.desugaredLibraryConfiguration =
@@ -168,6 +169,7 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addOptionsModification(
options ->
options.desugaredLibraryConfiguration =
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ConcurrentHashMapSubclassTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ConcurrentHashMapSubclassTest.java
index 9b48952..696de2e 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ConcurrentHashMapSubclassTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ConcurrentHashMapSubclassTest.java
@@ -7,6 +7,8 @@
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
@@ -46,6 +48,7 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(ConcurrentHashMapSubclassTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -102,6 +105,7 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(ConcurrentHashMapSubclassTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepClassAndMembersRules(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionForwardingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionForwardingTest.java
index 3c822f2..10a127d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionForwardingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionForwardingTest.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -42,6 +42,7 @@
public void testCustomCollectionD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomCollectionForwardingTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -60,6 +61,7 @@
public void testCustomCollectionR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomCollectionForwardingTest.class)
.addKeepMainRule(Executor.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionInterfaceSuperTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionInterfaceSuperTest.java
index 684998e..10d91fa 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionInterfaceSuperTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionInterfaceSuperTest.java
@@ -7,6 +7,7 @@
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -58,6 +59,7 @@
}
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomCollectionInterfaceSuperTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -79,6 +81,7 @@
assumeTrue(parameters.isDexRuntime());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomCollectionInterfaceSuperTest.class)
.addKeepMainRule(Main.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionSuperCallsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionSuperCallsTest.java
index 2269987..e917cd3 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionSuperCallsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionSuperCallsTest.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.nio.file.Path;
@@ -44,6 +44,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
D8TestRunResult d8TestRunResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomCollectionSuperCallsTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -106,6 +107,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
R8TestRunResult r8TestRunResult =
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomCollectionSuperCallsTest.class)
.addKeepMainRule(Executor.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
index 514742c..d24f4dd 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomCollectionTest.java
@@ -10,6 +10,8 @@
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -54,6 +56,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
D8TestRunResult d8TestRunResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomCollectionTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -130,6 +133,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
R8TestRunResult r8TestRunResult =
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomCollectionTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepClassAndMembersRules(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java
index 57d8867..a1c19eb 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/CustomMapHierarchyTest.java
@@ -8,7 +8,9 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
@@ -60,6 +62,7 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomMapHierarchyTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -121,6 +124,7 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(CustomMapHierarchyTest.class)
.addKeepMainRule(Main.class)
.addKeepAllClassesRuleWithAllowObfuscation()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibrary2Test.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibrary2Test.java
index b7181de..4a4ee82 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibrary2Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibrary2Test.java
@@ -12,6 +12,8 @@
import com.android.tools.r8.TestRunResult;
import com.android.tools.r8.TestRuntime;
import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.lang.reflect.Method;
@@ -76,6 +78,7 @@
.apply(this::checkResult);
} else {
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(getClasses())
.addProgramClassFileData(getTransforms())
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibraryTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibraryTest.java
index d244909..e597f8e 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibraryTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideConflictWithLibraryTest.java
@@ -12,6 +12,8 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime;
import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.lang.reflect.Method;
@@ -77,6 +79,7 @@
.assertFailureWithErrorThatMatches(getExpectedError());
} else {
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(CLASSES)
.addProgramClassFileData(getTransforms())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideInLibraryTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideInLibraryTest.java
index ec4ba98..085cd28 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideInLibraryTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DefaultMethodOverrideInLibraryTest.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime;
import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
@@ -65,6 +66,7 @@
.assertSuccessWithOutput(EXPECTED);
} else {
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addInnerClasses(DefaultMethodOverrideInLibraryTest.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
index af6ca9e..3e23d64 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredGenericSignatureTest.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -55,6 +56,7 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(DesugaredGenericSignatureTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -118,6 +120,7 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(DesugaredGenericSignatureTest.class)
.addKeepMainRule(Main.class)
.addKeepAllClassesRuleWithAllowObfuscation()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCloneTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCloneTest.java
index 73e5d67..c4c0c13 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCloneTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryCloneTest.java
@@ -5,6 +5,8 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.time.DayOfWeek;
import java.util.List;
@@ -35,6 +37,7 @@
public void testD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(getClass())
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -52,6 +55,7 @@
public void testR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(getClass())
.addKeepMainRule(Main.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
index e705ca6..888436d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryMismatchTest.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.errors.DesugaredLibraryMismatchDiagnostic;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.origin.Origin;
@@ -55,6 +56,7 @@
// Combine DEX input without library desugaring with dexing with library desugaring.
try {
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(libraryDex)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
@@ -91,6 +93,7 @@
// Combine CF desugared input without library desugaring with dexing with library desugaring.
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(desugaredLibrary)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
@@ -118,6 +121,7 @@
.writeToZip();
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(desugaredLibraryDex)
.addProgramClasses(TestRunner.class)
.setMinApi(apiLevel)
@@ -161,6 +165,7 @@
// DEX code with library desugaring.
Path libraryDex =
testForD8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(Library.class)
.setMinApi(apiLevel)
.enableCoreLibraryDesugaring(apiLevel)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
index a4c52ad..2414cf7 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLibraryTestBase.java
@@ -5,16 +5,14 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import static com.android.tools.r8.utils.InternalOptions.ASM_VERSION;
-import static junit.framework.Assert.assertNull;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.CompilationMode;
-import com.android.tools.r8.DexIndexedConsumer;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.L8Command;
-import com.android.tools.r8.L8TestCompileResult;
+import com.android.tools.r8.L8TestBuilder;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration;
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.StringResource;
@@ -22,36 +20,27 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestState;
-import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
-import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfigurationParser;
-import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.tracereferences.TraceReferences;
import com.android.tools.r8.utils.AndroidApiLevel;
-import com.android.tools.r8.utils.AndroidAppConsumers;
-import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import org.junit.BeforeClass;
-import org.junit.rules.TemporaryFolder;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
@@ -104,151 +93,12 @@
return parameters.getApiLevel().getLevel() < AndroidApiLevel.O.getLevel();
}
- public static class L8TestBuilder {
-
- private final AndroidApiLevel apiLevel;
- private final TestState state;
-
- private CompilationMode mode = CompilationMode.RELEASE;
- private String generatedKeepRules = null;
- private List<String> keepRules = new ArrayList<>();
- private List<Path> additionalProgramFiles = new ArrayList<>();
- private Consumer<InternalOptions> optionsModifier = ConsumerUtils.emptyConsumer();
- private Path desugarJDKLibs = ToolHelper.getDesugarJDKLibs();
- private Path desugarJDKLibsConfiguration = null;
- private StringResource desugaredLibraryConfiguration =
- StringResource.fromFile(ToolHelper.getDesugarLibJsonForTesting());
- private List<Path> libraryFiles = new ArrayList<>();
-
- private L8TestBuilder(AndroidApiLevel apiLevel, TemporaryFolder temp) {
- this.apiLevel = apiLevel;
- this.state = new TestState(temp);
- }
-
- public L8TestBuilder addProgramFiles(Collection<Path> programFiles) {
- this.additionalProgramFiles.addAll(programFiles);
- return this;
- }
-
- public L8TestBuilder addLibraryFiles(Path... libraryFiles) {
- Collections.addAll(this.libraryFiles, libraryFiles);
- return this;
- }
-
- public L8TestBuilder addGeneratedKeepRules(String generatedKeepRules) {
- assertNull(this.generatedKeepRules);
- this.generatedKeepRules = generatedKeepRules;
- return this;
- }
-
- public L8TestBuilder addKeepRuleFile(Path keepRuleFile) throws IOException {
- this.keepRules.add(FileUtils.readTextFile(keepRuleFile, StandardCharsets.UTF_8));
- return this;
- }
-
- public L8TestBuilder addKeepRuleFiles(Collection<Path> keepRuleFiles) throws IOException {
- for (Path keepRuleFile : keepRuleFiles) {
- addKeepRuleFile(keepRuleFile);
- }
- return this;
- }
-
- public L8TestBuilder addOptionsModifier(Consumer<InternalOptions> optionsModifier) {
- this.optionsModifier = this.optionsModifier.andThen(optionsModifier);
- return this;
- }
-
- public L8TestBuilder applyIf(boolean condition, ThrowableConsumer<L8TestBuilder> thenConsumer) {
- return applyIf(condition, thenConsumer, ThrowableConsumer.empty());
- }
-
- public L8TestBuilder applyIf(
- boolean condition,
- ThrowableConsumer<L8TestBuilder> thenConsumer,
- ThrowableConsumer<L8TestBuilder> elseConsumer) {
- if (condition) {
- thenConsumer.acceptWithRuntimeException(this);
- } else {
- elseConsumer.acceptWithRuntimeException(this);
- }
- return this;
- }
-
- public L8TestBuilder setDebug() {
- this.mode = CompilationMode.DEBUG;
- return this;
- }
-
- public L8TestBuilder setDesugarJDKLibs(Path desugarJDKLibs) {
- this.desugarJDKLibs = desugarJDKLibs;
- return this;
- }
-
- public L8TestBuilder setDesugarJDKLibsConfiguration(Path desugarJDKLibsConfiguration) {
- this.desugarJDKLibsConfiguration = desugarJDKLibsConfiguration;
- return this;
- }
-
- public L8TestBuilder setDesugaredLibraryConfiguration(Path path) {
- this.desugaredLibraryConfiguration = StringResource.fromFile(path);
- return this;
- }
-
- private L8TestBuilder setDisableL8AnnotationRemoval(boolean disableL8AnnotationRemoval) {
- return addOptionsModifier(
- options -> options.testing.disableL8AnnotationRemoval = disableL8AnnotationRemoval);
- }
-
- public L8TestCompileResult compile()
- throws IOException, CompilationFailedException, ExecutionException {
- // We wrap exceptions in a RuntimeException to call this from a lambda.
- AndroidAppConsumers sink = new AndroidAppConsumers();
- L8Command.Builder l8Builder =
- L8Command.builder(state.getDiagnosticsHandler())
- .addProgramFiles(getProgramFiles())
- .addLibraryFiles(getLibraryFiles())
- .setMode(mode)
- .addDesugaredLibraryConfiguration(desugaredLibraryConfiguration)
- .setMinApiLevel(apiLevel.getLevel())
- .setProgramConsumer(sink.wrapProgramConsumer(DexIndexedConsumer.emptyConsumer()));
- Path mapping = null;
- if (!keepRules.isEmpty() || generatedKeepRules != null) {
- mapping = state.getNewTempFile("mapping.txt");
- l8Builder
- .addProguardConfiguration(
- ImmutableList.<String>builder()
- .addAll(keepRules)
- .addAll(
- generatedKeepRules != null
- ? ImmutableList.of(generatedKeepRules)
- : Collections.emptyList())
- .build(),
- Origin.unknown())
- .setProguardMapOutputPath(mapping);
- }
- ToolHelper.runL8(l8Builder.build(), optionsModifier);
- return new L8TestCompileResult(sink.build(), apiLevel, generatedKeepRules, mapping, state)
- .inspect(
- inspector ->
- inspector.forAllClasses(
- clazz -> assertTrue(clazz.getFinalName().startsWith("j$."))));
- }
-
- private Collection<Path> getProgramFiles() {
- ImmutableList.Builder<Path> builder = ImmutableList.<Path>builder().add(desugarJDKLibs);
- if (desugarJDKLibsConfiguration != null) {
- builder.add(desugarJDKLibsConfiguration);
- }
- return builder.addAll(additionalProgramFiles).build();
- }
-
- private Collection<Path> getLibraryFiles() {
- return libraryFiles;
- }
+ protected L8TestBuilder testForL8(AndroidApiLevel apiLevel) {
+ return L8TestBuilder.create(apiLevel, Backend.DEX, new TestState(temp));
}
- protected L8TestBuilder testForL8(AndroidApiLevel apiLevel) {
- return new L8TestBuilder(apiLevel, temp);
+ protected L8TestBuilder testForL8(AndroidApiLevel apiLevel, Backend backend) {
+ return L8TestBuilder.create(apiLevel, backend, new TestState(temp));
}
protected Path buildDesugaredLibrary(AndroidApiLevel apiLevel) {
@@ -341,10 +191,7 @@
}
protected KeepRuleConsumer createKeepRuleConsumer(TestParameters parameters) {
- if (requiresAnyCoreLibDesugaring(parameters)) {
- return new PresentKeepRuleConsumer();
- }
- return new AbsentKeepRuleConsumer();
+ return LibraryDesugaringTestConfiguration.createKeepRuleConsumer(parameters);
}
public Path getDesugaredLibraryInCF(
@@ -471,55 +318,6 @@
String get();
}
- public static class AbsentKeepRuleConsumer implements KeepRuleConsumer {
-
- public String get() {
- return null;
- }
-
- @Override
- public void accept(String string, DiagnosticsHandler handler) {
- throw new Unreachable("No desugaring on high API levels");
- }
-
- @Override
- public void finished(DiagnosticsHandler handler) {
- throw new Unreachable("No desugaring on high API levels");
- }
- }
-
- public static class PresentKeepRuleConsumer implements KeepRuleConsumer {
-
- StringBuilder stringBuilder = new StringBuilder();
- String result = null;
-
- @Override
- public void accept(String string, DiagnosticsHandler handler) {
- assert stringBuilder != null;
- assert result == null;
- stringBuilder.append(string);
- }
-
- @Override
- public void finished(DiagnosticsHandler handler) {
- assert stringBuilder != null;
- assert result == null;
- result = stringBuilder.toString();
- stringBuilder = null;
- }
-
- public String get() {
- // TODO(clement): remove that branch once StringConsumer has finished again.
- if (stringBuilder != null) {
- finished(null);
- }
-
- assert stringBuilder == null;
- assert result != null;
- return result;
- }
- }
-
protected static class ClassFileInfo {
private final String classBinaryName;
private List<String> interfaces;
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java
index 593c003..7a7ae9f 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectedTypePassedToStaticType.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -43,6 +44,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
D8TestRunResult runResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(DesugaredLocalDateReflectedTypePassedToStaticType.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -67,6 +69,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
R8TestRunResult runResult =
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(DesugaredLocalDateReflectedTypePassedToStaticType.class)
.addKeepMainRule(Main.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectionTest.java
index f5205f1..15d312d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredLocalDateReflectionTest.java
@@ -9,7 +9,9 @@
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.util.List;
@@ -42,6 +44,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
D8TestRunResult runResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(DesugaredLocalDateReflectionTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -66,6 +69,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
R8TestRunResult runResult =
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(DesugaredLocalDateReflectionTest.class)
.addKeepMainRule(Main.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java
index bedf904..bb2da3c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DesugaredReflectedDesugaredTypePassedToStaticTypeTest.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -44,6 +45,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
D8TestRunResult runResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(DesugaredReflectedDesugaredTypePassedToStaticTypeTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -68,6 +70,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
R8TestRunResult runResult =
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(DesugaredReflectedDesugaredTypePassedToStaticTypeTest.class)
.addKeepMainRule(Main.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
index 5f323bc..057d37f 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DontKeepBootstrapClassesTest.java
@@ -6,8 +6,10 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration.PresentKeepRuleConsumer;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.Arrays;
import java.util.function.Consumer;
@@ -33,6 +35,7 @@
public void test() throws Exception {
KeepRuleConsumer keepRuleConsumer = new PresentKeepRuleConsumer();
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(TestClass.class)
.setMinApi(minApiLevel)
.addLibraryClasses(CustomLibClass.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DoubleUtilityClassTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DoubleUtilityClassTest.java
index 3b12474..8ab1e6b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DoubleUtilityClassTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/DoubleUtilityClassTest.java
@@ -9,6 +9,8 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.zone.ZoneOffsetTransition;
@@ -36,6 +38,7 @@
public void testDoubleUtility() throws Exception {
for (Class<?> executor : new Class<?>[] {ExecutorV1.class, ExecutorV2.class}) {
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(executor)
.enableCoreLibraryDesugaring(parameters.getApiLevel())
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FeatureSplitTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FeatureSplitTest.java
index bca207f..f7eecc8 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FeatureSplitTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/FeatureSplitTest.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime;
-import com.android.tools.r8.TestShrinkerBuilder;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.ArtCommandBuilder;
import com.android.tools.r8.ToolHelper.ProcessResult;
@@ -237,6 +236,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(BaseClass.class, RunInterface.class, SplitRunner.class)
.setMinApi(parameters.getApiLevel())
.addFeatureSplit(
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ImplementedInterfacesTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ImplementedInterfacesTest.java
index b5ab3b5..75692a2 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ImplementedInterfacesTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ImplementedInterfacesTest.java
@@ -10,6 +10,8 @@
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.io.Serializable;
@@ -67,6 +69,7 @@
public void testInterfaces() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(ImplementedInterfacesTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InstantTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InstantTest.java
index 7e38a30..a99d29c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InstantTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InstantTest.java
@@ -5,6 +5,8 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.time.Instant;
import java.time.ZoneOffset;
@@ -35,6 +37,7 @@
public void testInstantD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(InstantTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -52,6 +55,7 @@
public void testInstantR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(InstantTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepClassAndMembersRules(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InvalidLibraryTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InvalidLibraryTest.java
index 0490d71..8ef34bb 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InvalidLibraryTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/InvalidLibraryTest.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.errors.InvalidLibrarySuperclassDiagnostic;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -67,6 +67,7 @@
public void testProgramSupertype() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(
Executor.class, SuperLibraryClass.class, LocalClass.class, LocalClassOverride.class)
@@ -88,6 +89,7 @@
Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class, LocalClass.class, LocalClassOverride.class)
.addClasspathClasses(SuperLibraryClass.class)
@@ -114,6 +116,7 @@
Assume.assumeTrue(requiresAnyCoreLibDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class, LocalClass.class, LocalClassOverride.class)
.addLibraryClasses(CustomLibraryClass.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IterableTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IterableTest.java
index 0c16701..e5f51dd 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IterableTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IterableTest.java
@@ -7,6 +7,8 @@
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -104,6 +106,7 @@
}
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(IterableTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IterateTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IterateTest.java
index 41935e4..0726e49 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IterateTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IterateTest.java
@@ -5,6 +5,8 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
@@ -79,6 +81,7 @@
}
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(IterateTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
index 46cb2bd..976f00e 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/IteratorTest.java
@@ -10,7 +10,9 @@
import static org.hamcrest.CoreMatchers.containsString;
import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration.AbsentKeepRuleConsumer;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -61,6 +63,7 @@
}
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(IteratorTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
index 3c78730..5d0cea7 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/J$ExtensionTest.java
@@ -143,6 +143,7 @@
try {
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(compiledClasses)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
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 7190c34..e1889a8 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
@@ -9,12 +9,13 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestBase;
-import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.TestShrinkerBuilder;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -237,20 +238,18 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
Assume.assumeTrue(shrinkDesugaredLibrary || !traceReferencesKeepRules);
- KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
- TestCompileResult<?, ?> result =
- testForD8()
- .addInnerClasses(JavaTimeTest.class)
- .setMinApi(parameters.getApiLevel())
- .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
- .compile()
- .inspect(this::checkRewrittenInvokesForD8);
- result
- .addDesugaredCoreLibraryRunClassPath(
- this::buildDesugaredLibrary,
- parameters.getApiLevel(),
- desugaredLibraryKeepRules(keepRuleConsumer, result::writeToZip),
- shrinkDesugaredLibrary)
+ testForD8()
+ .addInnerClasses(JavaTimeTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .enableLibraryDesugaring(
+ LibraryDesugaringTestConfiguration.builder()
+ .setMinApi(parameters.getApiLevel())
+ .withKeepRuleConsumer()
+ .setMode(shrinkDesugaredLibrary ? CompilationMode.RELEASE : CompilationMode.DEBUG)
+ .build())
+ .compile()
+ .inspect(this::checkRewrittenInvokesForD8)
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(expectedOutput);
}
@@ -260,23 +259,21 @@
Assume.assumeTrue(parameters.getRuntime().isDex());
Assume.assumeTrue(shrinkDesugaredLibrary || !traceReferencesKeepRules);
- KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
- TestCompileResult<?, ?> result =
- testForR8(parameters.getBackend())
- .addInnerClasses(JavaTimeTest.class)
- .addKeepMainRule(TestClass.class)
- .enableNoVerticalClassMergingAnnotations()
- .setMinApi(parameters.getApiLevel())
- .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
- .enableInliningAnnotations()
- .compile()
- .inspect(this::checkRewrittenInvokesForR8);
- result
- .addDesugaredCoreLibraryRunClassPath(
- this::buildDesugaredLibrary,
- parameters.getApiLevel(),
- desugaredLibraryKeepRules(keepRuleConsumer, result::writeToZip),
- shrinkDesugaredLibrary)
+ testForR8(parameters.getBackend())
+ .addInnerClasses(JavaTimeTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableNoVerticalClassMergingAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .enableLibraryDesugaring(
+ LibraryDesugaringTestConfiguration.builder()
+ .setMinApi(parameters.getApiLevel())
+ .withKeepRuleConsumer()
+ .setMode(shrinkDesugaredLibrary ? CompilationMode.RELEASE : CompilationMode.DEBUG)
+ .build())
+ .enableInliningAnnotations()
+ .compile()
+ .inspect(this::checkRewrittenInvokesForR8)
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(expectedOutput);
}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
index 32d9d95..0ac3687 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilFunctionTest.java
@@ -10,6 +10,8 @@
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -61,6 +63,7 @@
public void testJavaUtilFunctionD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(JavaUtilFunctionTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -80,6 +83,7 @@
public void testJavaUtilFunctionR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.enableInliningAnnotations()
.noMinification()
.addKeepMainRule(TestClass.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilOptionalTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilOptionalTest.java
index c2f83eb..1e145c4 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilOptionalTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/JavaUtilOptionalTest.java
@@ -93,6 +93,7 @@
@Test
public void testJavaOptionalJava9() throws Exception {
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(
Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION))
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibraryEmptySubclassInterfaceTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibraryEmptySubclassInterfaceTest.java
index ced1c31..172d7f9 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibraryEmptySubclassInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LibraryEmptySubclassInterfaceTest.java
@@ -8,6 +8,8 @@
import static org.hamcrest.MatcherAssert.assertThat;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@@ -38,6 +40,7 @@
public void testD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(LibraryEmptySubclassInterfaceTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -64,6 +67,7 @@
public void testR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(LibraryEmptySubclassInterfaceTest.class)
.addKeepMainRule(Executor.class)
.noMinification()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LinkedHashSetTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LinkedHashSetTest.java
index bbadc1d..ed4b6bc 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LinkedHashSetTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/LinkedHashSetTest.java
@@ -6,6 +6,8 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.Spliterator;
@@ -32,6 +34,7 @@
public void testLinkedHashSetOverrides() throws Exception {
String stdOut =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(LinkedHashSetTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java
index be9ae1a..1f1b593 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MergingWithDesugaredLibraryTest.java
@@ -62,6 +62,7 @@
try {
compileResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(buildPart1DesugaredLibrary(), buildPart2NoDesugaredLibrary())
.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
@@ -250,6 +251,7 @@
private Path buildPart1DesugaredLibrary() throws Exception {
return testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(Part1.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MinimalInterfaceSuperTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MinimalInterfaceSuperTest.java
index ff1039f..8de40b0 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MinimalInterfaceSuperTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MinimalInterfaceSuperTest.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.util.AbstractCollection;
@@ -44,6 +45,7 @@
return;
}
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(MinimalInterfaceSuperTest.class)
.addKeepMainRule(Main.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MonthTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MonthTest.java
index 6b2692b..2b71ee8 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MonthTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/MonthTest.java
@@ -7,6 +7,8 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.time.Month;
import java.time.format.TextStyle;
@@ -57,6 +59,7 @@
return;
}
testForD8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(MonthTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
@@ -70,6 +73,7 @@
public void testMonthR8() throws Exception {
Assume.assumeTrue(parameters.isDexRuntime());
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(MonthTest.class)
.addKeepMainRule(MonthTest.Main.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDefaultMethodOverrideInLibraryTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDefaultMethodOverrideInLibraryTest.java
index d9f93b9..37f834a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDefaultMethodOverrideInLibraryTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDefaultMethodOverrideInLibraryTest.java
@@ -11,6 +11,8 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime;
import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.lang.reflect.Method;
import java.util.Collection;
@@ -69,6 +71,7 @@
.assertSuccessWithOutput(EXPECTED);
} else {
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addInnerClasses(NoDefaultMethodOverrideInLibraryTest.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDesugaredLibraryDexFileTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDesugaredLibraryDexFileTest.java
index f0e55c0..4d99161 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDesugaredLibraryDexFileTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoDesugaredLibraryDexFileTest.java
@@ -7,6 +7,8 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.ArrayList;
@@ -44,6 +46,7 @@
Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(NoDesugaredLibraryDexFileTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -59,6 +62,7 @@
Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(NoDesugaredLibraryDexFileTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepClassAndMembersRules(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoForwardingMethodsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoForwardingMethodsTest.java
index 625395f..81457f6 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoForwardingMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/NoForwardingMethodsTest.java
@@ -7,6 +7,7 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
@@ -44,6 +45,7 @@
public void testCustomCollectionD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(NoForwardingMethodsTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -62,6 +64,7 @@
public void testCustomCollectionR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(NoForwardingMethodsTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepClassAndMembersRules(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
index 3e89a4f..213324c 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
@@ -45,6 +45,25 @@
@RunWith(Parameterized.class)
public class ObjectsTest extends DesugaredLibraryTestBase implements Opcodes {
+ private static final String EXPECTED_OUTPUT =
+ StringUtils.lines(
+ "1",
+ "false",
+ "false",
+ Objects.toString(Objects.hash(1, 2)),
+ "4",
+ "NPE",
+ "Was null",
+ "Supplier said was null",
+ "5",
+ "6",
+ "true",
+ "false",
+ "1",
+ "2",
+ "3",
+ "4");
+
private final TestParameters parameters;
private final boolean libraryDesugarJavaUtilObjects;
private final boolean shrinkDesugaredLibrary = false;
@@ -178,7 +197,7 @@
boolean invokeJDollarUtilObjects =
libraryDesugarJavaUtilObjects && parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
boolean invokeJavaUtilObjectsWithSupplier =
- !libraryDesugarJavaUtilObjects || !parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
+ parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N);
boolean invokeJDollarUtilObjectsWithSupplier =
libraryDesugarJavaUtilObjects && parameters.getApiLevel().isLessThan(AndroidApiLevel.N);
@@ -329,25 +348,19 @@
parameters.getApiLevel(),
desugaredLibraryKeepRules,
shrinkDesugaredLibrary)
- .run(
- parameters.getRuntime(),
- TestClass.class,
- Boolean.toString(libraryDesugarJavaUtilObjects))
- .assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
} else {
// Build the desugared library in class file format.
Path desugaredLib =
getDesugaredLibraryInCF(parameters, this::configurationForLibraryCompilation);
- // Run on the JVM with desuagred library on classpath.
+ // Run on the JVM with desugared library on classpath.
testForJvm()
.addProgramFiles(jar)
.addRunClasspathFiles(desugaredLib)
- .run(
- parameters.getRuntime(),
- TestClass.class,
- Boolean.toString(libraryDesugarJavaUtilObjects))
- .assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
}
}
@@ -375,11 +388,8 @@
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.inspect(this::inspect)
- .run(
- parameters.getRuntime(),
- TestClass.class,
- Boolean.toString(libraryDesugarJavaUtilObjects))
- .assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
}
@Test
@@ -411,33 +421,8 @@
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.inspect(this::inspect)
- .run(
- parameters.getRuntime(),
- TestClass.class,
- Boolean.toString(libraryDesugarJavaUtilObjects))
- .assertSuccessWithOutput(expectedOutput(libraryDesugarJavaUtilObjects));
- }
-
- private String expectedOutput(boolean objectsRequireNonNullWithSupplierSupported) {
- return StringUtils.lines(
- "1",
- "false",
- "false",
- Objects.toString(Objects.hash(1, 2)),
- "4",
- "NPE",
- "Was null",
- objectsRequireNonNullWithSupplierSupported
- ? "Supplier said was null"
- : "Not supported (b/174840626)",
- "5",
- "6",
- "true",
- "false",
- "1",
- "2",
- "3",
- "4");
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
}
static class TestClass {
@@ -522,7 +507,6 @@
}
public static void main(String[] args) throws Exception {
- boolean objectsRequireNonNullWithSupplierSupported = Boolean.parseBoolean(args[0]);
// Android K methods.
objectsCompare("b", "a");
objectsDeepEquals(args, new Object());
@@ -531,11 +515,7 @@
objectsHashCode(4);
objectsRequireNonNull(getNonNullableNull());
objectsRequireNonNullWithMessage(null, "Was null");
- if (objectsRequireNonNullWithSupplierSupported) {
- objectsRequireNonNullWithSupplier(null, () -> "Supplier said was null");
- } else {
- System.out.println("Not supported (b/174840626)");
- }
+ objectsRequireNonNullWithSupplier(null, () -> "Supplier said was null");
objectsToString(makeNullable("5"));
objectsToStringWithNullDefault(getNonNullableNull(), "6");
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/PriorityQueueSubclassTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/PriorityQueueSubclassTest.java
index 2c29f58..8cd0cca 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/PriorityQueueSubclassTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/PriorityQueueSubclassTest.java
@@ -5,6 +5,8 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.util.List;
import java.util.PriorityQueue;
@@ -35,6 +37,7 @@
public void testPriorityQueueD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(PriorityQueueSubclassTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -52,6 +55,7 @@
public void testPriorityQueueR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(PriorityQueueSubclassTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepClassAndMembersRules(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
index aa05c9d..9fe36a6 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ProgramRewritingTest.java
@@ -60,6 +60,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
D8TestCompileResult compileResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "stream.jar"))
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -118,6 +119,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
R8TestRunResult runResult =
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.minification(minifying)
.addKeepMainRule(TEST_CLASS)
.addProgramFiles(Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR + "stream.jar"))
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ReleasedVersionsSmokeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ReleasedVersionsSmokeTest.java
new file mode 100644
index 0000000..a81de0a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ReleasedVersionsSmokeTest.java
@@ -0,0 +1,112 @@
+// 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.desugaredlibrary;
+
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration.Configuration;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import java.time.Clock;
+import java.time.Duration;
+import java.time.ZoneId;
+import java.util.List;
+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 ReleasedVersionsSmokeTest extends DesugaredLibraryTestBase {
+
+ private final TestParameters parameters;
+ private final Configuration configuration;
+ private static final String expectedOutput =
+ StringUtils.lines(
+ "true",
+ "Caught java.time.format.DateTimeParseException",
+ "true",
+ "1970-01-02T10:17:36.789Z",
+ "GMT",
+ "GMT",
+ "1000",
+ "Hello, world");
+
+ @Parameters(name = "{0}, {1}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ Configuration.getReleased(),
+ getTestParameters().withDexRuntimes().withApiLevel(AndroidApiLevel.B).build());
+ }
+
+ public ReleasedVersionsSmokeTest(Configuration configuration, TestParameters parameters) {
+ this.configuration = configuration;
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .addInnerClasses(ReleasedVersionsSmokeTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(
+ LibraryDesugaringTestConfiguration.builder()
+ .setMinApi(parameters.getApiLevel())
+ .setConfiguration(configuration)
+ .withKeepRuleConsumer()
+ .setMode(CompilationMode.DEBUG)
+ .build())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .applyIf(
+ configuration.equals(Configuration.RELEASED_1_1_5),
+ r -> r.assertSuccessWithOutput(expectedOutput),
+ r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .addInnerClasses(ReleasedVersionsSmokeTest.class)
+ .addKeepMainRule(TestClass.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableCoreLibraryDesugaring(
+ LibraryDesugaringTestConfiguration.builder()
+ .setMinApi(parameters.getApiLevel())
+ .withKeepRuleConsumer()
+ .setMode(CompilationMode.RELEASE)
+ .build())
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutput(expectedOutput);
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ System.out.println(Clock.systemDefaultZone().getZone().equals(ZoneId.systemDefault()));
+ try {
+ java.time.LocalDate.parse("");
+ } catch (java.time.format.DateTimeParseException e) {
+ System.out.println("Caught java.time.format.DateTimeParseException");
+ }
+ System.out.println(java.time.ZoneOffset.getAvailableZoneIds().size() > 0);
+ System.out.println(
+ java.util.Date.from(new java.util.Date(123456789).toInstant()).toInstant());
+
+ java.util.TimeZone timeZone = java.util.TimeZone.getTimeZone(ZoneId.of("GMT"));
+ System.out.println(timeZone.getID());
+ System.out.println(timeZone.toZoneId().getId());
+
+ System.out.println(Duration.ofMillis(1000).toMillis());
+
+ System.out.println("Hello, world");
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RequiredNonNullWithSupplierTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RequiredNonNullWithSupplierTest.java
new file mode 100644
index 0000000..e1b302d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RequiredNonNullWithSupplierTest.java
@@ -0,0 +1,86 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.desugar.desugaredlibrary;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.BooleanUtils;
+import com.android.tools.r8.utils.StringUtils;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Supplier;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class RequiredNonNullWithSupplierTest extends DesugaredLibraryTestBase {
+
+ private static final String EXPECTED_OUTPUT = StringUtils.lines("SuppliedString2", "OK");
+
+ private final TestParameters parameters;
+ private final boolean shrinkDesugaredLibrary;
+
+ @Parameterized.Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
+ public static List<Object[]> data() {
+ return buildParameters(
+ BooleanUtils.values(), getTestParameters().withAllRuntimesAndApiLevels().build());
+ }
+
+ public RequiredNonNullWithSupplierTest(
+ boolean shrinkDesugaredLibrary, TestParameters parameters) {
+ this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testRequiredNonNullWithSupplierTest() throws Exception {
+ if (parameters.isCfRuntime()) {
+ testForJvm()
+ .addInnerClasses(RequiredNonNullWithSupplierTest.class)
+ .run(parameters.getRuntime(), Executor.class)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
+ return;
+ }
+ KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
+ testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ .addInnerClasses(RequiredNonNullWithSupplierTest.class)
+ .enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .addDesugaredCoreLibraryRunClassPath(
+ this::buildDesugaredLibrary,
+ parameters.getApiLevel(),
+ keepRuleConsumer.get(),
+ shrinkDesugaredLibrary)
+ .run(parameters.getRuntime(), Executor.class)
+ .assertSuccessWithOutput(EXPECTED_OUTPUT);
+ }
+
+ static class Executor {
+
+ public static void main(String[] args) {
+ Object o = System.currentTimeMillis() > 10 ? new Object() : new Object();
+ Objects.requireNonNull(o, () -> "SuppliedString");
+ try {
+ Objects.requireNonNull(null, () -> "SuppliedString2");
+ throw new AssertionError("Unexpected");
+ } catch (NullPointerException e) {
+ System.out.println(e.getMessage());
+ }
+ try {
+ Objects.requireNonNull(null, (Supplier<String>) null);
+ throw new AssertionError("Unexpected");
+ } catch (NullPointerException e) {
+ // Normally we would want to print the exception message, but some ART versions have a bug
+ // where they erroneously calls supplier.get() on a null reference which produces the NPE
+ // but with an ART-defined message. See b/147419222.
+ System.out.println("OK");
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java
new file mode 100644
index 0000000..40d658d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetAndBackportTest.java
@@ -0,0 +1,175 @@
+// Copyright (c) 2021, 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.desugaredlibrary;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class RetargetAndBackportTest extends DesugaredLibraryTestBase implements Opcodes {
+
+ Backend backend;
+
+ @Parameters(name = "{0} {1}")
+ public static List<Object[]> data() {
+ return buildParameters(getTestParameters().withNoneRuntime().build(), Backend.values());
+ }
+
+ public RetargetAndBackportTest(TestParameters parameters, Backend backend) {
+ this.backend = backend;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForL8(AndroidApiLevel.B, backend)
+ .noDefaultDesugarJDKLibs()
+ .addProgramClassFileData(dump())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
+ /*
+ Add this library desugaring configuration:
+ "library_flags": [
+ {
+ "rewrite_prefix": {"java.time.": "j$.time."},
+ "backport": {"java.lang.DesugarMath": "java.lang.Math"},
+ "retarget_lib_member": {"java.util.Date#toInstant": "java.util.DesugarDate"}
+ }
+ ],
+ */
+ .addOptionsModifier(
+ options ->
+ options.desugaredLibraryConfiguration =
+ DesugaredLibraryConfiguration.builder(
+ options.dexItemFactory(), options.reporter, Origin.unknown())
+ .setDesugaredLibraryIdentifier("my-identifier")
+ .putRewritePrefix("java.time.", "j$.time.")
+ .putBackportCoreLibraryMember("java.lang.DesugarMath", "java.lang.Math")
+ .putRetargetCoreLibMember(
+ "java.util.Date#toInstant", "java.util.DesugarDate")
+ .setLibraryCompilation()
+ .build())
+ .compile()
+ .inspect(
+ inspector -> {
+ assertTrue(
+ inspector
+ .clazz("j$.time.Duration")
+ .uniqueMethodWithName("toMillis")
+ .streamInstructions()
+ .filter(InstructionSubject::isInvokeStatic)
+ .map(InstructionSubject::toString)
+ .allMatch(s -> s.contains("Backport")));
+ });
+ }
+
+ // Dump of java.time.Duration from JDK 11 based desugared library input built from
+ // https://github.com/google/desugar_jdk_libs/commit/a2a0a26c06cbee9144eceaefd8c65e1bae2b611c.
+ public static byte[] dump() {
+
+ ClassWriter classWriter = new ClassWriter(0);
+ MethodVisitor methodVisitor;
+
+ classWriter.visit(
+ V11,
+ ACC_PUBLIC | ACC_FINAL | ACC_SUPER,
+ "java/time/Duration",
+ "Ljava/lang/Object;Ljava/time/temporal/TemporalAmount;Ljava/lang/Comparable<Ljava/time/Duration;>;Ljava/io/Serializable;",
+ "java/lang/Object",
+ new String[] {
+ "java/time/temporal/TemporalAmount", "java/lang/Comparable", "java/io/Serializable"
+ });
+
+ classWriter.visitSource("Duration.java", null);
+
+ {
+ methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "toMillis", "()J", null, null);
+ methodVisitor.visitCode();
+ Label label0 = new Label();
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitLineNumber(1217, label0);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitFieldInsn(GETFIELD, "java/time/Duration", "seconds", "J");
+ methodVisitor.visitVarInsn(LSTORE, 1);
+ Label label1 = new Label();
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitLineNumber(1218, label1);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitFieldInsn(GETFIELD, "java/time/Duration", "nanos", "I");
+ methodVisitor.visitInsn(I2L);
+ methodVisitor.visitVarInsn(LSTORE, 3);
+ Label label2 = new Label();
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitLineNumber(1219, label2);
+ methodVisitor.visitVarInsn(LLOAD, 1);
+ methodVisitor.visitInsn(LCONST_0);
+ methodVisitor.visitInsn(LCMP);
+ Label label3 = new Label();
+ methodVisitor.visitJumpInsn(IFGE, label3);
+ Label label4 = new Label();
+ methodVisitor.visitLabel(label4);
+ methodVisitor.visitLineNumber(1222, label4);
+ methodVisitor.visitVarInsn(LLOAD, 1);
+ methodVisitor.visitInsn(LCONST_1);
+ methodVisitor.visitInsn(LADD);
+ methodVisitor.visitVarInsn(LSTORE, 1);
+ Label label5 = new Label();
+ methodVisitor.visitLabel(label5);
+ methodVisitor.visitLineNumber(1223, label5);
+ methodVisitor.visitVarInsn(LLOAD, 3);
+ methodVisitor.visitLdcInsn(new Long(1000000000L));
+ methodVisitor.visitInsn(LSUB);
+ methodVisitor.visitVarInsn(LSTORE, 3);
+ methodVisitor.visitLabel(label3);
+ methodVisitor.visitLineNumber(1225, label3);
+ methodVisitor.visitFrame(
+ Opcodes.F_APPEND, 2, new Object[] {Opcodes.LONG, Opcodes.LONG}, 0, null);
+ methodVisitor.visitVarInsn(LLOAD, 1);
+ methodVisitor.visitIntInsn(SIPUSH, 1000);
+ methodVisitor.visitMethodInsn(
+ INVOKESTATIC, "java/lang/DesugarMath", "multiplyExact", "(JI)J", false);
+ methodVisitor.visitVarInsn(LSTORE, 5);
+ Label label6 = new Label();
+ methodVisitor.visitLabel(label6);
+ methodVisitor.visitLineNumber(1226, label6);
+ methodVisitor.visitVarInsn(LLOAD, 5);
+ methodVisitor.visitVarInsn(LLOAD, 3);
+ methodVisitor.visitLdcInsn(new Long(1000000L));
+ methodVisitor.visitInsn(LDIV);
+ methodVisitor.visitMethodInsn(
+ INVOKESTATIC, "java/lang/DesugarMath", "addExact", "(JJ)J", false);
+ methodVisitor.visitVarInsn(LSTORE, 5);
+ Label label7 = new Label();
+ methodVisitor.visitLabel(label7);
+ methodVisitor.visitLineNumber(1227, label7);
+ methodVisitor.visitVarInsn(LLOAD, 5);
+ methodVisitor.visitInsn(LRETURN);
+ Label label8 = new Label();
+ methodVisitor.visitLabel(label8);
+ methodVisitor.visitLocalVariable("this", "Ljava/time/Duration;", null, label0, label8, 0);
+ methodVisitor.visitLocalVariable("tempSeconds", "J", null, label1, label8, 1);
+ methodVisitor.visitLocalVariable("tempNanos", "J", null, label2, label8, 3);
+ methodVisitor.visitLocalVariable("millis", "J", null, label6, label8, 5);
+ methodVisitor.visitMaxs(6, 7);
+ methodVisitor.visitEnd();
+ }
+ classWriter.visitEnd();
+
+ return classWriter.toByteArray();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
index 8df7620..3409cfd 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/RetargetOverrideTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.time.Instant;
@@ -41,6 +42,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
String stdout =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(RetargetOverrideTest.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.setMinApi(parameters.getApiLevel())
@@ -61,6 +63,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
String stdout =
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addKeepMainRule(Executor.class)
.addInnerClasses(RetargetOverrideTest.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SimpleStreamTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SimpleStreamTest.java
index aec1045..60fb964 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SimpleStreamTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SimpleStreamTest.java
@@ -5,6 +5,8 @@
package com.android.tools.r8.desugar.desugaredlibrary;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.util.ArrayList;
@@ -38,6 +40,7 @@
public void testStreamD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(SimpleStreamTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -55,6 +58,7 @@
public void testStreamR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(SimpleStreamTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepClassAndMembersRules(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SpliteratorTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SpliteratorTest.java
index 5af29c3..738d9d4 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SpliteratorTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SpliteratorTest.java
@@ -7,6 +7,8 @@
import static junit.framework.TestCase.assertTrue;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.ArrayList;
@@ -49,6 +51,7 @@
public void testSpliterator() throws Exception {
Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(SpliteratorTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/StaticInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/StaticInterfaceMethodTest.java
index c9b2a93..9c06716 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/StaticInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/StaticInterfaceMethodTest.java
@@ -7,6 +7,8 @@
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
@@ -50,6 +52,7 @@
}
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(StaticInterfaceMethodTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -109,6 +112,7 @@
Assume.assumeFalse(parameters.isCfRuntime());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addKeepMainRule(Executor.class)
.addInnerClasses(StaticInterfaceMethodTest.class)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SynchronizedCollectionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SynchronizedCollectionTest.java
index 27a8590..feaa98a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SynchronizedCollectionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/SynchronizedCollectionTest.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
-import com.android.tools.r8.TestShrinkerBuilder;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -59,6 +58,7 @@
}
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(INPUT_JAR)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -79,6 +79,7 @@
Assume.assumeFalse(parameters.isCfRuntime());
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(INPUT_JAR)
.addKeepMainRule(MAIN_CLASS)
.setMinApi(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionTest.java
index dc13cb2..3a864c2 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/APIConversionTest.java
@@ -7,6 +7,7 @@
import static org.hamcrest.core.StringContains.containsString;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -30,7 +31,7 @@
private static final AndroidApiLevel MIN_SUPPORTED = AndroidApiLevel.N;
private static final String EXPECTED_RESULT =
- StringUtils.lines("[5, 6, 7]", "j$.wrappers.$r8$wrapper$java$util$stream$IntStream$-V-WRP");
+ StringUtils.lines("[5, 6, 7]", "j$.util.stream.IntStream$VivifiedWrapper");
@Parameters(name = "{0}, shrinkDesugaredLibrary: {1}")
public static List<Object[]> data() {
@@ -63,6 +64,7 @@
public void testAPIConversionDesugaringD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(APIConversionTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AllOptionalConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AllOptionalConversionTest.java
index 75d46fe..e301fd1 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AllOptionalConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AllOptionalConversionTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -64,6 +65,7 @@
public void testRewrittenAPICallsD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
@@ -83,6 +85,7 @@
public void testRewrittenAPICallsR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(Executor.class)
.addProgramClasses(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AllTimeConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AllTimeConversionTest.java
index 5a03f73..1d79e26 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AllTimeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/AllTimeConversionTest.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.TestDiagnosticMessages;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -71,6 +72,7 @@
public void testRewrittenAPICallsD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
@@ -92,6 +94,7 @@
public void testRewrittenAPICallsR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(Executor.class)
.addProgramClasses(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicLongDoubleConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicLongDoubleConversionTest.java
index 4ac3ccc..3c0ad88 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicLongDoubleConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/BasicLongDoubleConversionTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -57,6 +58,7 @@
public void testRewrittenAPICallsD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
@@ -76,6 +78,7 @@
public void testRewrittenAPICallsR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addKeepMainRule(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
index e23e86d..bf148dc 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/CallBackConversionTest.java
@@ -7,7 +7,9 @@
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertTrue;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration.AbsentKeepRuleConsumer;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -87,6 +89,7 @@
public void testCallBack() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Impl.class)
.addLibraryClasses(CustomLibClass.class)
@@ -108,6 +111,7 @@
// Use D8 to desugar with Java classfile output.
Path firstJar =
testForD8(Backend.CF)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Impl.class)
.addLibraryClasses(CustomLibClass.class)
@@ -127,6 +131,7 @@
// Use D8 to desugar with Java classfile output.
Path secondJar =
testForD8(Backend.CF)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addOptionsModification(
options -> options.desugarSpecificOptions().allowAllDesugaredInput = true)
.setMinApi(parameters.getApiLevel())
@@ -147,6 +152,7 @@
// Convert to DEX without desugaring and run.
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(firstJar)
.setMinApi(parameters.getApiLevel())
.disableDesugaring()
@@ -167,6 +173,7 @@
public void testCallBackR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addKeepMainRule(Impl.class)
.noMinification()
.setMinApi(parameters.getApiLevel())
@@ -185,6 +192,7 @@
public void testCallBackR8Minifying() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addKeepMainRule(Impl.class)
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Impl.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ClockAPIConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ClockAPIConversionTest.java
index 382f55d..37ed786 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ClockAPIConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ClockAPIConversionTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -52,6 +53,7 @@
public void testClockD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
@@ -72,6 +74,7 @@
public void testClockR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addKeepMainRule(Executor.class)
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionAndMergeTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionAndMergeTest.java
index ef584d2..e2b5c8b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionAndMergeTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionAndMergeTest.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
@@ -37,6 +38,7 @@
Path extra = buildClass(ExtraClass.class);
Path convClass = buildClass(APIConversionClass.class);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramFiles(extra, convClass)
.enableCoreLibraryDesugaring(parameters.getApiLevel())
@@ -48,6 +50,7 @@
private Path buildClass(Class<?> cls) throws Exception {
return testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(cls)
.enableCoreLibraryDesugaring(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionErrorMessageTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionErrorMessageTest.java
index bdd9f5d..3976a4f 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionErrorMessageTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionErrorMessageTest.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
@@ -75,6 +76,7 @@
// NoSuchMethodError instead of NoClassDefFoundError on the wrapper.
Assume.assumeTrue(hasRequiredAPI());
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(Executor.class, MyIntUnaryOperator.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
index 5cd8c8d..9264433 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/ConversionIntroduceInterfaceMethodTest.java
@@ -9,6 +9,7 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -79,6 +80,7 @@
public void testNoInterfaceMethodsD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(MyCollectionInterface.class, MyCollection.class, Executor.class)
.addLibraryClasses(CustomLibClass.class)
@@ -142,6 +144,7 @@
public void testNoInterfaceMethodsR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(MyCollectionInterface.class, MyCollection.class, Executor.class)
.addKeepMainRule(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
index 9a251a9..160726b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIDesugaredLibTest.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.DexRuntime;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -54,6 +55,7 @@
.writeToZip();
String stdOut =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(AndroidApiLevel.B)
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIProgramTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIProgramTest.java
index a96a874..38b7c3f 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIProgramTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/DuplicateAPIProgramTest.java
@@ -7,6 +7,7 @@
import static junit.framework.TestCase.assertEquals;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -56,6 +57,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
String stdOut =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class, MyMap.class)
.addLibraryClasses(CustomLibClass.class)
@@ -79,6 +81,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
String stdOut =
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(Executor.class)
.addProgramClasses(Executor.class, MyMap.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
index 24588c6..5800cf5 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/FunctionConversionTest.java
@@ -7,6 +7,7 @@
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -64,6 +65,7 @@
public void testFunctionCompositionD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(
Executor.class, Executor.Object1.class, Executor.Object2.class, Executor.Object3.class)
@@ -86,6 +88,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
Path jar =
testForD8(Backend.CF)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(
Executor.class,
@@ -131,12 +134,14 @@
public void testFunctionCompositionR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(Executor.class)
.addProgramClasses(
Executor.class, Executor.Object1.class, Executor.Object2.class, Executor.Object3.class)
.addLibraryClasses(CustomLibClass.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
+ .allowStdoutMessages()
.compile()
.addDesugaredCoreLibraryRunClassPath(
this::buildDesugaredLibrary,
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/MoreFunctionConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/MoreFunctionConversionTest.java
index 10823c3..ba7f28d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/MoreFunctionConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/MoreFunctionConversionTest.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -60,6 +61,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
D8TestCompileResult compileResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
@@ -82,6 +84,7 @@
public void testFunctionR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addKeepMainRule(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/SummaryStatisticsConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/SummaryStatisticsConversionTest.java
index 7fe00d5..4d5f8d1 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/SummaryStatisticsConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/SummaryStatisticsConversionTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -68,6 +69,7 @@
public void testStatsD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
@@ -87,6 +89,7 @@
public void testStatsR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addKeepMainRule(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/SuperAPIConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/SuperAPIConversionTest.java
index d4e1c8f..958e8b4 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/SuperAPIConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/SuperAPIConversionTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -50,6 +51,7 @@
Assume.assumeFalse("TODO(b/189435770): fix", shrinkDesugaredLibrary);
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(SuperAPIConversionTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -60,7 +62,7 @@
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.run(parameters.getRuntime(), Executor.class)
- .assertSuccessWithOutputLines("$r8$wrapper$java$util$stream$IntStream$-V-WRP");
+ .assertSuccessWithOutputLines("IntStream$VivifiedWrapper");
}
@Test
@@ -68,6 +70,7 @@
Assume.assumeFalse("TODO(b/189435770): fix", shrinkDesugaredLibrary);
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(SuperAPIConversionTest.class)
.setMinApi(parameters.getApiLevel())
.addKeepMainRule(Executor.class)
@@ -79,7 +82,7 @@
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.run(parameters.getRuntime(), Executor.class)
- .assertSuccessWithOutputLines("$r8$wrapper$java$util$stream$IntStream$-V-WRP");
+ .assertSuccessWithOutputLines("IntStream$VivifiedWrapper");
}
static class ParallelRandom extends Random {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
index 4dbcccb..b7c33c4 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/TryCatchTimeConversionTest.java
@@ -5,8 +5,8 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
-import com.android.tools.r8.desugar.desugaredlibrary.conversiontests.SummaryStatisticsConversionTest.CustomLibClass;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -75,6 +75,7 @@
public void testBaselineR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(BaselineExecutor.class)
.addKeepMainRule(BaselineExecutor.class)
@@ -114,6 +115,7 @@
public void testTryCatchR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(TryCatchExecutor.class)
.addKeepMainRule(TryCatchExecutor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/UnwrapConversionTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/UnwrapConversionTest.java
index 2f10f3a..ed2db6a 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/UnwrapConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/UnwrapConversionTest.java
@@ -5,8 +5,8 @@
package com.android.tools.r8.desugar.desugaredlibrary.conversiontests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
-import com.android.tools.r8.desugar.desugaredlibrary.conversiontests.SummaryStatisticsConversionTest.CustomLibClass;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
@@ -54,6 +54,7 @@
public void testUnwrapD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addLibraryClasses(CustomLibClass.class)
@@ -73,6 +74,7 @@
public void testUnwrapR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Executor.class)
.addKeepMainRule(Executor.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperPlacementTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperPlacementTest.java
index cbab10c..c4d1f98 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperPlacementTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/conversiontests/WrapperPlacementTest.java
@@ -10,8 +10,9 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
-import com.android.tools.r8.ir.desugar.DesugaredLibraryWrapperSynthesizer;
+import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.testing.AndroidBuildVersion;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
@@ -61,6 +62,7 @@
Path path1 = compileWithCoreLibraryDesugaring(MyArrays1.class);
Path path2 = compileWithCoreLibraryDesugaring(MyArrays2.class);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(TestClass.class)
.addAndroidBuildVersion()
.enableCoreLibraryDesugaring(parameters.getApiLevel())
@@ -83,6 +85,7 @@
private Path compileWithCoreLibraryDesugaring(Class<?> clazz) throws Exception {
return testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClassesAndInnerClasses(clazz)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
@@ -108,8 +111,7 @@
private Stream<FoundClassSubject> getWrappers(CodeInspector inspector) {
return inspector.allClasses().stream()
- .filter(
- c -> c.getOriginalName().contains(DesugaredLibraryWrapperSynthesizer.WRAPPER_PREFIX));
+ .filter(c -> SyntheticItemsTestUtils.isWrapper(c.getOriginalReference()));
}
static class MyArrays1 {
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/ConcurrentHashMapFileSerializationTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/ConcurrentHashMapFileSerializationTest.java
index db361d4..5c1e73d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/ConcurrentHashMapFileSerializationTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/ConcurrentHashMapFileSerializationTest.java
@@ -5,8 +5,10 @@
package com.android.tools.r8.desugar.desugaredlibrary.gson;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.io.File;
@@ -52,6 +54,7 @@
public void testMapSerializationD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(ConcurrentHashMapFileSerializationTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -71,6 +74,7 @@
public void testMapSerializationR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(ConcurrentHashMapFileSerializationTest.class)
.addKeepMainRule(Executor.class)
.noMinification()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GetGenericInterfaceTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GetGenericInterfaceTest.java
index 70dab5d..fd1b30b 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GetGenericInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GetGenericInterfaceTest.java
@@ -8,6 +8,7 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -52,6 +53,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
String stdOut =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(GetGenericInterfaceTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -72,6 +74,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
String stdOut =
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(GetGenericInterfaceTest.class)
.addKeepMainRule(Executor.class)
.noMinification()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonAllMapsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonAllMapsTest.java
index d5a6637..a6a460d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonAllMapsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonAllMapsTest.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.desugar.desugaredlibrary.gson;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.util.List;
import org.junit.Assume;
@@ -38,6 +40,7 @@
Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClassesAndInnerClasses(AllMapsTestClass.class)
.addProgramFiles(GSON_2_8_1_JAR)
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -57,6 +60,7 @@
Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClassesAndInnerClasses(AllMapsTestClass.class)
.addProgramFiles(GSON_2_8_1_JAR)
.addKeepMainRule(AllMapsTestClass.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonEnumTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonEnumTest.java
index d71b536..584c3f3 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonEnumTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonEnumTest.java
@@ -5,7 +5,9 @@
package com.android.tools.r8.desugar.desugaredlibrary.gson;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.lang.reflect.Field;
import java.time.chrono.IsoEra;
@@ -36,6 +38,7 @@
public void testCustomCollectionD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(GsonEnumTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -53,6 +56,7 @@
public void testCustomCollectionR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(GsonEnumTest.class)
.addKeepMainRule(Executor.class)
.noMinification()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonOptionalTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonOptionalTest.java
index 62cf8d2..39c6644 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonOptionalTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/GsonOptionalTest.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.desugar.desugaredlibrary.gson;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import java.util.List;
import org.junit.Assume;
@@ -32,6 +34,7 @@
Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClassesAndInnerClasses(OptionalTestClass.class)
.addProgramFiles(GSON_2_8_1_JAR)
.addOptionsModification(opt -> opt.ignoreMissingClasses = true)
@@ -52,6 +55,7 @@
Assume.assumeTrue(requiresEmulatedInterfaceCoreLibDesugaring(parameters));
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClassesAndInnerClasses(OptionalTestClass.class)
.addProgramFiles(GSON_2_8_1_JAR)
.addKeepMainRule(OptionalTestClass.class)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/MyMapFileSerializationTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/MyMapFileSerializationTest.java
index 42844c1..01c1b44 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/MyMapFileSerializationTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/gson/MyMapFileSerializationTest.java
@@ -5,8 +5,10 @@
package com.android.tools.r8.desugar.desugaredlibrary.gson;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.io.File;
@@ -50,6 +52,7 @@
public void testMapSerializationD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(MyMapFileSerializationTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
@@ -69,6 +72,7 @@
public void testMapSerializationR8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForR8(Backend.DEX)
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(MyMapFileSerializationTest.class)
.addKeepMainRule(Executor.class)
.noMinification()
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11AtomicTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11AtomicTests.java
index 03995ac..e1849dc 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11AtomicTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11AtomicTests.java
@@ -76,6 +76,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
String verbosity = "2";
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(
ATOMIC_COMPILED_TESTS_FOLDER.resolve(ATOMIC_REFERENCE_TEST + CLASS_EXTENSION))
.addProgramFiles(testNGSupportProgramFiles())
@@ -99,6 +100,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
String verbosity = "2";
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(
getAllFilesWithSuffixInDirectory(ATOMIC_COMPILED_TESTS_FOLDER, CLASS_EXTENSION))
.addProgramFiles(testNGSupportProgramFiles())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentMapTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentMapTests.java
index 7d0fc6b..9123915 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentMapTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11ConcurrentMapTests.java
@@ -163,6 +163,7 @@
String verbosity = "2";
D8TestCompileResult d8TestCompileResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(concurrentHashTestToCompile())
.addProgramFiles(testNGSupportProgramFiles())
.addProgramFiles(getPathsFiles())
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeTests.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeTests.java
index 6288598..c8ddd5d 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeTests.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdktests/Jdk11TimeTests.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.D8TestCompileResult;
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -137,6 +138,7 @@
String verbosity = "2";
D8TestCompileResult compileResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(getPathsFiles())
.addProgramFiles(Paths.get(JDK_TESTS_BUILD_DIR + "jdk11TimeTests.jar"))
.addProgramFiles(Paths.get(JDK_TESTS_BUILD_DIR + "testng-6.10.jar"))
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
index 55e2905..c7fc371 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/kotlin/KotlinMetadataTest.java
@@ -27,6 +27,7 @@
import com.android.tools.r8.kotlin.KotlinMetadataWriter;
import com.android.tools.r8.kotlin.metadata.KotlinMetadataTestBase;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
@@ -94,6 +95,7 @@
final File output = temp.newFile("output.zip");
final D8TestRunResult d8TestRunResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(compiledJars.getForConfiguration(kotlinParameters))
.addProgramFiles(ToolHelper.getKotlinStdlibJar(kotlinParameters.getCompiler()))
.addProgramFiles(ToolHelper.getKotlinReflectJar(kotlinParameters.getCompiler()))
@@ -123,6 +125,7 @@
boolean desugarLibrary = parameters.isDexRuntime() && requiresAnyCoreLibDesugaring(parameters);
final R8FullTestBuilder testBuilder =
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramFiles(compiledJars.getForConfiguration(kotlinParameters))
.addProgramFiles(ToolHelper.getKotlinStdlibJar(kotlinParameters.getCompiler()))
.addProgramFiles(ToolHelper.getKotlinReflectJar(kotlinParameters.getCompiler()))
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/HelloWorldCompiledOnArtTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/HelloWorldCompiledOnArtTest.java
index cd8ec64..537b873 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/HelloWorldCompiledOnArtTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/r8ondex/HelloWorldCompiledOnArtTest.java
@@ -128,6 +128,7 @@
}
D8TestCompileResult compile =
d8TestBuilder
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel())
.addOptionsModification(opt -> opt.testing.trackDesugaredAPIConversions = true)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/EnumSetTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/EnumSetTest.java
index 454adc7..bdc2b91 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/EnumSetTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/EnumSetTest.java
@@ -5,7 +5,9 @@
package com.android.tools.r8.desugar.desugaredlibrary.shrinkingtests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import java.time.DayOfWeek;
@@ -39,6 +41,7 @@
public void testEnum() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(EnumSetUser.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/FieldAccessTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/FieldAccessTest.java
index aabd492..2b57223 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/FieldAccessTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/FieldAccessTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary.shrinkingtests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -37,6 +38,7 @@
public void testField() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(Executor.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/InheritanceTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/InheritanceTest.java
index 5d9e5e7..f314581 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/InheritanceTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/InheritanceTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.desugar.desugaredlibrary.shrinkingtests;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -39,6 +40,7 @@
public void testInheritance() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(Impl.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/KeepRuleShrinkTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/KeepRuleShrinkTest.java
index 391cd8d..fa6a0c6 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/KeepRuleShrinkTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/shrinkingtests/KeepRuleShrinkTest.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.D8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
@@ -41,6 +42,7 @@
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
D8TestRunResult d8TestRunResult =
testForD8()
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addInnerClasses(KeepRuleShrinkTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
index 8bec281..30dc93f 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/MethodParametersTest.java
@@ -4,8 +4,9 @@
package com.android.tools.r8.desugar.nestaccesscontrol;
import static com.android.tools.r8.TestRuntime.getCheckedInJdk11;
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
@@ -13,7 +14,11 @@
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.desugar.nestaccesscontrol.methodparameters.Outer;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import java.nio.file.Path;
+import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -51,6 +56,8 @@
.addProgramFiles(nestCompiledWithParameters)
.setMinApi(parameters.getApiLevel())
.compile()
+ .assertNoMessages()
+ .inspect(this::verifyNoAnnotationsOnSyntheticConstructors)
.writeToZip();
Path nestDesugaredTwice =
@@ -58,12 +65,8 @@
.addProgramFiles(nestDesugared)
.setMinApi(parameters.getApiLevel())
.compile()
- // TODO(b/189743726): These warnings should not be there.
- .assertAtLeastOneInfoMessage()
- .assertAllInfoMessagesMatch(
- anyOf(
- containsString("Invalid parameter counts in MethodParameter attributes"),
- containsString("Methods with invalid MethodParameter attributes")))
+ .assertNoMessages()
+ .inspect(this::verifyNoAnnotationsOnSyntheticConstructors)
.writeToZip();
Path programDesugared =
@@ -72,6 +75,7 @@
.addInnerClasses(getClass())
.setMinApi(parameters.getApiLevel())
.compile()
+ .assertNoMessages()
.writeToZip();
testForD8(parameters.getBackend())
@@ -79,16 +83,47 @@
.addProgramFiles(programDesugared)
.setMinApi(parameters.getApiLevel())
.compile()
- // TODO(b/189743726): These warnings should not be there.
- .assertAtLeastOneInfoMessage()
- .assertAllInfoMessagesMatch(
- anyOf(
- containsString("Invalid parameter counts in MethodParameter attributes"),
- containsString("Methods with invalid MethodParameter attributes")))
+ .assertNoMessages()
+ .inspect(this::verifyNoAnnotationsOnSyntheticConstructors)
.run(parameters.getRuntime(), TestRunner.class)
- // TODO(b/189743726): Should not fail at runtime.
- .assertFailureWithErrorThatMatches(
- containsString("Wrong number of parameters in MethodParameters attribute"));
+ // Order of constructors is different on dex due to sorting.
+ .applyIf(
+ parameters.isCfRuntime(),
+ result ->
+ result.assertSuccessWithOutputLines(
+ "int, int, Outer$Inner-IA, 3",
+ "int, Outer$Inner-IA, 2",
+ "Outer$Inner-IA, 1",
+ "int, int, 2",
+ "int, 1",
+ "0"),
+ result ->
+ result.assertSuccessWithOutputLines(
+ "0",
+ "int, 1",
+ "int, int, 2",
+ "int, int, Outer$Inner-IA, 3",
+ "int, Outer$Inner-IA, 2",
+ "Outer$Inner-IA, 1"));
+ }
+
+ @Test
+ public void testJavacBridges() throws Exception {
+ assumeTrue(parameters.useRuntimeAsNoneRuntime());
+ verifyNoAnnotationsOnSyntheticConstructors(
+ new CodeInspector(ToolHelper.getClassFileForTestClass(Outer.Inner.class)));
+ }
+
+ private void verifyNoAnnotationsOnSyntheticConstructors(CodeInspector inspector) {
+ ClassSubject innerClassSubject = inspector.clazz(Outer.Inner.class);
+ List<FoundMethodSubject> syntheticInitializers =
+ innerClassSubject.allMethods(
+ method -> method.isInstanceInitializer() && method.isSynthetic());
+ assertEquals(3, syntheticInitializers.size());
+ syntheticInitializers.forEach(
+ syntheticInitializer ->
+ assertTrue(
+ syntheticInitializer.getProgramMethod().getDefinition().annotations().isEmpty()));
}
static class TestRunner {
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestPrivateInterfaceMethodsTest.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestPrivateInterfaceMethodsTest.java
new file mode 100644
index 0000000..ae2b6ae
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/NestPrivateInterfaceMethodsTest.java
@@ -0,0 +1,78 @@
+// Copyright (c) 2021, 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.nestaccesscontrol;
+
+import com.android.tools.r8.DesugarTestConfiguration;
+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.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class NestPrivateInterfaceMethodsTest extends TestBase {
+
+ static final String EXPECTED = StringUtils.lines("Hello world!");
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public NestPrivateInterfaceMethodsTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ private byte[] getClassWithNest(Class<?> clazz) throws Exception {
+ return transformer(clazz)
+ .setNest(I.class, J.class)
+ .setAccessFlags(
+ I.class.getMethod("foo"),
+ flags -> {
+ flags.unsetPublic();
+ flags.setPrivate();
+ })
+ .transform();
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForDesugaring(parameters)
+ .addProgramClasses(TestClass.class)
+ .addProgramClassFileData(getClassWithNest(I.class), getClassWithNest(J.class))
+ .run(parameters.getRuntime(), TestClass.class)
+ // TODO(191115349): Nest desugar does not downgrade the classfile version.
+ .applyIf(
+ c ->
+ DesugarTestConfiguration.isNotJavac(c)
+ || parameters.getRuntime().asCf().isNewerThanOrEqual(CfVm.JDK11),
+ r -> r.assertSuccessWithOutput(EXPECTED),
+ r -> r.assertFailureWithErrorThatThrows(UnsupportedClassVersionError.class));
+ }
+
+ interface I {
+ default /* will be private */ void foo() {
+ System.out.println("Hello world!");
+ }
+ }
+
+ interface J {
+ default void bar(I o) {
+ o.foo();
+ }
+ }
+
+ static class TestClass implements I, J {
+
+ public static void main(String[] args) {
+ TestClass o = new TestClass();
+ o.bar(o);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/methodparameters/Outer.java b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/methodparameters/Outer.java
index 9c92994..369aff3 100644
--- a/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/methodparameters/Outer.java
+++ b/src/test/java/com/android/tools/r8/desugar/nestaccesscontrol/methodparameters/Outer.java
@@ -3,21 +3,37 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.desugar.nestaccesscontrol.methodparameters;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Parameter;
public class Outer {
public static class Inner {
+ @MyAnnotation
private Inner() {
for (Constructor<?> constructor : getClass().getDeclaredConstructors()) {
+ for (Parameter parameter : constructor.getParameters()) {
+ System.out.print(parameter.getType().getSimpleName());
+ System.out.print(", ");
+ }
System.out.println(constructor.getParameters().length);
}
}
+ @MyAnnotation
private Inner(int a) {}
+ @MyAnnotation
private Inner(int a, int b) {}
}
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.CONSTRUCTOR)
+ @interface MyAnnotation {}
+
public static Inner callPrivateInnerConstructorZeroArgs() {
return new Inner();
}
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeV1612Test.java b/src/test/java/com/android/tools/r8/internal/YouTubeV1612Test.java
index f2fe2b8..830d6fc 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeV1612Test.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeV1612Test.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.L8TestCompileResult;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration.PresentKeepRuleConsumer;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.ResourceException;
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeV1620Test.java b/src/test/java/com/android/tools/r8/internal/YouTubeV1620Test.java
index c1182bd..0b76040 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeV1620Test.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeV1620Test.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.L8TestCompileResult;
+import com.android.tools.r8.LibraryDesugaringTestConfiguration.PresentKeepRuleConsumer;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8TestCompileResult;
import com.android.tools.r8.ResourceException;
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
index 455c5c2..5e79870 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/GenerateBackportMethods.java
@@ -75,7 +75,7 @@
@Override
protected int getYear() {
- return 2020;
+ return 2021;
}
private static CfInstruction rewriteToJava9API(
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethods.java
index 97e896e..566d8f2 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethods.java
@@ -71,6 +71,18 @@
return obj;
}
+ public static <T> T requireNonNullSupplier(T obj, Supplier<String> messageSupplier) {
+ if (obj == null) {
+ // While calling `messageSupplier.get()` unconditionally would produce the correct behavior,
+ // some ART versions add an exception message to seemingly-unintended null dereferences along
+ // the lines of "Attempted to invoke interface method Supplier.get() on a null reference"
+ // which we don't want to expose as the reference implementation has a null message.
+ String message = messageSupplier != null ? messageSupplier.get() : null;
+ throw new NullPointerException(message);
+ }
+ return obj;
+ }
+
public static <T> T requireNonNullElse(T obj, T defaultObj) {
if (obj != null) return obj;
return Objects.requireNonNull(defaultObj, "defaultObj");
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineMethodWithRetargetedLibMemberTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineMethodWithRetargetedLibMemberTest.java
index 415a868..70c10da 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineMethodWithRetargetedLibMemberTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineMethodWithRetargetedLibMemberTest.java
@@ -11,6 +11,8 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,6 +36,7 @@
@Test
public void test() throws Exception {
testForR8(parameters.getBackend())
+ .addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.P))
.addProgramClasses(TestClass.class)
.addKeepMainRule(TestClass.class)
.enableCoreLibraryDesugaring(parameters.getApiLevel())
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/NopInliningConstraintTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/NopInliningConstraintTest.java
new file mode 100644
index 0000000..3295203
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/conditionalsimpleinlining/NopInliningConstraintTest.java
@@ -0,0 +1,108 @@
+// Copyright (c) 2021, 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.ir.optimize.inliner.conditionalsimpleinlining;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.AlwaysInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+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;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class NopInliningConstraintTest extends TestBase {
+
+ @Parameter public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .enableAlwaysInliningAnnotations()
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(
+ inspector -> {
+ ClassSubject mainClassSubject = inspector.clazz(Main.class);
+ assertThat(mainClassSubject, isPresent());
+
+ // Method doStuff() is inlined into main().
+ assertThat(mainClassSubject.uniqueMethodWithName("doStuff"), isAbsent());
+
+ // Method checkNotNull() is not inlined.
+ MethodSubject checkNotNullMethodSubject =
+ mainClassSubject.uniqueMethodWithName("checkNotNull");
+ assertThat(checkNotNullMethodSubject, isPresent());
+
+ // There is a single call to checkNotNull() in main(), as checkNotNull(newObject())
+ // is dead code eliminated.
+ assertEquals(
+ 1,
+ mainClassSubject
+ .mainMethod()
+ .streamInstructions()
+ .filter(CodeMatchers.isInvokeWithTarget(checkNotNullMethodSubject))
+ .count());
+ })
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(
+ "Caught NPE: Parameter specified as non-null is null: method "
+ + Main.class.getTypeName()
+ + ".main, parameter o");
+ }
+
+ static class Main {
+ public static void main(String[] args) {
+ doStuff(new Object());
+ try {
+ doStuff(null);
+ } catch (NullPointerException e) {
+ System.out.println("Caught NPE: " + e.getMessage());
+ }
+ }
+
+ @AlwaysInline
+ static void doStuff(Object o) {
+ checkNotNull(o, "o");
+ }
+
+ @NeverInline
+ static void checkNotNull(Object o, String parameterName) {
+ if (o != null) {
+ return;
+ }
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ int callerStackTraceElementIndex =
+ stackTrace[0].getMethodName().equals("getThreadStackTrace") ? 3 : 2;
+ StackTraceElement callerStackTraceElement = stackTrace[callerStackTraceElementIndex];
+ throw new NullPointerException(
+ "Parameter specified as non-null is null: method "
+ + callerStackTraceElement.getClassName()
+ + "."
+ + callerStackTraceElement.getMethodName()
+ + ", parameter "
+ + parameterName);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/KotlinIntrinsicsInlineTest.java b/src/test/java/com/android/tools/r8/kotlin/KotlinIntrinsicsInlineTest.java
index 872b5f0..f6cc385 100644
--- a/src/test/java/com/android/tools/r8/kotlin/KotlinIntrinsicsInlineTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/KotlinIntrinsicsInlineTest.java
@@ -130,10 +130,10 @@
MethodSubject method = main.uniqueMethodWithName(methodName);
assertThat(method, isPresent());
int arity = method.getMethod().getReference().getArity();
- // One from the method's own argument, if any, and
- // Two from Array utils, `contains` and `indexOf`, if inlined with access relaxation.
+ // One for each of the method's own arguments, unless building with
+ // -allowaccessmodification.
assertEquals(
- allowAccessModification ? 0 : arity + 2,
+ allowAccessModification ? 0 : arity,
countCall(method, "checkParameterIsNotNull"));
});
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java b/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
index 4769427..e83626b 100644
--- a/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/SimplifyIfNotNullKotlinTest.java
@@ -91,7 +91,7 @@
// ?: in aOrDefault
// TODO(b/179951729): Not the same amount of ifz on CF and DEX.
assertEquals(testParameters.isCfRuntime() ? 0 : 1, ifzCount);
- assertEquals(allowAccessModification ? 0 : 1, paramNullCheckCount);
+ assertEquals(0, paramNullCheckCount);
});
}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexRemovedAnnotationTest.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexRemovedAnnotationTest.java
index 67b113c..589a1e2 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexRemovedAnnotationTest.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexRemovedAnnotationTest.java
@@ -13,6 +13,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.codeinspector.ClassSubject;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -43,7 +44,7 @@
@Test
public void testMainDexTracing() throws Exception {
testForR8(parameters.getBackend())
- .addProgramClasses(MainDex.class, Inside.class, Main.class)
+ .addProgramClasses(MainDex.class, Inside.class, Dead.class, Main.class)
.addKeepClassAndMembersRules(Main.class)
.setMinApi(parameters.getApiLevel())
.enableInliningAnnotations()
@@ -51,13 +52,11 @@
.collectMainDexClasses()
.compile()
.inspectMainDexClasses(
- mainDexClasses -> {
- // TODO(b/190623364): Should not be empty.
- assertTrue(mainDexClasses.isEmpty());
- })
- .inspect(
- codeInspector -> {
- assertThat(codeInspector.clazz(MainDex.class), not(isPresent()));
+ (inspector, mainDexClasses) -> {
+ ClassSubject inside = inspector.clazz(Inside.class);
+ assertThat(inside, isPresent());
+ assertTrue(mainDexClasses.contains(inside.getFinalName()));
+ assertThat(inspector.clazz(MainDex.class), not(isPresent()));
})
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines("Hello World!");
@@ -76,6 +75,11 @@
}
}
+ @MainDex
+ public static class Dead {
+ // Will be removed during first round of tree-pruning.
+ }
+
public static class Main {
public static void main(String[] args) {
diff --git a/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByReferenceInAnnotationTest.java b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByReferenceInAnnotationTest.java
new file mode 100644
index 0000000..137706a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/keptgraph/KeptByReferenceInAnnotationTest.java
@@ -0,0 +1,103 @@
+// 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.shaking.keptgraph;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.MethodReferenceUtils;
+import com.android.tools.r8.utils.graphinspector.GraphInspector.QueryNode;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+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 KeptByReferenceInAnnotationTest extends TestBase {
+
+ @Parameter public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(getClass())
+ .addKeepMainRule(Main.class)
+ .addKeepRuntimeVisibleAnnotations()
+ .enableGraphInspector()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspectGraph(
+ inspector -> {
+ QueryNode keepMainMethodRule = inspector.rule(Origin.unknown(), 1, 1).assertRoot();
+
+ QueryNode mainClassNode =
+ inspector
+ .clazz(Main.class)
+ .assertPresent()
+ .assertNotRenamed()
+ .assertKeptBy(keepMainMethodRule);
+
+ // The main() method is kept by the -keep rule.
+ QueryNode mainMethodNode =
+ inspector
+ .method(MethodReferenceUtils.mainMethod(Main.class))
+ .assertPresent()
+ .assertNotRenamed()
+ .assertKeptBy(keepMainMethodRule);
+
+ // MyAnnotation is referenced from main() and is also used to annotate class Main.
+ QueryNode annotationNode =
+ inspector
+ .clazz(MyAnnotation.class)
+ .assertPresent()
+ .assertRenamed()
+ .assertKeptBy(mainMethodNode);
+ annotationNode.assertKeptByReferenceInAnnotationOn(annotationNode, mainClassNode);
+
+ // ReferencedInAnnotation is referenced from inside the annotation on class Main.
+ inspector
+ .clazz(ReferencedInAnnotation.class)
+ .assertPresent()
+ .assertRenamed()
+ .assertKeptByReferenceInAnnotationOn(annotationNode, mainClassNode);
+
+ // Check the presence of an edge from main() to the annotation node.
+ inspector
+ .annotation(MyAnnotation.class, mainClassNode)
+ .assertPresent()
+ .assertKeptByAnnotationOn(mainClassNode);
+ })
+ .run(parameters.getRuntime(), Main.class)
+ .apply(
+ result ->
+ result.assertSuccessWithOutputLines(
+ result.inspector().clazz(ReferencedInAnnotation.class).getFinalName()));
+ }
+
+ @MyAnnotation(ReferencedInAnnotation.class)
+ static class Main {
+
+ public static void main(String[] args) {
+ MyAnnotation annotation = Main.class.getAnnotation(MyAnnotation.class);
+ System.out.println(annotation.value().getName());
+ }
+ }
+
+ static class ReferencedInAnnotation {}
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface MyAnnotation {
+
+ Class<?> value();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
index 9e49bc9..dfcf7e8 100644
--- a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
+++ b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
@@ -117,6 +117,11 @@
reference, null, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_3);
}
+ public static boolean isWrapper(ClassReference reference) {
+ return SyntheticNaming.isSynthetic(reference, null, SyntheticKind.WRAPPER)
+ || SyntheticNaming.isSynthetic(reference, null, SyntheticKind.VIVIFIED_WRAPPER);
+ }
+
public static Matcher<String> containsInternalSyntheticReference() {
return containsString(SyntheticNaming.getPhaseSeparator(Phase.INTERNAL));
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
index 4ac4f95..1114bce 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundClassSubject.java
@@ -538,6 +538,7 @@
codeInspector.getFactory().kotlin, annotationSubject.getAnnotation());
}
+ @Override
public RetraceClassResult retrace() {
assertTrue(mapping.getNaming() != null);
return codeInspector
@@ -545,6 +546,7 @@
.retraceClass(Reference.classFromTypeName(mapping.getNaming().renamedName));
}
+ @Override
public RetraceClassElement retraceUnique() {
RetraceClassResult result = retrace();
if (result.isAmbiguous()) {
diff --git a/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java b/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java
index e51c162..45ffbf2 100644
--- a/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/graphinspector/GraphInspector.java
@@ -26,10 +26,12 @@
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
import com.android.tools.r8.shaking.CollectingGraphConsumer;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.ImmutableSet;
+import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -53,6 +55,10 @@
new EdgeKindPredicate(EdgeKind.ReflectiveUseFrom);
public static final EdgeKindPredicate isLibraryMethod =
new EdgeKindPredicate(EdgeKind.IsLibraryMethod);
+ public static final EdgeKindPredicate isAnnotatedOn =
+ new EdgeKindPredicate(EdgeKind.AnnotatedOn);
+ public static final EdgeKindPredicate isReferencedInAnnotation =
+ new EdgeKindPredicate(EdgeKind.ReferencedInAnnotation);
public static final EdgeKindPredicate overriding =
new EdgeKindPredicate(EdgeKind.OverridingMethod);
public static final EdgeKindPredicate compatibilityRule =
@@ -148,6 +154,11 @@
public abstract boolean isPureCompatKeptBy(QueryNode node);
+ public abstract boolean isKeptByAnnotationOn(QueryNode annotatedNode);
+
+ public abstract boolean isKeptByReferenceInAnnotationOn(
+ QueryNode annotationNode, QueryNode annotatedNode);
+
public abstract boolean isKeptByLibraryMethod(QueryNode node);
public abstract boolean isSatisfiedBy(QueryNode... nodes);
@@ -274,14 +285,46 @@
if (isSatisfiedBy(nodes)) {
return this;
}
- QueryNodeImpl impl = (QueryNodeImpl) this;
+ QueryNodeImpl<?> impl = (QueryNodeImpl<?>) this;
impl.runSatisfiedBy(Assert::fail, nodes);
throw new Unreachable();
}
+ public QueryNode assertKeptByAnnotationOn(QueryNode annotatedNode) {
+ assertTrue(
+ "Invalid call to assertKeptByAnnotation with: " + annotatedNode.getNodeDescription(),
+ annotatedNode.isPresent());
+ assertTrue(
+ errorMessage(
+ "kept by annotation on " + annotatedNode.getNodeDescription(),
+ "was not kept by an annotation"),
+ isKeptByAnnotationOn(annotatedNode));
+ return this;
+ }
+
+ public QueryNode assertKeptByReferenceInAnnotationOn(
+ QueryNode annotationNode, QueryNode annotatedNode) {
+ assertTrue(
+ "Invalid call to assertKeptByAnnotation with: " + annotationNode.getNodeDescription(),
+ annotationNode.isPresent());
+ assertTrue(
+ "Invalid call to assertKeptByAnnotation with: " + annotatedNode.getNodeDescription(),
+ annotatedNode.isPresent());
+ assertTrue(
+ errorMessage(
+ "kept by annotation "
+ + annotationNode.getNodeDescription()
+ + " on "
+ + annotatedNode.getNodeDescription(),
+ "was not kept by an annotation"),
+ isKeptByReferenceInAnnotationOn(annotationNode, annotatedNode));
+ return this;
+ }
+
public QueryNode assertKeptByLibraryMethod(QueryNode node) {
assertTrue(
- "Invalid call to assertKeptBy with: " + node.getNodeDescription(), node.isPresent());
+ "Invalid call to assertKeptByLibraryMethod with: " + node.getNodeDescription(),
+ node.isPresent());
assertTrue(
errorMessage(
"kept by library method on " + node.getNodeDescription(),
@@ -376,14 +419,27 @@
}
@Override
+ public boolean isKeptByAnnotationOn(QueryNode annotatedNode) {
+ fail("Invalid call to isKeptByAnnotationOn on " + getNodeDescription());
+ throw new Unreachable();
+ }
+
+ @Override
+ public boolean isKeptByReferenceInAnnotationOn(
+ QueryNode annotationNode, QueryNode annotatedNode) {
+ fail("Invalid call to isKeptByReferenceInAnnotationOn on " + getNodeDescription());
+ throw new Unreachable();
+ }
+
+ @Override
public boolean isKeptByLibraryMethod(QueryNode node) {
- fail("Invalid call to isKeptByLibrary on " + getNodeDescription());
+ fail("Invalid call to isKeptByLibraryMethod on " + getNodeDescription());
throw new Unreachable();
}
@Override
public boolean isSatisfiedBy(QueryNode... nodes) {
- fail("Invalid call to isTriggeredBy on " + getNodeDescription());
+ fail("Invalid call to isSatisfiedBy on " + getNodeDescription());
throw new Unreachable();
}
}
@@ -391,19 +447,19 @@
// Class representing a point in the kept-graph structure.
// The purpose of this class is to tersely specify what relationships are expected between nodes,
// thus most methods will throw assertion errors if the predicate is false.
- private static class QueryNodeImpl extends QueryNode {
+ private static class QueryNodeImpl<T extends GraphNode> extends QueryNode {
private final GraphInspector inspector;
- private final GraphNode graphNode;
+ private final T graphNode;
- public QueryNodeImpl(GraphInspector inspector, GraphNode graphNode) {
+ public QueryNodeImpl(GraphInspector inspector, T graphNode) {
this.inspector = inspector;
this.graphNode = graphNode;
}
@Override
public boolean equals(Object obj) {
- return obj instanceof QueryNodeImpl && graphNode.equals(((QueryNodeImpl) obj).graphNode);
+ return obj instanceof QueryNodeImpl && graphNode.equals(((QueryNodeImpl<?>) obj).graphNode);
}
@Override
@@ -484,7 +540,7 @@
if (!(node instanceof QueryNodeImpl)) {
return false;
}
- QueryNodeImpl impl = (QueryNodeImpl) node;
+ QueryNodeImpl<?> impl = (QueryNodeImpl<?>) node;
return filterSources((source, infos) -> impl.graphNode == source).findFirst().isPresent();
}
@@ -493,7 +549,7 @@
if (!(node instanceof QueryNodeImpl)) {
return false;
}
- QueryNodeImpl impl = (QueryNodeImpl) node;
+ QueryNodeImpl<?> impl = (QueryNodeImpl<?>) node;
return filterSources(
(source, infos) ->
impl.graphNode == source && EdgeKindPredicate.compatibilityRule.test(infos))
@@ -506,22 +562,63 @@
if (!isCompatKeptBy(node)) {
return false;
}
- QueryNodeImpl impl = (QueryNodeImpl) node;
+ QueryNodeImpl<?> impl = (QueryNodeImpl<?>) node;
return filterSources((source, infos) -> impl.graphNode != source).count() == 0;
}
@Override
+ public boolean isKeptByAnnotationOn(QueryNode annotatedNode) {
+ // This should be an annotation node or a class node which it an annotation.
+ assert graphNode instanceof AnnotationGraphNode || graphNode instanceof ClassGraphNode;
+
+ // The annotated node (class, field or method) should be present.
+ assert annotatedNode.isPresent();
+ QueryNodeImpl<?> annotatedNodeImpl = (QueryNodeImpl<?>) annotatedNode;
+ assert annotatedNodeImpl.graphNode instanceof ClassGraphNode
+ || annotatedNodeImpl.graphNode instanceof FieldGraphNode
+ || annotatedNodeImpl.graphNode instanceof MethodGraphNode;
+
+ return hasSource(
+ (source, infos) ->
+ source.equals(annotatedNodeImpl.graphNode)
+ && EdgeKindPredicate.isAnnotatedOn.test(infos));
+ }
+
+ @Override
+ public boolean isKeptByReferenceInAnnotationOn(
+ QueryNode annotationNode, QueryNode annotatedNode) {
+ // The annotation node should be present.
+ assert annotationNode.isPresent();
+ QueryNodeImpl<ClassGraphNode> annotationNodeImpl =
+ (QueryNodeImpl<ClassGraphNode>) annotationNode;
+
+ // The annotated node (class, field or method) should be present.
+ assert annotatedNode.isPresent();
+ QueryNodeImpl<?> annotatedNodeImpl = (QueryNodeImpl<?>) annotatedNode;
+ assert annotatedNodeImpl.graphNode instanceof ClassGraphNode
+ || annotatedNodeImpl.graphNode instanceof FieldGraphNode
+ || annotatedNodeImpl.graphNode instanceof MethodGraphNode;
+
+ AnnotationGraphNode expectedSource =
+ new AnnotationGraphNode(annotatedNodeImpl.graphNode, annotationNodeImpl.graphNode);
+
+ return hasSource(
+ (source, infos) ->
+ source.equals(expectedSource)
+ && EdgeKindPredicate.isReferencedInAnnotation.test(infos));
+ }
+
+ @Override
public boolean isKeptByLibraryMethod(QueryNode node) {
assert graphNode instanceof MethodGraphNode;
- if (!(node instanceof QueryNodeImpl)) {
+ if (!node.isPresent()) {
return false;
}
- QueryNodeImpl impl = (QueryNodeImpl) node;
- return filterSources(
- (source, infos) ->
- impl.graphNode == source && EdgeKindPredicate.isLibraryMethod.test(infos))
- .findFirst()
- .isPresent();
+ assert node instanceof QueryNodeImpl;
+ QueryNodeImpl<?> impl = (QueryNodeImpl<?>) node;
+ return hasSource(
+ (source, infos) ->
+ impl.graphNode == source && EdgeKindPredicate.isLibraryMethod.test(infos));
}
@Override
@@ -544,7 +641,7 @@
+ node.getNodeDescription());
return;
}
- QueryNodeImpl impl = (QueryNodeImpl) node;
+ QueryNodeImpl<?> impl = (QueryNodeImpl<?>) node;
if (!filterSources((source, infos) -> impl.graphNode == source).findFirst().isPresent()) {
onError.accept(
"Expected to find dependency from precondtion to dependent rule, but could not. "
@@ -564,7 +661,7 @@
if (nodes.length != preconditions.size()) {
for (GraphNode precondition : preconditions) {
if (Arrays.stream(nodes)
- .noneMatch(node -> ((QueryNodeImpl) node).graphNode == precondition)) {
+ .noneMatch(node -> ((QueryNodeImpl<?>) node).graphNode == precondition)) {
onError.accept("Unexpected item in precondtions: " + precondition.toString());
return;
}
@@ -614,6 +711,10 @@
.filter(e -> test.test(e.getKey(), e.getValue()))
.map(Entry::getKey);
}
+
+ private boolean hasSource(BiPredicate<GraphNode, Set<GraphEdgeInfo>> test) {
+ return filterSources(test).findAny().isPresent();
+ }
}
private final CollectingGraphConsumer consumer;
@@ -753,6 +854,52 @@
return "rule@" + origin + ":" + new TextPosition(0, line, column);
}
+ public QueryNode annotation(Class<? extends Annotation> clazz, QueryNode annotatedNode) {
+ return annotation(Reference.classFromClass(clazz), annotatedNode);
+ }
+
+ public QueryNode annotation(ClassReference annotationClassReference, QueryNode annotatedNode) {
+ // The annotation node (class, field or method) should be present.
+ assert annotatedNode.isPresent();
+ QueryNodeImpl<?> annotatedNodeImpl = (QueryNodeImpl<?>) annotatedNode;
+ assert annotatedNodeImpl.graphNode instanceof ClassGraphNode
+ || annotatedNodeImpl.graphNode instanceof FieldGraphNode
+ || annotatedNodeImpl.graphNode instanceof MethodGraphNode;
+
+ Map<ClassReference, AnnotationGraphNode> annotationsOnAnnotatedItem;
+ if (annotatedNodeImpl.graphNode instanceof ClassGraphNode) {
+ annotationsOnAnnotatedItem =
+ classAnnotations.get(((ClassGraphNode) annotatedNodeImpl.graphNode).getReference());
+ } else if (annotatedNodeImpl.graphNode instanceof FieldGraphNode) {
+ annotationsOnAnnotatedItem =
+ fieldAnnotations.get(((FieldGraphNode) annotatedNodeImpl.graphNode).getReference());
+ } else {
+ assert annotatedNodeImpl.graphNode instanceof MethodGraphNode;
+ annotationsOnAnnotatedItem =
+ methodAnnotations.get(((MethodGraphNode) annotatedNodeImpl.graphNode).getReference());
+ }
+
+ if (annotationsOnAnnotatedItem == null) {
+ return new AbsentQueryNode(
+ "Node " + annotatedNode.getNodeDescription() + " has no annotations");
+ }
+
+ AnnotationGraphNode annotationGraphNode =
+ annotationsOnAnnotatedItem.get(annotationClassReference);
+ if (annotationGraphNode == null) {
+ return new AbsentQueryNode(
+ "Node "
+ + annotatedNode.getNodeDescription()
+ + " has no annotation of type "
+ + annotationClassReference.getTypeName());
+ }
+ return new QueryNodeImpl<>(this, annotationGraphNode);
+ }
+
+ public QueryNode clazz(Class<?> clazz) {
+ return clazz(Reference.classFromClass(clazz));
+ }
+
public QueryNode clazz(ClassReference clazz) {
return getQueryNode(classes.get(clazz), clazz.toString());
}
diff --git a/third_party/openjdk/desugar_jdk_libs_releases/1.0.10.tar.gz.sha1 b/third_party/openjdk/desugar_jdk_libs_releases/1.0.10.tar.gz.sha1
new file mode 100644
index 0000000..ec8b41b
--- /dev/null
+++ b/third_party/openjdk/desugar_jdk_libs_releases/1.0.10.tar.gz.sha1
@@ -0,0 +1 @@
+ee0cf6f06d1f8f725a72f28826533bbcc407678e
\ No newline at end of file
diff --git a/third_party/openjdk/desugar_jdk_libs_releases/1.0.9.tar.gz.sha1 b/third_party/openjdk/desugar_jdk_libs_releases/1.0.9.tar.gz.sha1
new file mode 100644
index 0000000..10b5a1f
--- /dev/null
+++ b/third_party/openjdk/desugar_jdk_libs_releases/1.0.9.tar.gz.sha1
@@ -0,0 +1 @@
+e5b342cfdd5c0799c9c729e55d4258a4bd2b13c7
\ No newline at end of file
diff --git a/third_party/openjdk/desugar_jdk_libs_releases/1.1.0.tar.gz.sha1 b/third_party/openjdk/desugar_jdk_libs_releases/1.1.0.tar.gz.sha1
new file mode 100644
index 0000000..f42f4c4
--- /dev/null
+++ b/third_party/openjdk/desugar_jdk_libs_releases/1.1.0.tar.gz.sha1
@@ -0,0 +1 @@
+d49b2f1b946cfb868a843605a8c75f5d958fb2a6
\ No newline at end of file
diff --git a/third_party/openjdk/desugar_jdk_libs_releases/1.1.1.tar.gz.sha1 b/third_party/openjdk/desugar_jdk_libs_releases/1.1.1.tar.gz.sha1
new file mode 100644
index 0000000..1133b23
--- /dev/null
+++ b/third_party/openjdk/desugar_jdk_libs_releases/1.1.1.tar.gz.sha1
@@ -0,0 +1 @@
+57bafe4d948330c30123732981e40827a6e02479
\ No newline at end of file
diff --git a/third_party/openjdk/desugar_jdk_libs_releases/1.1.5.tar.gz.sha1 b/third_party/openjdk/desugar_jdk_libs_releases/1.1.5.tar.gz.sha1
new file mode 100644
index 0000000..522687f
--- /dev/null
+++ b/third_party/openjdk/desugar_jdk_libs_releases/1.1.5.tar.gz.sha1
@@ -0,0 +1 @@
+074f2bea4a557e48a92ffc6c572a791db655574c
\ No newline at end of file
diff --git a/tools/compiledump.py b/tools/compiledump.py
index cc71d22..192145b 100755
--- a/tools/compiledump.py
+++ b/tools/compiledump.py
@@ -3,21 +3,26 @@
# 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.
-import archive
import argparse
-import jdk
import os
-import retrace
import subprocess
import sys
import zipfile
+import archive
+import jdk
+import retrace
import utils
def make_parser():
parser = argparse.ArgumentParser(description = 'Compile a dump artifact.')
parser.add_argument(
+ '--summary',
+ help='List a summary of the contents of the dumps.',
+ default=False,
+ action='store_true')
+ parser.add_argument(
'-d',
'--dump',
help='Dump file or directory to compile',
@@ -169,15 +174,17 @@
return open(f).read().split(' ')[0]
return None
-def read_dump(args, temp):
+def read_dump_from_args(args, temp):
if args.dump is None:
error("A dump file or directory must be specified")
- if os.path.isdir(args.dump):
- return Dump(args.dump)
- dump_file = zipfile.ZipFile(os.path.abspath(args.dump), 'r')
- with utils.ChangedWorkingDirectory(temp):
- if args.override or not os.path.isfile('r8-version'):
- print("Extracting into: %s" % temp)
+ return read_dump(args.dump, temp, args.override)
+
+def read_dump(dump, temp, override=False):
+ if os.path.isdir(dump):
+ return Dump(dump)
+ dump_file = zipfile.ZipFile(os.path.abspath(dump), 'r')
+ with utils.ChangedWorkingDirectory(temp, quiet=True):
+ if override or not os.path.isfile('r8-version'):
dump_file.extractall()
if not os.path.isfile('r8-version'):
error("Did not extract into %s. Either the zip file is invalid or the "
@@ -268,7 +275,7 @@
temp = out
if not os.path.exists(temp):
os.makedirs(temp)
- dump = read_dump(args, temp)
+ dump = read_dump_from_args(args, temp)
if not dump.program_jar():
error("Cannot compile dump with no program classes")
if not dump.library_jar():
@@ -376,8 +383,56 @@
print('Could not find map file from argument: %s.' % version)
return None
+def summarize_dump_files(dumpfiles):
+ if len(dumpfiles) == 0:
+ error('Summary command expects a list of dumps to summarize')
+ for f in dumpfiles:
+ print(f + ':')
+ try:
+ with utils.TempDir() as temp:
+ dump = read_dump(f, temp)
+ summarize_dump(dump)
+ except IOError as e:
+ print("Error: " + str(e))
+ except zipfile.BadZipfile as e:
+ print("Error: " + str(e))
+
+def summarize_dump(dump):
+ version = dump.version()
+ if not version:
+ print('No dump version info')
+ return
+ print('version=' + version)
+ props = dump.build_properties_file()
+ if props:
+ with open(props) as props_file:
+ print(props_file.read())
+ if dump.library_jar():
+ print('library.jar present')
+ if dump.classpath_jar():
+ print('classpath.jar present')
+ prog = dump.program_jar()
+ if prog:
+ print('program.jar content:')
+ summarize_jar(prog)
+
+def summarize_jar(jar):
+ with zipfile.ZipFile(jar) as zip:
+ pkgs = {}
+ for info in zip.infolist():
+ if info.filename.endswith('.class'):
+ pkg, clazz = os.path.split(info.filename)
+ count = pkgs.get(pkg, 0)
+ pkgs[pkg] = count + 1
+ sorted = list(pkgs.keys())
+ sorted.sort()
+ for p in sorted:
+ print(' ' + p + ': ' + str(pkgs[p]))
+
def run(args, otherargs):
- if (args.loop):
+ if args.summary:
+ summarize_dump_files(otherargs)
+ elif args.loop:
count = 1
while True:
print('Iteration {:03d}'.format(count))