Add support for synthesizing classpath classes
Change-Id: Ifb4731a712e4755de632762c38bbaa643c980ea9
diff --git a/src/main/java/com/android/tools/r8/graph/DexApplication.java b/src/main/java/com/android/tools/r8/graph/DexApplication.java
index 219b723..af6d9f6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DexApplication.java
@@ -98,6 +98,8 @@
abstract List<DexProgramClass> programClasses();
+ abstract List<DexClasspathClass> classpathClasses();
+
public List<DexProgramClass> classes() {
ReorderBox<DexProgramClass> box = new ReorderBox<>(programClasses());
assert box.reorderClasses();
@@ -134,7 +136,8 @@
// new or removing existing classes), classpath and library
// collections will be considered monolithic collections.
- List<DexProgramClass> programClasses = new ArrayList<>();
+ private List<DexProgramClass> programClasses = new ArrayList<>();
+ private List<DexClasspathClass> classpathClasses = new ArrayList<>();
final List<DataResourceProvider> dataResourceProviders = new ArrayList<>();
@@ -157,6 +160,7 @@
public Builder(DexApplication application) {
programClasses.addAll(application.programClasses());
+ classpathClasses.addAll(application.classpathClasses());
dataResourceProviders.addAll(application.dataResourceProviders);
proguardMap = application.getProguardMap();
timing = application.timing;
@@ -172,13 +176,21 @@
return self();
}
- public synchronized T replaceProgramClasses(List<DexProgramClass> newProgramClasses) {
+ public synchronized T replaceProgramClasses(Collection<DexProgramClass> newProgramClasses) {
assert newProgramClasses != null;
this.programClasses.clear();
this.programClasses.addAll(newProgramClasses);
return self();
}
+ public synchronized T replaceClasspathClasses(
+ Collection<DexClasspathClass> newClasspathClasses) {
+ assert newClasspathClasses != null;
+ classpathClasses.clear();
+ classpathClasses.addAll(newClasspathClasses);
+ return self();
+ }
+
public synchronized T addDataResourceProvider(DataResourceProvider provider) {
dataResourceProviders.add(provider);
return self();
@@ -194,6 +206,21 @@
return self();
}
+ public synchronized T addProgramClasses(Collection<DexProgramClass> classes) {
+ programClasses.addAll(classes);
+ return self();
+ }
+
+ public synchronized T addClasspathClass(DexClasspathClass clazz) {
+ classpathClasses.add(clazz);
+ return self();
+ }
+
+ public synchronized T addClasspathClasses(Collection<DexClasspathClass> classes) {
+ classpathClasses.addAll(classes);
+ return self();
+ }
+
public synchronized T addSynthesizedClass(DexProgramClass synthesizedClass) {
assert synthesizedClass.isProgramClass() : "All synthesized classes must be program classes";
addProgramClass(synthesizedClass);
@@ -201,10 +228,14 @@
return self();
}
- public Collection<DexProgramClass> getProgramClasses() {
+ public List<DexProgramClass> getProgramClasses() {
return programClasses;
}
+ public List<DexClasspathClass> getClasspathClasses() {
+ return classpathClasses;
+ }
+
public Collection<DexProgramClass> getSynthesizedClasses() {
return synthesizedClasses;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
index dc3ff8d..7fb6023 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClasspathClass.java
@@ -12,13 +12,17 @@
import com.android.tools.r8.graph.GenericSignature.ClassSignature;
import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
+import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
-public class DexClasspathClass extends DexClass implements Supplier<DexClasspathClass> {
+public class DexClasspathClass extends DexClass
+ implements Supplier<DexClasspathClass>, StructuralItem<DexClasspathClass> {
public DexClasspathClass(
DexType type,
@@ -129,4 +133,30 @@
}
return !isInterface() || appView.options().classpathInterfacesMayHaveStaticInitialization;
}
+
+ @Override
+ public DexClasspathClass self() {
+ return this;
+ }
+
+ @Override
+ public StructuralMapping<DexClasspathClass> getStructuralMapping() {
+ return DexClasspathClass::specify;
+ }
+
+ private static void specify(StructuralSpecification<DexClasspathClass, ?> spec) {
+ spec.withItem(DexClass::getType)
+ .withItem(DexClass::getSuperType)
+ .withItem(DexClass::getInterfaces)
+ .withItem(DexClass::getAccessFlags)
+ .withNullableItem(DexClass::getSourceFile)
+ .withNullableItem(DexClass::getNestHostClassAttribute)
+ .withItemCollection(DexClass::getNestMembersClassAttributes)
+ .withItem(DexDefinition::annotations)
+ // TODO(b/158159959): Make signatures structural.
+ .withAssert(c -> c.classSignature == ClassSignature.noSignature())
+ .withItemArray(c -> c.staticFields)
+ .withItemArray(c -> c.instanceFields)
+ .withItemCollection(DexClass::allMethodsSorted);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
index c6cf5f8..c267e7c 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -67,7 +67,8 @@
return libraryClasses;
}
- public Collection<DexClasspathClass> classpathClasses() {
+ @Override
+ public List<DexClasspathClass> classpathClasses() {
return classpathClasses;
}
@@ -181,21 +182,19 @@
public static class Builder extends DexApplication.Builder<Builder> {
private ImmutableList<DexLibraryClass> libraryClasses;
- private ImmutableList<DexClasspathClass> classpathClasses;
Builder(LazyLoadedDexApplication application) {
super(application);
// As a side-effect, this will force-load all classes.
AllClasses allClasses = application.loadAllClasses();
libraryClasses = allClasses.getLibraryClasses();
- classpathClasses = allClasses.getClasspathClasses();
replaceProgramClasses(allClasses.getProgramClasses());
+ replaceClasspathClasses(allClasses.getClasspathClasses());
}
private Builder(DirectMappedDexApplication application) {
super(application);
libraryClasses = application.libraryClasses;
- classpathClasses = application.classpathClasses;
}
@Override
@@ -208,26 +207,6 @@
return self();
}
- public Builder replaceClasspathClasses(Collection<DexClasspathClass> classpathClasses) {
- this.classpathClasses = ImmutableList.copyOf(classpathClasses);
- return self();
- }
-
- public Builder addProgramClasses(Collection<DexProgramClass> classes) {
- programClasses =
- ImmutableList.<DexProgramClass>builder().addAll(programClasses).addAll(classes).build();
- return self();
- }
-
- public Builder addClasspathClasses(Collection<DexClasspathClass> classes) {
- classpathClasses =
- ImmutableList.<DexClasspathClass>builder()
- .addAll(classpathClasses)
- .addAll(classes)
- .build();
- return self();
- }
-
public Builder addLibraryClasses(Collection<DexLibraryClass> classes) {
libraryClasses =
ImmutableList.<DexLibraryClass>builder().addAll(libraryClasses).addAll(classes).build();
@@ -240,17 +219,17 @@
// TODO(zerny): Consider not rebuilding the map if no program classes are added.
Map<DexType, DexClass> allClasses =
new IdentityHashMap<>(
- programClasses.size() + classpathClasses.size() + libraryClasses.size());
+ getProgramClasses().size() + getClasspathClasses().size() + libraryClasses.size());
// Note: writing classes in reverse priority order, so a duplicate will be correctly ordered.
// There should never be duplicates and that is asserted in the addAll subroutine.
addAll(allClasses, libraryClasses);
- addAll(allClasses, classpathClasses);
- addAll(allClasses, programClasses);
+ addAll(allClasses, getClasspathClasses());
+ addAll(allClasses, getProgramClasses());
return new DirectMappedDexApplication(
proguardMap,
allClasses,
- ImmutableList.copyOf(programClasses),
- classpathClasses,
+ ImmutableList.copyOf(getProgramClasses()),
+ ImmutableList.copyOf(getClasspathClasses()),
libraryClasses,
ImmutableList.copyOf(dataResourceProviders),
options,
diff --git a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
index ce5ff83..ba240f6 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyLoadedDexApplication.java
@@ -54,6 +54,12 @@
}
@Override
+ List<DexClasspathClass> classpathClasses() {
+ classpathClasses.forceLoad(t -> true);
+ return classpathClasses.getAllClasses();
+ }
+
+ @Override
public DexClass definitionFor(DexType type) {
assert type.isClassType() : "Cannot lookup definition for type: " + type;
DexClass clazz = null;
@@ -199,7 +205,7 @@
Builder(ProgramClassConflictResolver resolver, InternalOptions options, Timing timing) {
super(options, timing);
this.resolver = resolver;
- this.classpathClasses = null;
+ this.classpathClasses = ClasspathClassCollection.empty();
this.libraryClasses = null;
}
@@ -229,7 +235,7 @@
public LazyLoadedDexApplication build() {
return new LazyLoadedDexApplication(
proguardMap,
- ProgramClassCollection.create(programClasses, resolver),
+ ProgramClassCollection.create(getProgramClasses(), resolver),
ImmutableList.copyOf(dataResourceProviders),
classpathClasses,
libraryClasses,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
index 966cfec..477d8d8 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -34,7 +34,7 @@
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
import com.android.tools.r8.ir.synthetic.SynthesizedCode;
-import com.android.tools.r8.synthesis.SyntheticClassBuilder;
+import com.android.tools.r8.synthesis.SyntheticProgramClassBuilder;
import com.android.tools.r8.utils.OptionalBool;
import java.util.ArrayList;
import java.util.Collections;
@@ -72,7 +72,7 @@
private DexProgramClass clazz = null;
LambdaClass(
- SyntheticClassBuilder builder,
+ SyntheticProgramClassBuilder builder,
AppView<?> appView,
LambdaRewriter rewriter,
ProgramMethod accessedFrom,
@@ -115,7 +115,7 @@
this.clazz = clazz;
}
- private void synthesizeLambdaClass(SyntheticClassBuilder builder) {
+ private void synthesizeLambdaClass(SyntheticProgramClassBuilder builder) {
builder.setInterfaces(descriptor.interfaces);
synthesizeStaticFields(builder);
synthesizeInstanceFields(builder);
@@ -137,7 +137,7 @@
}
// Synthesize virtual methods.
- private void synthesizeVirtualMethods(SyntheticClassBuilder builder) {
+ private void synthesizeVirtualMethods(SyntheticProgramClassBuilder builder) {
DexMethod mainMethod =
appView.dexItemFactory().createMethod(type, descriptor.erasedProto, descriptor.name);
@@ -178,7 +178,7 @@
}
// Synthesize direct methods.
- private void synthesizeDirectMethods(SyntheticClassBuilder builder) {
+ private void synthesizeDirectMethods(SyntheticProgramClassBuilder builder) {
boolean stateless = isStateless();
List<DexEncodedMethod> methods = new ArrayList<>(stateless ? 2 : 1);
@@ -214,7 +214,7 @@
}
// Synthesize instance fields to represent captured values.
- private void synthesizeInstanceFields(SyntheticClassBuilder builder) {
+ private void synthesizeInstanceFields(SyntheticProgramClassBuilder builder) {
DexType[] fieldTypes = descriptor.captures.values;
int fieldCount = fieldTypes.length;
List<DexEncodedField> fields = new ArrayList<>(fieldCount);
@@ -234,7 +234,7 @@
}
// Synthesize static fields to represent singleton instance.
- private void synthesizeStaticFields(SyntheticClassBuilder builder) {
+ private void synthesizeStaticFields(SyntheticProgramClassBuilder builder) {
if (isStateless()) {
// Create instance field for stateless lambda.
assert this.lambdaField != null;
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index 8d83434..e88a714 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -279,7 +279,7 @@
previous.getMainDexClasses(),
previous.deadProtoTypes,
previous.getMissingClasses(),
- CollectionUtils.mergeSets(previous.liveTypes, committedItems.getCommittedTypes()),
+ CollectionUtils.mergeSets(previous.liveTypes, committedItems.getCommittedProgramTypes()),
previous.targetedMethods,
previous.failedResolutionTargets,
previous.bootstrapMethods,
diff --git a/src/main/java/com/android/tools/r8/synthesis/CommittedItems.java b/src/main/java/com/android/tools/r8/synthesis/CommittedItems.java
index e60dfa3..2681a90 100644
--- a/src/main/java/com/android/tools/r8/synthesis/CommittedItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/CommittedItems.java
@@ -27,17 +27,17 @@
final DexApplication application;
final int nextSyntheticId;
final CommittedSyntheticsCollection committed;
- final ImmutableList<DexType> committedTypes;
+ final ImmutableList<DexType> committedProgramTypes;
CommittedItems(
int nextSyntheticId,
DexApplication application,
CommittedSyntheticsCollection committed,
- ImmutableList<DexType> committedTypes) {
+ ImmutableList<DexType> committedProgramTypes) {
this.nextSyntheticId = nextSyntheticId;
this.application = application;
this.committed = committed;
- this.committedTypes = committedTypes;
+ this.committedProgramTypes = committedProgramTypes;
committed.verifyTypesAreInApp(application);
}
@@ -50,8 +50,8 @@
return application;
}
- public Collection<DexType> getCommittedTypes() {
- return committedTypes;
+ public Collection<DexType> getCommittedProgramTypes() {
+ return committedProgramTypes;
}
@Deprecated
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 582a39a..053b20b 100644
--- a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
+++ b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
@@ -26,7 +26,8 @@
static class Builder {
private final CommittedSyntheticsCollection parent;
- private ImmutableMap.Builder<DexType, SyntheticClassReference> newNonLegacyClasses = null;
+ private ImmutableMap.Builder<DexType, SyntheticProgramClassReference> newNonLegacyClasses =
+ null;
private ImmutableMap.Builder<DexType, SyntheticMethodReference> newNonLegacyMethods = null;
private ImmutableSet.Builder<DexType> newLegacyClasses = null;
@@ -34,16 +35,18 @@
this.parent = parent;
}
- public Builder addItem(SyntheticDefinition<?, ?> definition) {
- definition.toReference().apply(this::addNonLegacyMethod, this::addNonLegacyClass);
+ public Builder addItem(SyntheticDefinition<?, ?, ?> definition) {
+ if (definition.isProgramDefinition()) {
+ definition.asProgramDefinition().apply(this::addNonLegacyMethod, this::addNonLegacyClass);
+ }
return this;
}
- public Builder addNonLegacyClass(SyntheticClassDefinition definition) {
+ public Builder addNonLegacyClass(SyntheticProgramClassDefinition definition) {
return addNonLegacyClass(definition.toReference());
}
- public Builder addNonLegacyClass(SyntheticClassReference reference) {
+ public Builder addNonLegacyClass(SyntheticProgramClassReference reference) {
if (newNonLegacyClasses == null) {
newNonLegacyClasses = ImmutableMap.builder();
}
@@ -83,7 +86,7 @@
if (newNonLegacyClasses == null && newNonLegacyMethods == null && newLegacyClasses == null) {
return parent;
}
- ImmutableMap<DexType, SyntheticClassReference> allNonLegacyClasses =
+ ImmutableMap<DexType, SyntheticProgramClassReference> allNonLegacyClasses =
newNonLegacyClasses == null
? parent.nonLegacyClasses
: newNonLegacyClasses.putAll(parent.nonLegacyClasses).build();
@@ -114,12 +117,12 @@
private final ImmutableMap<DexType, SyntheticMethodReference> nonLegacyMethods;
/** Mapping from synthetic type to its synthetic class item description. */
- private final ImmutableMap<DexType, SyntheticClassReference> nonLegacyClasses;
+ private final ImmutableMap<DexType, SyntheticProgramClassReference> nonLegacyClasses;
public CommittedSyntheticsCollection(
ImmutableSet<DexType> legacyTypes,
ImmutableMap<DexType, SyntheticMethodReference> nonLegacyMethods,
- ImmutableMap<DexType, SyntheticClassReference> nonLegacyClasses) {
+ ImmutableMap<DexType, SyntheticProgramClassReference> nonLegacyClasses) {
this.legacyTypes = legacyTypes;
this.nonLegacyMethods = nonLegacyMethods;
this.nonLegacyClasses = nonLegacyClasses;
@@ -160,11 +163,11 @@
return nonLegacyMethods;
}
- public ImmutableMap<DexType, SyntheticClassReference> getNonLegacyClasses() {
+ public ImmutableMap<DexType, SyntheticProgramClassReference> getNonLegacyClasses() {
return nonLegacyClasses;
}
- public SyntheticReference<?, ?> getNonLegacyItem(DexType type) {
+ public SyntheticReference<?, ?, ?> getNonLegacyItem(DexType type) {
SyntheticMethodReference reference = nonLegacyMethods.get(type);
if (reference != null) {
return reference;
@@ -172,7 +175,7 @@
return nonLegacyClasses.get(type);
}
- public void forEachNonLegacyItem(Consumer<SyntheticReference<?, ?>> fn) {
+ public void forEachNonLegacyItem(Consumer<SyntheticReference<?, ?, ?>> fn) {
nonLegacyMethods.forEach((t, r) -> fn.accept(r));
nonLegacyClasses.forEach((t, r) -> fn.accept(r));
}
@@ -198,7 +201,7 @@
builder.addNonLegacyMethod(reference);
}
}
- for (SyntheticClassReference reference : nonLegacyClasses.values()) {
+ for (SyntheticProgramClassReference reference : nonLegacyClasses.values()) {
if (removed.contains(reference.getHolder())) {
changed = true;
} else {
@@ -215,7 +218,7 @@
rewriteItems(nonLegacyClasses, lens));
}
- private static <R extends SyntheticReference<R, ?>> ImmutableMap<DexType, R> rewriteItems(
+ private static <R extends SyntheticReference<R, ?, ?>> ImmutableMap<DexType, R> rewriteItems(
Map<DexType, R> items, NonIdentityGraphLens lens) {
ImmutableMap.Builder<DexType, R> rewrittenItems = ImmutableMap.builder();
for (R reference : items.values()) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
index 2e371d0..932359d 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SynthesizingContext.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.utils.DescriptorUtils.getDescriptorFromClassBinaryName;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
@@ -39,6 +40,13 @@
private final DexType inputContextType;
private final Origin inputContextOrigin;
+ static SynthesizingContext fromNonSyntheticInputContext(DexClass context) {
+ // A context that is itself non-synthetic is the single context, thus both the input context
+ // and synthesizing context coincide.
+ return new SynthesizingContext(
+ context.getContextType(), context.getContextType(), context.getOrigin());
+ }
+
static SynthesizingContext fromNonSyntheticInputContext(ProgramDefinition context) {
// A context that is itself non-synthetic is the single context, thus both the input context
// and synthesizing context coincide.
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 9d2460b..01e6c75 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassBuilder.java
@@ -1,16 +1,18 @@
// 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.synthesis;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.ClassAccessFlags;
+import com.android.tools.r8.graph.ClassKind;
import com.android.tools.r8.graph.DexAnnotationSet;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
@@ -25,12 +27,14 @@
import java.util.List;
import java.util.function.Consumer;
-public class SyntheticClassBuilder {
+abstract class SyntheticClassBuilder<B extends SyntheticClassBuilder<B, C>, C extends DexClass> {
+
private final DexItemFactory factory;
private final DexType type;
private final Origin origin;
+ private Kind originKind;
private DexType superType;
private DexTypeList interfaces = DexTypeList.empty();
private List<DexEncodedField> staticFields = new ArrayList<>();
@@ -46,6 +50,10 @@
this.superType = factory.objectType;
}
+ public abstract B self();
+
+ public abstract ClassKind<C> getClassKind();
+
public DexItemFactory getFactory() {
return factory;
}
@@ -54,50 +62,54 @@
return type;
}
- public SyntheticClassBuilder setInterfaces(List<DexType> interfaces) {
+ public B setInterfaces(List<DexType> interfaces) {
this.interfaces =
interfaces.isEmpty()
? DexTypeList.empty()
: new DexTypeList(interfaces.toArray(DexType.EMPTY_ARRAY));
- return this;
+ return self();
}
- public SyntheticClassBuilder setStaticFields(List<DexEncodedField> fields) {
+ public B setOriginKind(Kind originKind) {
+ this.originKind = originKind;
+ return self();
+ }
+
+ public B setStaticFields(List<DexEncodedField> fields) {
staticFields.clear();
staticFields.addAll(fields);
- return this;
+ return self();
}
- public SyntheticClassBuilder setInstanceFields(List<DexEncodedField> fields) {
+ public B setInstanceFields(List<DexEncodedField> fields) {
instanceFields.clear();
instanceFields.addAll(fields);
- return this;
+ return self();
}
- public SyntheticClassBuilder setDirectMethods(Iterable<DexEncodedMethod> methods) {
+ public B setDirectMethods(Iterable<DexEncodedMethod> methods) {
directMethods.clear();
methods.forEach(directMethods::add);
- return this;
+ return self();
}
- public SyntheticClassBuilder setVirtualMethods(Iterable<DexEncodedMethod> methods) {
+ public B setVirtualMethods(Iterable<DexEncodedMethod> methods) {
virtualMethods.clear();
methods.forEach(virtualMethods::add);
- return this;
+ return self();
}
- public SyntheticClassBuilder addMethod(Consumer<SyntheticMethodBuilder> fn) {
+ public B addMethod(Consumer<SyntheticMethodBuilder> fn) {
SyntheticMethodBuilder method = new SyntheticMethodBuilder(this);
fn.accept(method);
methods.add(method);
- return this;
+ return self();
}
- DexProgramClass build() {
+ public C build() {
ClassAccessFlags accessFlags =
ClassAccessFlags.fromSharedAccessFlags(
Constants.ACC_FINAL | Constants.ACC_PUBLIC | Constants.ACC_SYNTHETIC);
- Kind originKind = null;
DexString sourceFile = null;
NestHostClassAttribute nestHost = null;
List<NestMemberClassAttribute> nestMembers = Collections.emptyList();
@@ -116,25 +128,26 @@
+ 11 * (long) virtualMethods.hashCode()
+ 13 * (long) staticFields.hashCode()
+ 17 * (long) instanceFields.hashCode();
- return new DexProgramClass(
- type,
- originKind,
- origin,
- accessFlags,
- superType,
- interfaces,
- sourceFile,
- nestHost,
- nestMembers,
- enclosingMembers,
- innerClasses,
- ClassSignature.noSignature(),
- DexAnnotationSet.empty(),
- staticFields.toArray(new DexEncodedField[staticFields.size()]),
- instanceFields.toArray(new DexEncodedField[instanceFields.size()]),
- directMethods.toArray(new DexEncodedMethod[directMethods.size()]),
- virtualMethods.toArray(new DexEncodedMethod[virtualMethods.size()]),
- factory.getSkipNameValidationForTesting(),
- c -> checksum);
+ return getClassKind()
+ .create(
+ type,
+ originKind,
+ origin,
+ accessFlags,
+ superType,
+ interfaces,
+ sourceFile,
+ nestHost,
+ nestMembers,
+ enclosingMembers,
+ innerClasses,
+ ClassSignature.noSignature(),
+ DexAnnotationSet.empty(),
+ staticFields.toArray(DexEncodedField.EMPTY_ARRAY),
+ instanceFields.toArray(DexEncodedField.EMPTY_ARRAY),
+ directMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
+ virtualMethods.toArray(DexEncodedMethod.EMPTY_ARRAY),
+ factory.getSkipNameValidationForTesting(),
+ c -> checksum);
}
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassDefinition.java
index 4b0b2cf..3a915bf 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassDefinition.java
@@ -3,37 +3,29 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.synthesis;
-import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-import com.android.tools.r8.utils.structural.RepresentativeMap;
-import com.google.common.hash.Hasher;
/**
* Definition of a synthetic class item.
*
* <p>This class is internal to the synthetic items collection, thus package-protected.
*/
-class SyntheticClassDefinition
- extends SyntheticDefinition<SyntheticClassReference, SyntheticClassDefinition> {
+public abstract class SyntheticClassDefinition<
+ R extends SyntheticClassReference<R, D, C>,
+ D extends SyntheticClassDefinition<R, D, C>,
+ C extends DexClass>
+ extends SyntheticDefinition<R, D, C> {
- private final DexProgramClass clazz;
+ final C clazz;
- SyntheticClassDefinition(SyntheticKind kind, SynthesizingContext context, DexProgramClass clazz) {
+ SyntheticClassDefinition(SyntheticKind kind, SynthesizingContext context, C clazz) {
super(kind, context);
this.clazz = clazz;
}
- public DexProgramClass getProgramClass() {
- return clazz;
- }
-
@Override
- SyntheticClassReference toReference() {
- return new SyntheticClassReference(getKind(), getContext(), clazz.getType());
- }
-
- @Override
- DexProgramClass getHolder() {
+ public final C getHolder() {
return clazz;
}
@@ -43,16 +35,6 @@
}
@Override
- void internalComputeHash(Hasher hasher, RepresentativeMap map) {
- clazz.hashWithTypeEquivalence(hasher, map);
- }
-
- @Override
- int internalCompareTo(SyntheticClassDefinition o, RepresentativeMap map) {
- return clazz.compareWithTypeEquivalenceTo(o.clazz, map);
- }
-
- @Override
public String toString() {
return "SyntheticClass{ clazz = "
+ clazz.type.toSourceString()
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassReference.java
index 9c79ab9..25142ee 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticClassReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClassReference.java
@@ -1,22 +1,24 @@
// 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.synthesis;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-import java.util.function.Consumer;
-import java.util.function.Function;
/**
* Reference to a synthetic class item.
*
* <p>This class is internal to the synthetic items collection, thus package-protected.
*/
-class SyntheticClassReference
- extends SyntheticReference<SyntheticClassReference, SyntheticClassDefinition> {
+abstract class SyntheticClassReference<
+ R extends SyntheticClassReference<R, D, C>,
+ D extends SyntheticClassDefinition<R, D, C>,
+ C extends DexClass>
+ extends SyntheticReference<R, D, C> {
+
final DexType type;
SyntheticClassReference(SyntheticKind kind, SynthesizingContext context, DexType type) {
@@ -28,46 +30,4 @@
DexType getHolder() {
return type;
}
-
- @Override
- SyntheticClassDefinition lookupDefinition(Function<DexType, DexClass> definitions) {
- DexClass clazz = definitions.apply(type);
- if (clazz == null) {
- return null;
- }
- assert clazz.isProgramClass();
- return new SyntheticClassDefinition(getKind(), getContext(), clazz.asProgramClass());
- }
-
- @Override
- SyntheticClassReference rewrite(NonIdentityGraphLens lens) {
- DexType rewritten = lens.lookupType(type);
- // If the reference has been non-trivially rewritten the compiler has changed it and it can no
- // longer be considered a synthetic. The context may or may not have changed.
- if (type != rewritten && !lens.isSimpleRenaming(type, rewritten)) {
- // If the referenced item is rewritten, it should be moved to another holder as the
- // synthetic holder is no longer part of the synthetic collection.
- assert SyntheticNaming.verifyNotInternalSynthetic(rewritten);
- return null;
- }
- SynthesizingContext context = getContext().rewrite(lens);
- if (context == getContext() && rewritten == type) {
- return this;
- }
- // Ensure that if a synthetic moves its context moves consistently.
- if (type != rewritten) {
- context =
- SynthesizingContext.fromSyntheticContextChange(rewritten, context, lens.dexItemFactory());
- if (context == null) {
- return null;
- }
- }
- return new SyntheticClassReference(getKind(), context, rewritten);
- }
-
- @Override
- void apply(
- Consumer<SyntheticMethodReference> onMethod, Consumer<SyntheticClassReference> onClass) {
- onClass.accept(this);
- }
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassBuilder.java
new file mode 100644
index 0000000..20cd075
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassBuilder.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.synthesis;
+
+import com.android.tools.r8.ProgramResource.Kind;
+import com.android.tools.r8.graph.ClassKind;
+import com.android.tools.r8.graph.DexClasspathClass;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexType;
+
+public class SyntheticClasspathClassBuilder
+ extends SyntheticClassBuilder<SyntheticClasspathClassBuilder, DexClasspathClass> {
+
+ SyntheticClasspathClassBuilder(
+ DexType type, SynthesizingContext context, DexItemFactory factory) {
+ super(type, context, factory);
+ setOriginKind(Kind.CF);
+ }
+
+ @Override
+ public ClassKind<DexClasspathClass> getClassKind() {
+ return ClassKind.CLASSPATH;
+ }
+
+ @Override
+ public SyntheticClasspathClassBuilder self() {
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassDefinition.java
new file mode 100644
index 0000000..a05d505
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassDefinition.java
@@ -0,0 +1,66 @@
+// 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.synthesis;
+
+import com.android.tools.r8.graph.DexClasspathClass;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.utils.structural.RepresentativeMap;
+import com.google.common.hash.Hasher;
+
+/**
+ * Definition of a synthetic classpath class.
+ *
+ * <p>This class is internal to the synthetic items collection, thus package-protected.
+ */
+class SyntheticClasspathClassDefinition
+ extends SyntheticClassDefinition<
+ SyntheticClasspathClassReference, SyntheticClasspathClassDefinition, DexClasspathClass>
+ implements SyntheticClasspathDefinition {
+
+ SyntheticClasspathClassDefinition(
+ SyntheticKind kind, SynthesizingContext context, DexClasspathClass clazz) {
+ super(kind, context, clazz);
+ }
+
+ @Override
+ public boolean isClasspathDefinition() {
+ return true;
+ }
+
+ @Override
+ public SyntheticClasspathDefinition asClasspathDefinition() {
+ return this;
+ }
+
+ @Override
+ SyntheticClasspathClassReference toReference() {
+ return new SyntheticClasspathClassReference(getKind(), getContext(), clazz.getType());
+ }
+
+ @Override
+ public boolean isValid() {
+ return clazz.isPublic() && clazz.isFinal() && clazz.accessFlags.isSynthetic();
+ }
+
+ @Override
+ void internalComputeHash(Hasher hasher, RepresentativeMap map) {
+ clazz.hashWithTypeEquivalence(hasher, map);
+ }
+
+ @Override
+ int internalCompareTo(SyntheticClasspathClassDefinition o, RepresentativeMap map) {
+ return clazz.compareWithTypeEquivalenceTo(o.clazz, map);
+ }
+
+ @Override
+ public String toString() {
+ return "SyntheticClasspathClass{ clazz = "
+ + clazz.type.toSourceString()
+ + ", kind = "
+ + getKind()
+ + ", context = "
+ + getContext()
+ + " }";
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassReference.java
new file mode 100644
index 0000000..5b9ba3c
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathClassReference.java
@@ -0,0 +1,42 @@
+// 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.synthesis;
+
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClasspathClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import java.util.function.Function;
+
+/**
+ * Reference to a synthetic class item.
+ *
+ * <p>This class is internal to the synthetic items collection, thus package-protected.
+ */
+class SyntheticClasspathClassReference
+ extends SyntheticClassReference<
+ SyntheticClasspathClassReference, SyntheticClasspathClassDefinition, DexClasspathClass> {
+
+ SyntheticClasspathClassReference(SyntheticKind kind, SynthesizingContext context, DexType type) {
+ super(kind, context, type);
+ }
+
+ @Override
+ SyntheticClasspathClassDefinition lookupDefinition(Function<DexType, DexClass> definitions) {
+ DexClass clazz = definitions.apply(type);
+ if (clazz == null) {
+ return null;
+ }
+ assert clazz.isClasspathClass();
+ return new SyntheticClasspathClassDefinition(getKind(), getContext(), clazz.asClasspathClass());
+ }
+
+ @Override
+ SyntheticClasspathClassReference rewrite(NonIdentityGraphLens lens) {
+ assert type == lens.lookupType(type)
+ : "Unexpected classpath rewrite of type " + type.toSourceString();
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathDefinition.java
new file mode 100644
index 0000000..0904dff
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticClasspathDefinition.java
@@ -0,0 +1,12 @@
+// 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.synthesis;
+
+import com.android.tools.r8.graph.DexClasspathClass;
+
+public interface SyntheticClasspathDefinition {
+
+ DexClasspathClass getHolder();
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
index c04ad0a..071e7b6 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.synthesis;
-import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
@@ -18,7 +18,9 @@
* <p>This class is internal to the synthetic items collection, thus package-protected.
*/
abstract class SyntheticDefinition<
- R extends SyntheticReference<R, D>, D extends SyntheticDefinition<R, D>> {
+ R extends SyntheticReference<R, D, C>,
+ D extends SyntheticDefinition<R, D, C>,
+ C extends DexClass> {
private final SyntheticKind kind;
private final SynthesizingContext context;
@@ -30,6 +32,22 @@
this.context = context;
}
+ public boolean isClasspathDefinition() {
+ return false;
+ }
+
+ public SyntheticClasspathDefinition asClasspathDefinition() {
+ return null;
+ }
+
+ public boolean isProgramDefinition() {
+ return false;
+ }
+
+ public SyntheticProgramDefinition asProgramDefinition() {
+ return null;
+ }
+
abstract R toReference();
final SyntheticKind getKind() {
@@ -40,7 +58,7 @@
return context;
}
- abstract DexProgramClass getHolder();
+ public abstract C getHolder();
final HashCode computeHash(RepresentativeMap map, boolean intermediate) {
Hasher hasher = Hashing.murmur3_128().newHasher();
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index ca29c94..128fcef 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -172,7 +172,7 @@
}
}
- public static class EquivalenceGroup<T extends SyntheticDefinition<?, T>> {
+ public static class EquivalenceGroup<T extends SyntheticDefinition<?, T, ?>> {
private final List<T> members;
public EquivalenceGroup(T representative, List<T> members) {
@@ -260,7 +260,7 @@
.build());
}
- private <R extends SyntheticReference<R, D>, D extends SyntheticDefinition<R, D>>
+ private <R extends SyntheticReference<R, D, ?>, D extends SyntheticDefinition<R, D, ?>>
Map<DexType, EquivalenceGroup<D>> computeEquivalences(
AppView<?> appView,
ImmutableCollection<R> references,
@@ -380,7 +380,7 @@
private static DexApplication buildLensAndProgram(
AppView<?> appView,
Map<DexType, EquivalenceGroup<SyntheticMethodDefinition>> syntheticMethodGroups,
- Map<DexType, EquivalenceGroup<SyntheticClassDefinition>> syntheticClassGroups,
+ Map<DexType, EquivalenceGroup<SyntheticProgramClassDefinition>> syntheticClassGroups,
MainDexClasses mainDexClasses,
Builder lensBuilder,
List<DexProgramClass> newSyntheticClasses) {
@@ -426,14 +426,14 @@
List<DexProgramClass> deduplicatedClasses = new ArrayList<>();
syntheticClassGroups.forEach(
(syntheticType, syntheticGroup) -> {
- SyntheticClassDefinition representative = syntheticGroup.getRepresentative();
+ SyntheticProgramClassDefinition representative = syntheticGroup.getRepresentative();
SynthesizingContext context = representative.getContext();
context.registerPrefixRewriting(syntheticType, appView);
- DexProgramClass externalSyntheticClass = representative.getProgramClass();
+ DexProgramClass externalSyntheticClass = representative.getHolder();
newSyntheticClasses.add(externalSyntheticClass);
addSyntheticMarker(representative.getKind(), externalSyntheticClass, context, appView);
- for (SyntheticClassDefinition member : syntheticGroup.getMembers()) {
- DexProgramClass memberClass = member.getProgramClass();
+ for (SyntheticProgramClassDefinition member : syntheticGroup.getMembers()) {
+ DexProgramClass memberClass = member.getHolder();
DexType memberType = memberClass.getType();
pruned.add(memberType);
if (memberType != syntheticType) {
@@ -495,7 +495,7 @@
(syntheticType, syntheticGroup) -> {
DexProgramClass externalSyntheticClass = appForLookup.programDefinitionFor(syntheticType);
newSyntheticClasses.add(externalSyntheticClass);
- for (SyntheticClassDefinition member : syntheticGroup.getMembers()) {
+ for (SyntheticProgramClassDefinition member : syntheticGroup.getMembers()) {
addMainDexAndSynthesizedFromForMember(
member,
externalSyntheticClass,
@@ -542,8 +542,8 @@
private static DexProgramClass createExternalMethodClass(
DexType syntheticType, SyntheticMethodDefinition representative, DexItemFactory factory) {
- SyntheticClassBuilder builder =
- new SyntheticClassBuilder(syntheticType, representative.getContext(), factory);
+ SyntheticProgramClassBuilder builder =
+ new SyntheticProgramClassBuilder(syntheticType, representative.getContext(), factory);
// TODO(b/158159959): Support grouping multiple methods per synthetic class.
builder.addMethod(
methodBuilder -> {
@@ -560,7 +560,7 @@
}
private static void addMainDexAndSynthesizedFromForMember(
- SyntheticDefinition<?, ?> member,
+ SyntheticDefinition<?, ?, ?> member,
DexProgramClass externalSyntheticClass,
MainDexClasses mainDexClasses,
Set<DexType> derivedMainDexTypes,
@@ -584,7 +584,7 @@
return options.intermediate && !options.cfToCfDesugar;
}
- private <T extends SyntheticDefinition<?, T>>
+ private <T extends SyntheticDefinition<?, T, ?>>
Map<DexType, EquivalenceGroup<T>> computeActualEquivalences(
Collection<List<T>> potentialEquivalences,
Map<DexType, NumberGenerator> generators,
@@ -627,7 +627,7 @@
return equivalences;
}
- private static <T extends SyntheticDefinition<?, T>> List<List<T>> groupEquivalent(
+ private static <T extends SyntheticDefinition<?, T, ?>> List<List<T>> groupEquivalent(
List<T> potentialEquivalence, boolean intermediate, GraphLens graphLens) {
List<List<T>> groups = new ArrayList<>();
// Each other member is in a shared group if it is actually equivalent to the first member.
@@ -649,7 +649,7 @@
return groups;
}
- private static <T extends SyntheticDefinition<?, T>> boolean checkGroupsAreDistinct(
+ private static <T extends SyntheticDefinition<?, T, ?>> boolean checkGroupsAreDistinct(
EquivalenceGroup<T> g1, EquivalenceGroup<T> g2, GraphLens graphLens) {
int order = g1.compareToIncludingContext(g2, graphLens);
assert order != 0;
@@ -657,7 +657,7 @@
return true;
}
- private static <T extends SyntheticDefinition<?, T>> T findDeterministicRepresentative(
+ private static <T extends SyntheticDefinition<?, T, ?>> T findDeterministicRepresentative(
List<T> members, GraphLens graphLens) {
// Pick a deterministic member as representative.
T smallest = members.get(0);
@@ -695,7 +695,7 @@
return externalType;
}
- private static <T extends SyntheticDefinition<?, T>>
+ private static <T extends SyntheticDefinition<?, T, ?>>
Collection<List<T>> computePotentialEquivalences(
Map<DexType, T> definitions,
boolean intermediate,
@@ -729,7 +729,7 @@
return equivalences.values();
}
- private <R extends SyntheticReference<R, D>, D extends SyntheticDefinition<R, D>>
+ private <R extends SyntheticReference<R, D, ?>, D extends SyntheticDefinition<R, D, ?>>
Map<DexType, D> lookupDefinitions(AppView<?> appView, Collection<R> references) {
Map<DexType, D> definitions = new IdentityHashMap<>(references.size());
for (R reference : references) {
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 9c03710..657db43 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
@@ -49,7 +50,7 @@
private final Map<DexType, DexProgramClass> legacyClasses = new ConcurrentHashMap<>();
/** Thread safe collection of synthetic items not yet committed to the application. */
- private final ConcurrentHashMap<DexType, SyntheticDefinition<?, ?>> nonLegacyDefinitions =
+ private final ConcurrentHashMap<DexType, SyntheticDefinition<?, ?, ?>> nonLegacyDefinitions =
new ConcurrentHashMap<>();
boolean isEmpty() {
@@ -66,11 +67,13 @@
return true;
}
- Collection<DexProgramClass> getAllClasses() {
+ Collection<DexProgramClass> getAllProgramClasses() {
List<DexProgramClass> allPending =
new ArrayList<>(nonLegacyDefinitions.size() + legacyClasses.size());
- for (SyntheticDefinition<?, ?> item : nonLegacyDefinitions.values()) {
- allPending.add(item.getHolder());
+ for (SyntheticDefinition<?, ?, ?> item : nonLegacyDefinitions.values()) {
+ if (item.isProgramDefinition()) {
+ allPending.add(item.asProgramDefinition().getHolder());
+ }
}
allPending.addAll(legacyClasses.values());
return Collections.unmodifiableList(allPending);
@@ -121,7 +124,7 @@
});
} else if (marker.isSyntheticClass()) {
builder.addNonLegacyClass(
- new SyntheticClassDefinition(marker.getKind(), marker.getContext(), clazz));
+ new SyntheticProgramClassDefinition(marker.getKind(), marker.getContext(), clazz));
}
}
CommittedSyntheticsCollection committed = builder.build();
@@ -148,11 +151,13 @@
@Override
public DexClass definitionFor(DexType type, Function<DexType, DexClass> baseDefinitionFor) {
- DexProgramClass clazz = pending.legacyClasses.get(type);
+ DexClass clazz = pending.legacyClasses.get(type);
if (clazz == null) {
- SyntheticDefinition<?, ?> item = pending.nonLegacyDefinitions.get(type);
+ SyntheticDefinition<?, ?, ?> item = pending.nonLegacyDefinitions.get(type);
if (item != null) {
clazz = item.getHolder();
+ assert clazz.isProgramClass() == item.isProgramDefinition();
+ assert clazz.isClasspathClass() == item.isClasspathDefinition();
}
}
if (clazz != null) {
@@ -168,7 +173,7 @@
: "Uncommitted synthetics: "
+ pending.nonLegacyDefinitions.keySet().stream()
.map(DexType::getName)
- .collect(Collectors.joining());
+ .collect(Collectors.joining(", "));
return true;
}
@@ -177,7 +182,7 @@
}
public Collection<DexProgramClass> getPendingSyntheticClasses() {
- return pending.getAllClasses();
+ return pending.getAllProgramClasses();
}
private boolean isCommittedSynthetic(DexType type) {
@@ -213,9 +218,9 @@
DexProgramClass clazz,
Predicate<DexProgramClass> ifIsLambda,
Predicate<DexProgramClass> ifNotLambda) {
- SyntheticReference<?, ?> reference = committed.getNonLegacyItem(clazz.getType());
+ SyntheticReference<?, ?, ?> reference = committed.getNonLegacyItem(clazz.getType());
if (reference == null) {
- SyntheticDefinition<?, ?> definition = pending.nonLegacyDefinitions.get(clazz.getType());
+ SyntheticDefinition<?, ?, ?> definition = pending.nonLegacyDefinitions.get(clazz.getType());
if (definition != null) {
reference = definition.toReference();
}
@@ -242,11 +247,11 @@
private SynthesizingContext getSynthesizingContext(ProgramDefinition context) {
DexType contextType = context.getContextType();
- SyntheticDefinition<?, ?> existingDefinition = pending.nonLegacyDefinitions.get(contextType);
+ SyntheticDefinition<?, ?, ?> existingDefinition = pending.nonLegacyDefinitions.get(contextType);
if (existingDefinition != null) {
return existingDefinition.getContext();
}
- SyntheticReference<?, ?> existingReference = committed.getNonLegacyItem(contextType);
+ SyntheticReference<?, ?, ?> existingReference = committed.getNonLegacyItem(contextType);
if (existingReference != null) {
return existingReference.getContext();
}
@@ -270,16 +275,29 @@
DexProgramClass context,
DexItemFactory factory,
Supplier<String> syntheticIdSupplier,
- Consumer<SyntheticClassBuilder> fn) {
+ Consumer<SyntheticProgramClassBuilder> fn) {
// Obtain the outer synthesizing context in the case the context itself is synthetic.
// This is to ensure a flat input-type -> synthetic-item mapping.
SynthesizingContext outerContext = getSynthesizingContext(context);
DexType type =
SyntheticNaming.createInternalType(kind, outerContext, syntheticIdSupplier.get(), factory);
- SyntheticClassBuilder classBuilder = new SyntheticClassBuilder(type, outerContext, factory);
+ SyntheticProgramClassBuilder classBuilder =
+ new SyntheticProgramClassBuilder(type, outerContext, factory);
fn.accept(classBuilder);
DexProgramClass clazz = classBuilder.build();
- addPendingDefinition(new SyntheticClassDefinition(kind, outerContext, clazz));
+ addPendingDefinition(new SyntheticProgramClassDefinition(kind, outerContext, clazz));
+ return clazz;
+ }
+
+ public DexClasspathClass createClasspathClass(
+ SyntheticKind kind, DexType type, DexClass context, DexItemFactory factory) {
+ // Obtain the outer synthesizing context in the case the context itself is synthetic.
+ // This is to ensure a flat input-type -> synthetic-item mapping.
+ SynthesizingContext outerContext = SynthesizingContext.fromNonSyntheticInputContext(context);
+ SyntheticClasspathClassBuilder classBuilder =
+ new SyntheticClasspathClassBuilder(type, outerContext, factory);
+ DexClasspathClass clazz = classBuilder.build();
+ addPendingDefinition(new SyntheticClasspathClassDefinition(kind, outerContext, clazz));
return clazz;
}
@@ -322,7 +340,8 @@
SynthesizingContext outerContext = getSynthesizingContext(context);
DexType type =
SyntheticNaming.createInternalType(kind, outerContext, syntheticIdSupplier.get(), factory);
- SyntheticClassBuilder classBuilder = new SyntheticClassBuilder(type, outerContext, factory);
+ SyntheticProgramClassBuilder classBuilder =
+ new SyntheticProgramClassBuilder(type, outerContext, factory);
DexProgramClass clazz =
classBuilder
.addMethod(fn.andThen(m -> m.setName(SyntheticNaming.INTERNAL_SYNTHETIC_METHOD_PREFIX)))
@@ -332,7 +351,7 @@
return method;
}
- private void addPendingDefinition(SyntheticDefinition<?, ?> definition) {
+ private void addPendingDefinition(SyntheticDefinition<?, ?, ?> definition) {
pending.nonLegacyDefinitions.put(definition.getHolder().getType(), definition);
}
@@ -365,26 +384,34 @@
assert verifyClassesAreInApp(application, pending.legacyClasses.values());
builder.addLegacyClasses(pending.legacyClasses.values());
// Compute the synthetic additions and add them to the application.
- ImmutableList<DexType> additions;
+ ImmutableList<DexType> committedProgramTypes;
DexApplication amendedApplication;
if (pending.nonLegacyDefinitions.isEmpty()) {
- additions = ImmutableList.of();
+ committedProgramTypes = ImmutableList.of();
amendedApplication = application;
} else {
DexApplication.Builder<?> appBuilder = application.builder();
- ImmutableList.Builder<DexType> additionsBuilder = ImmutableList.builder();
- for (SyntheticDefinition<?, ?> definition : pending.nonLegacyDefinitions.values()) {
+ ImmutableList.Builder<DexType> committedProgramTypesBuilder = ImmutableList.builder();
+ for (SyntheticDefinition<?, ?, ?> definition : pending.nonLegacyDefinitions.values()) {
if (!removedClasses.contains(definition.getHolder().getType())) {
- additionsBuilder.add(definition.getHolder().getType());
- appBuilder.addProgramClass(definition.getHolder());
+ if (definition.isProgramDefinition()) {
+ committedProgramTypesBuilder.add(definition.getHolder().getType());
+ appBuilder.addProgramClass(definition.asProgramDefinition().getHolder());
+ } else {
+ assert definition.isClasspathDefinition();
+ appBuilder.addClasspathClass(definition.asClasspathDefinition().getHolder());
+ }
builder.addItem(definition);
}
}
- additions = additionsBuilder.build();
+ committedProgramTypes = committedProgramTypesBuilder.build();
amendedApplication = appBuilder.build();
}
return new CommittedItems(
- nextSyntheticId, amendedApplication, builder.build().pruneItems(prunedItems), additions);
+ nextSyntheticId,
+ amendedApplication,
+ builder.build().pruneItems(prunedItems),
+ committedProgramTypes);
}
private static boolean verifyClassesAreInApp(
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
index 60e3079..ab4cd49 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
@@ -20,14 +20,14 @@
Code generate(DexMethod method);
}
- private final SyntheticClassBuilder parent;
+ private final SyntheticClassBuilder<?, ?> parent;
private DexString name = null;
private DexProto proto = null;
private CfVersion classFileVersion;
private SyntheticCodeGenerator codeGenerator = null;
private MethodAccessFlags accessFlags = null;
- SyntheticMethodBuilder(SyntheticClassBuilder parent) {
+ SyntheticMethodBuilder(SyntheticClassBuilder<?, ?> parent) {
this.parent = parent;
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodDefinition.java
index 0ba1127..87393f7 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodDefinition.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.structural.RepresentativeMap;
import com.google.common.hash.Hasher;
+import java.util.function.Consumer;
/**
* Definition of a synthetic method item.
@@ -15,7 +16,9 @@
* <p>This class is internal to the synthetic items collection, thus package-protected.
*/
class SyntheticMethodDefinition
- extends SyntheticDefinition<SyntheticMethodReference, SyntheticMethodDefinition> {
+ extends SyntheticDefinition<
+ SyntheticMethodReference, SyntheticMethodDefinition, DexProgramClass>
+ implements SyntheticProgramDefinition {
private final ProgramMethod method;
@@ -24,17 +27,34 @@
this.method = method;
}
+ @Override
+ public void apply(
+ Consumer<SyntheticMethodDefinition> onMethod,
+ Consumer<SyntheticProgramClassDefinition> onClass) {
+ onMethod.accept(this);
+ }
+
public ProgramMethod getMethod() {
return method;
}
@Override
+ public boolean isProgramDefinition() {
+ return true;
+ }
+
+ @Override
+ public SyntheticProgramDefinition asProgramDefinition() {
+ return this;
+ }
+
+ @Override
SyntheticMethodReference toReference() {
return new SyntheticMethodReference(getKind(), getContext(), method.getReference());
}
@Override
- DexProgramClass getHolder() {
+ public DexProgramClass getHolder() {
return method.getHolder();
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
index cade86e..09a0f1a 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodReference.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.ProgramMethod;
@@ -18,7 +19,8 @@
* <p>This class is internal to the synthetic items collection, thus package-protected.
*/
class SyntheticMethodReference
- extends SyntheticReference<SyntheticMethodReference, SyntheticMethodDefinition> {
+ extends SyntheticReference<SyntheticMethodReference, SyntheticMethodDefinition, DexProgramClass>
+ implements SyntheticProgramReference {
final DexMethod method;
SyntheticMethodReference(SyntheticKind kind, SynthesizingContext context, DexMethod method) {
@@ -73,8 +75,9 @@
}
@Override
- void apply(
- Consumer<SyntheticMethodReference> onMethod, Consumer<SyntheticClassReference> onClass) {
+ public void apply(
+ Consumer<SyntheticMethodReference> onMethod,
+ Consumer<SyntheticProgramClassReference> onClass) {
onMethod.accept(this);
}
}
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 93c3f64..b33e260 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -22,12 +22,14 @@
*/
public enum SyntheticKind {
// Class synthetics.
+ COMPANION_CLASS("CompanionClass", false),
LAMBDA("Lambda", false),
// Method synthetics.
BACKPORT("Backport", true),
STATIC_INTERFACE_CALL("StaticInterfaceCall", true),
TO_STRING_IF_NOT_NULL("ToStringIfNotNull", true),
THROW_CCE_IF_NOT_NULL("ThrowCCEIfNotNull", true),
+ THROW_ICCE("ThrowICCE", true),
THROW_NSME("ThrowNSME", true),
TWR_CLOSE_RESOURCE("TwrCloseResource", true),
SERVICE_LOADER("ServiceLoad", true);
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassBuilder.java
new file mode 100644
index 0000000..6408621
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassBuilder.java
@@ -0,0 +1,27 @@
+// 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.synthesis;
+
+import com.android.tools.r8.graph.ClassKind;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
+
+public class SyntheticProgramClassBuilder
+ extends SyntheticClassBuilder<SyntheticProgramClassBuilder, DexProgramClass> {
+
+ SyntheticProgramClassBuilder(DexType type, SynthesizingContext context, DexItemFactory factory) {
+ super(type, context, factory);
+ }
+
+ @Override
+ public ClassKind<DexProgramClass> getClassKind() {
+ return ClassKind.PROGRAM;
+ }
+
+ @Override
+ public SyntheticProgramClassBuilder self() {
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassDefinition.java
new file mode 100644
index 0000000..8b42eb6
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassDefinition.java
@@ -0,0 +1,74 @@
+// 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.synthesis;
+
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.utils.structural.RepresentativeMap;
+import com.google.common.hash.Hasher;
+import java.util.function.Consumer;
+
+/**
+ * Definition of a synthetic class item.
+ *
+ * <p>This class is internal to the synthetic items collection, thus package-protected.
+ */
+class SyntheticProgramClassDefinition
+ extends SyntheticClassDefinition<
+ SyntheticProgramClassReference, SyntheticProgramClassDefinition, DexProgramClass>
+ implements SyntheticProgramDefinition {
+
+ SyntheticProgramClassDefinition(
+ SyntheticKind kind, SynthesizingContext context, DexProgramClass clazz) {
+ super(kind, context, clazz);
+ }
+
+ @Override
+ public void apply(
+ Consumer<SyntheticMethodDefinition> onMethod,
+ Consumer<SyntheticProgramClassDefinition> onClass) {
+ onClass.accept(this);
+ }
+
+ @Override
+ public boolean isProgramDefinition() {
+ return true;
+ }
+
+ @Override
+ public SyntheticProgramDefinition asProgramDefinition() {
+ return this;
+ }
+
+ @Override
+ SyntheticProgramClassReference toReference() {
+ return new SyntheticProgramClassReference(getKind(), getContext(), clazz.getType());
+ }
+
+ @Override
+ public boolean isValid() {
+ return clazz.isPublic() && clazz.isFinal() && clazz.accessFlags.isSynthetic();
+ }
+
+ @Override
+ void internalComputeHash(Hasher hasher, RepresentativeMap map) {
+ clazz.hashWithTypeEquivalence(hasher, map);
+ }
+
+ @Override
+ int internalCompareTo(SyntheticProgramClassDefinition o, RepresentativeMap map) {
+ return clazz.compareWithTypeEquivalenceTo(o.clazz, map);
+ }
+
+ @Override
+ public String toString() {
+ return "SyntheticProgramClass{ clazz = "
+ + clazz.type.toSourceString()
+ + ", kind = "
+ + getKind()
+ + ", context = "
+ + getContext()
+ + " }";
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java
new file mode 100644
index 0000000..3472268
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramClassReference.java
@@ -0,0 +1,70 @@
+// 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.synthesis;
+
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
+import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * Reference to a synthetic class item.
+ *
+ * <p>This class is internal to the synthetic items collection, thus package-protected.
+ */
+class SyntheticProgramClassReference
+ extends SyntheticClassReference<
+ SyntheticProgramClassReference, SyntheticProgramClassDefinition, DexProgramClass>
+ implements SyntheticProgramReference {
+
+ SyntheticProgramClassReference(SyntheticKind kind, SynthesizingContext context, DexType type) {
+ super(kind, context, type);
+ }
+
+ @Override
+ SyntheticProgramClassDefinition lookupDefinition(Function<DexType, DexClass> definitions) {
+ DexClass clazz = definitions.apply(type);
+ if (clazz == null) {
+ return null;
+ }
+ assert clazz.isProgramClass();
+ return new SyntheticProgramClassDefinition(getKind(), getContext(), clazz.asProgramClass());
+ }
+
+ @Override
+ SyntheticProgramClassReference rewrite(NonIdentityGraphLens lens) {
+ DexType rewritten = lens.lookupType(type);
+ // If the reference has been non-trivially rewritten the compiler has changed it and it can no
+ // longer be considered a synthetic. The context may or may not have changed.
+ if (type != rewritten && !lens.isSimpleRenaming(type, rewritten)) {
+ // If the referenced item is rewritten, it should be moved to another holder as the
+ // synthetic holder is no longer part of the synthetic collection.
+ assert SyntheticNaming.verifyNotInternalSynthetic(rewritten);
+ return null;
+ }
+ SynthesizingContext context = getContext().rewrite(lens);
+ if (context == getContext() && rewritten == type) {
+ return this;
+ }
+ // Ensure that if a synthetic moves its context moves consistently.
+ if (type != rewritten) {
+ context =
+ SynthesizingContext.fromSyntheticContextChange(rewritten, context, lens.dexItemFactory());
+ if (context == null) {
+ return null;
+ }
+ }
+ return new SyntheticProgramClassReference(getKind(), context, rewritten);
+ }
+
+ @Override
+ public void apply(
+ Consumer<SyntheticMethodReference> onMethod,
+ Consumer<SyntheticProgramClassReference> onClass) {
+ onClass.accept(this);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramDefinition.java
new file mode 100644
index 0000000..dd8953a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramDefinition.java
@@ -0,0 +1,17 @@
+// 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.synthesis;
+
+import com.android.tools.r8.graph.DexProgramClass;
+import java.util.function.Consumer;
+
+public interface SyntheticProgramDefinition {
+
+ void apply(
+ Consumer<SyntheticMethodDefinition> onMethod,
+ Consumer<SyntheticProgramClassDefinition> onClass);
+
+ DexProgramClass getHolder();
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramReference.java
new file mode 100644
index 0000000..4df1f46
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticProgramReference.java
@@ -0,0 +1,14 @@
+// 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.synthesis;
+
+import java.util.function.Consumer;
+
+public interface SyntheticProgramReference {
+
+ void apply(
+ Consumer<SyntheticMethodReference> onMethod,
+ Consumer<SyntheticProgramClassReference> onClass);
+}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticReference.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticReference.java
index ea33564..1a2d2fb 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticReference.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticReference.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-import java.util.function.Consumer;
import java.util.function.Function;
/**
@@ -16,7 +15,9 @@
* <p>This class is internal to the synthetic items collection, thus package-protected.
*/
abstract class SyntheticReference<
- R extends SyntheticReference<R, D>, D extends SyntheticDefinition<R, D>> {
+ R extends SyntheticReference<R, D, C>,
+ D extends SyntheticDefinition<R, D, C>,
+ C extends DexClass> {
private final SyntheticKind kind;
private final SynthesizingContext context;
@@ -41,7 +42,4 @@
abstract DexType getHolder();
abstract R rewrite(NonIdentityGraphLens lens);
-
- abstract void apply(
- Consumer<SyntheticMethodReference> onMethod, Consumer<SyntheticClassReference> onClass);
}
diff --git a/src/main/java/com/android/tools/r8/utils/ClasspathClassCollection.java b/src/main/java/com/android/tools/r8/utils/ClasspathClassCollection.java
index 28eb17b..e14d8ed 100644
--- a/src/main/java/com/android/tools/r8/utils/ClasspathClassCollection.java
+++ b/src/main/java/com/android/tools/r8/utils/ClasspathClassCollection.java
@@ -10,10 +10,19 @@
/** Represents a collection of classpath classes. */
public class ClasspathClassCollection extends ClassMap<DexClasspathClass> {
+
+ private ClasspathClassCollection() {
+ this(null);
+ }
+
public ClasspathClassCollection(ClassProvider<DexClasspathClass> classProvider) {
super(null, classProvider);
}
+ public static ClasspathClassCollection empty() {
+ return new ClasspathClassCollection();
+ }
+
@Override
DexClasspathClass resolveClassConflict(DexClasspathClass a, DexClasspathClass b) {
throw new CompilationError("Classpath type already present: " + a.type.toSourceString());