Merge commit '819b3dfe0b79a426565aeb717d91d2a83d64cb72' into dev-release
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index e46d5c1..85abb47 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -21,7 +21,6 @@
import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
import com.android.tools.r8.ir.optimize.AssertionsRewriter;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
-import com.android.tools.r8.ir.optimize.library.LibraryOptimizationInfoInitializer;
import com.android.tools.r8.naming.PrefixRewritingNamingLens;
import com.android.tools.r8.origin.CommandLineOrigin;
import com.android.tools.r8.utils.AndroidApp;
@@ -180,8 +179,6 @@
AppView<?> appView = AppView.createForD8(appInfo, options, rewritePrefix);
- new LibraryOptimizationInfoInitializer(appView).run();
-
IRConverter converter = new IRConverter(appView, timing, printer);
app = converter.convert(app, executor);
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexList.java b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
index 5e47207..a647cf5 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexList.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexList.java
@@ -52,6 +52,8 @@
AppView.createForR8(new AppInfoWithSubtyping(application), options);
appView.setAppServices(AppServices.builder(appView).build());
+ MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
+
RootSet mainDexRootSet =
new RootSetBuilder(appView, application, options.mainDexKeepRules).run(executor);
diff --git a/src/main/java/com/android/tools/r8/PrintUses.java b/src/main/java/com/android/tools/r8/PrintUses.java
index d8d93ab..d492e67 100644
--- a/src/main/java/com/android/tools/r8/PrintUses.java
+++ b/src/main/java/com/android/tools/r8/PrintUses.java
@@ -250,7 +250,7 @@
for (DexType type : method.method.proto.parameters.values) {
registerTypeReference(type);
}
- for (DexAnnotation annotation : method.annotations.annotations) {
+ for (DexAnnotation annotation : method.annotations().annotations) {
if (annotation.annotation.type == appInfo.dexItemFactory().annotationThrows) {
DexValueArray dexValues = (DexValueArray) annotation.annotation.elements[0].value;
for (DexValue dexValType : dexValues.getValues()) {
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 78471d6..7db3d7c 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -31,6 +31,7 @@
import com.android.tools.r8.graph.analysis.InitializedClassesInInstanceMethodsAnalysis;
import com.android.tools.r8.ir.analysis.proto.GeneratedExtensionRegistryShrinker;
import com.android.tools.r8.ir.conversion.IRConverter;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
import com.android.tools.r8.ir.desugar.NestedPrivateMethodLense;
import com.android.tools.r8.ir.desugar.R8NestBasedAccessDesugaring;
import com.android.tools.r8.ir.optimize.AssertionsRewriter;
@@ -43,7 +44,6 @@
import com.android.tools.r8.ir.optimize.UnusedArgumentsCollector;
import com.android.tools.r8.ir.optimize.UnusedArgumentsCollector.UnusedArgumentsGraphLense;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
-import com.android.tools.r8.ir.optimize.library.LibraryOptimizationInfoInitializer;
import com.android.tools.r8.jar.CfApplicationWriter;
import com.android.tools.r8.kotlin.Kotlin;
import com.android.tools.r8.kotlin.KotlinInfo;
@@ -270,6 +270,14 @@
AppView.createForR8(new AppInfoWithSubtyping(application), options);
appView.setAppServices(AppServices.builder(appView).build());
+ // Up-front check for valid library setup.
+ if (!options.mainDexKeepRules.isEmpty()) {
+ MainDexListBuilder.checkForAssumedLibraryTypes(appView.appInfo());
+ }
+ if (!options.desugaredLibraryConfiguration.getRetargetCoreLibMember().isEmpty()) {
+ BackportedMethodRewriter.checkForAssumedLibraryTypes(appView);
+ }
+
List<ProguardConfigurationRule> synthesizedProguardRules = new ArrayList<>();
timing.begin("Strip unused code");
Set<DexType> classesToRetainInnerClassAttributeFor = null;
@@ -328,8 +336,6 @@
appView.rootSet().checkAllRulesAreUsed(options);
- new LibraryOptimizationInfoInitializer(appView).run();
-
if (options.proguardSeedsConsumer != null) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bytes);
diff --git a/src/main/java/com/android/tools/r8/ResourceShrinker.java b/src/main/java/com/android/tools/r8/ResourceShrinker.java
index 21e4f10..efeccec 100644
--- a/src/main/java/com/android/tools/r8/ResourceShrinker.java
+++ b/src/main/java/com/android/tools/r8/ResourceShrinker.java
@@ -54,7 +54,6 @@
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import java.io.IOException;
-import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -232,36 +231,24 @@
}
private void processAnnotations(DexProgramClass classDef) {
- Stream<DexAnnotation> instanceFieldAnnotations =
- classDef.instanceFields().stream()
+ Stream<DexAnnotation> classAnnotations = classDef.annotations().stream();
+ Stream<DexAnnotation> fieldAnnotations =
+ Streams.stream(classDef.fields())
.filter(DexEncodedField::hasAnnotation)
- .flatMap(f -> Arrays.stream(f.annotations.annotations));
- Stream<DexAnnotation> staticFieldAnnotations =
- classDef.staticFields().stream()
- .filter(DexEncodedField::hasAnnotation)
- .flatMap(f -> Arrays.stream(f.annotations.annotations));
- Stream<DexAnnotation> virtualMethodAnnotations =
- classDef.virtualMethods().stream()
+ .flatMap(f -> f.annotations().stream());
+ Stream<DexAnnotation> methodAnnotations =
+ Streams.stream(classDef.methods())
.filter(DexEncodedMethod::hasAnnotation)
- .flatMap(m -> Arrays.stream(m.annotations.annotations));
- Stream<DexAnnotation> directMethodAnnotations =
- classDef.directMethods().stream()
- .filter(DexEncodedMethod::hasAnnotation)
- .flatMap(m -> Arrays.stream(m.annotations.annotations));
- Stream<DexAnnotation> classAnnotations = Arrays.stream(classDef.annotations.annotations);
+ .flatMap(m -> m.annotations().stream());
- Streams.concat(
- instanceFieldAnnotations,
- staticFieldAnnotations,
- virtualMethodAnnotations,
- directMethodAnnotations,
- classAnnotations)
- .forEach(annotation -> {
- for (DexAnnotationElement element : annotation.annotation.elements) {
- DexValue value = element.value;
- processAnnotationValue(value);
- }
- });
+ Streams.concat(classAnnotations, fieldAnnotations, methodAnnotations)
+ .forEach(
+ annotation -> {
+ for (DexAnnotationElement element : annotation.annotation.elements) {
+ DexValue value = element.value;
+ processAnnotationValue(value);
+ }
+ });
}
private void processIntArrayPayload(Instruction instruction) {
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 94633a0..93ee213 100644
--- a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
@@ -57,6 +57,7 @@
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.ArrayList;
@@ -64,6 +65,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
@@ -224,8 +226,42 @@
return "options.itemFactory.createString(" + quote(string.toString()) + ")";
}
+ private final Map<String, String> knownTypeFields =
+ ImmutableMap.<String, String>builder()
+ .put("Z", "booleanType")
+ .put("B", "byteType")
+ .put("C", "charType")
+ .put("D", "doubleType")
+ .put("F", "floatType")
+ .put("I", "intType")
+ .put("J", "longType")
+ .put("S", "shortType")
+ .put("V", "voidType")
+ .put("[Z", "booleanArrayType")
+ .put("[B", "byteArrayType")
+ .put("[C", "charArrayType")
+ .put("[D", "doubleArrayType")
+ .put("[F", "floatArrayType")
+ .put("[I", "intArrayType")
+ .put("[J", "longArrayType")
+ .put("[S", "shortArrayType")
+ .put("Ljava/lang/Object;", "objectType")
+ .put("Ljava/lang/Class;", "classType")
+ .put("Ljava/lang/Throwable;", "throwableType")
+ .put("Ljava/lang/String;", "stringType")
+ .put("Ljava/lang/Character;", "boxedCharType")
+ .put("Ljava/lang/CharSequence;", "charSequenceType")
+ .put("Ljava/lang/StringBuilder;", "stringBuilderType")
+ .put("Ljava/lang/AutoCloseable;", "autoCloseableType")
+ .build();
+
private String dexType(DexType type) {
- return "options.itemFactory.createType(" + quote(type.toDescriptorString()) + ")";
+ String descriptor = type.toDescriptorString();
+ String field = knownTypeFields.get(descriptor);
+ if (field != null) {
+ return "options.itemFactory." + field;
+ }
+ return "options.itemFactory.createSynthesizedType(" + quote(descriptor) + ")";
}
private String dexProto(DexProto proto) {
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 993363c..2992824 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -246,7 +246,14 @@
if (options.encodeChecksums) {
encodeChecksums(virtualFiles);
}
+ // TODO(b/149190785): Only sort the live program!
+ if (appView != null) {
+ appView.appInfo().disableDefinitionForAssert();
+ }
application.dexItemFactory.sort(namingLens);
+ if (appView != null) {
+ appView.appInfo().enableDefinitionForAssert();
+ }
assert markers == null
|| markers.isEmpty()
|| application.dexItemFactory.extractMarkers() != null;
@@ -520,10 +527,10 @@
// Append the annotations to annotations array of the class.
DexAnnotation[] copy =
ObjectArrays.concat(
- clazz.annotations.annotations,
+ clazz.annotations().annotations,
annotations.toArray(DexAnnotation.EMPTY_ARRAY),
DexAnnotation.class);
- clazz.annotations = new DexAnnotationSet(copy);
+ clazz.setAnnotations(new DexAnnotationSet(copy));
}
// Clear the attribute structures now that they are represented in annotations.
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 5cbd975..53f65b6 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -25,6 +25,7 @@
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexEncodedArray;
import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItem;
@@ -38,7 +39,6 @@
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.IndexedDexItem;
-import com.android.tools.r8.graph.KeyedDexItem;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.PresortedComparable;
@@ -577,7 +577,7 @@
}
}
- private <S extends Descriptor<T, S>, T extends KeyedDexItem<S>> void writeMemberAnnotations(
+ private <S extends Descriptor<T, S>, T extends DexEncodedMember<S>> void writeMemberAnnotations(
List<T> items, ToIntFunction<T> getter) {
for (T item : items) {
dest.putInt(item.getKey().getOffset(mapping));
@@ -594,10 +594,10 @@
dest.putInt(fieldAnnotations.size());
dest.putInt(methodAnnotations.size());
dest.putInt(parameterAnnotations.size());
- writeMemberAnnotations(fieldAnnotations,
- item -> mixedSectionOffsets.getOffsetFor(item.annotations));
- writeMemberAnnotations(methodAnnotations,
- item -> mixedSectionOffsets.getOffsetFor(item.annotations));
+ writeMemberAnnotations(
+ fieldAnnotations, item -> mixedSectionOffsets.getOffsetFor(item.annotations()));
+ writeMemberAnnotations(
+ methodAnnotations, item -> mixedSectionOffsets.getOffsetFor(item.annotations()));
writeMemberAnnotations(parameterAnnotations,
item -> mixedSectionOffsets.getOffsetFor(item.parameterAnnotationsList));
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfo.java b/src/main/java/com/android/tools/r8/graph/AppInfo.java
index 03f0231..29a5995 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfo.java
@@ -29,7 +29,7 @@
private final DexApplication app;
private final DexItemFactory dexItemFactory;
- private final ConcurrentHashMap<DexType, Map<Descriptor<?,?>, KeyedDexItem<?>>> definitions =
+ private final ConcurrentHashMap<DexType, Map<Descriptor<?, ?>, DexEncodedMember<?>>> definitions =
new ConcurrentHashMap<>();
// For some optimizations, e.g. optimizing synthetic classes, we may need to resolve the current
// class being optimized.
@@ -101,8 +101,8 @@
return Collections.unmodifiableCollection(synthesizedClasses.values());
}
- private Map<Descriptor<?,?>, KeyedDexItem<?>> computeDefinitions(DexType type) {
- Builder<Descriptor<?,?>, KeyedDexItem<?>> builder = ImmutableMap.builder();
+ private Map<Descriptor<?, ?>, DexEncodedMember<?>> computeDefinitions(DexType type) {
+ Builder<Descriptor<?, ?>, DexEncodedMember<?>> builder = ImmutableMap.builder();
DexClass clazz = definitionFor(type);
if (clazz != null) {
clazz.forEachMethod(method -> builder.put(method.getKey(), method));
@@ -186,14 +186,15 @@
return (DexEncodedField) getDefinitions(field.holder).get(field);
}
- private Map<Descriptor<?,?>, KeyedDexItem<?>> getDefinitions(DexType type) {
- Map<Descriptor<?,?>, KeyedDexItem<?>> typeDefinitions = definitions.get(type);
+ private Map<Descriptor<?, ?>, DexEncodedMember<?>> getDefinitions(DexType type) {
+ Map<Descriptor<?, ?>, DexEncodedMember<?>> typeDefinitions = definitions.get(type);
if (typeDefinitions != null) {
return typeDefinitions;
}
typeDefinitions = computeDefinitions(type);
- Map<Descriptor<?,?>, KeyedDexItem<?>> existing = definitions.putIfAbsent(type, typeDefinitions);
+ Map<Descriptor<?, ?>, DexEncodedMember<?>> existing =
+ definitions.putIfAbsent(type, typeDefinitions);
return existing != null ? existing : typeDefinitions;
}
@@ -673,4 +674,9 @@
}
}
+ // TODO(b/149190785): Remove once fixed.
+ public void enableDefinitionForAssert() {}
+
+ // TODO(b/149190785): Remove once fixed.
+ public void disableDefinitionForAssert() {}
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
index 6630f9c..cefb55a 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithClassHierarchy.java
@@ -4,12 +4,18 @@
package com.android.tools.r8.graph;
+import static com.android.tools.r8.utils.TraversalContinuation.BREAK;
+import static com.android.tools.r8.utils.TraversalContinuation.CONTINUE;
+
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
+import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.collect.Sets;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
/* Specific subclass of AppInfo designed to support desugaring in D8. Desugaring requires a
* minimal amount of knowledge in the overall program, provided through classpath. Basic
@@ -37,6 +43,92 @@
return this;
}
+ /**
+ * Primitive traversal over all supertypes of a given type.
+ *
+ * <p>No order is guaranteed for the traversal, but a given type will be visited at most once. The
+ * given type is *not* visited. The function indicates if traversal should continue or break. The
+ * result of the traversal is BREAK iff the function returned BREAK.
+ */
+ public TraversalContinuation traverseSuperTypes(
+ final DexClass clazz, BiFunction<DexType, Boolean, TraversalContinuation> fn) {
+ // We do an initial zero-allocation pass over the class super chain as it does not require a
+ // worklist/seen-set. Only if the traversal is not aborted and there actually are interfaces,
+ // do we continue traversal over the interface types. This is assuming that the second pass
+ // over the super chain is less expensive than the eager allocation of the worklist.
+ int interfaceCount = 0;
+ {
+ DexClass currentClass = clazz;
+ while (currentClass != null) {
+ interfaceCount += currentClass.interfaces.values.length;
+ if (currentClass.superType == null) {
+ break;
+ }
+ TraversalContinuation stepResult = fn.apply(currentClass.superType, false);
+ if (stepResult.shouldBreak()) {
+ return stepResult;
+ }
+ currentClass = definitionFor(currentClass.superType);
+ }
+ }
+ if (interfaceCount == 0) {
+ return CONTINUE;
+ }
+ // Interfaces exist, create a worklist and seen set to ensure single visits.
+ Set<DexType> seen = Sets.newIdentityHashSet();
+ Deque<DexType> worklist = new ArrayDeque<>();
+ // Populate the worklist with the direct interfaces of the super chain.
+ {
+ DexClass currentClass = clazz;
+ while (currentClass != null) {
+ for (DexType iface : currentClass.interfaces.values) {
+ if (seen.add(iface)) {
+ TraversalContinuation stepResult = fn.apply(iface, true);
+ if (stepResult.shouldBreak()) {
+ return stepResult;
+ }
+ worklist.addLast(iface);
+ }
+ }
+ if (currentClass.superType == null) {
+ break;
+ }
+ currentClass = definitionFor(currentClass.superType);
+ }
+ }
+ // Iterate all interfaces.
+ while (!worklist.isEmpty()) {
+ DexType type = worklist.removeFirst();
+ DexClass definition = definitionFor(type);
+ if (definition != null) {
+ for (DexType iface : definition.interfaces.values) {
+ if (seen.add(iface)) {
+ TraversalContinuation stepResult = fn.apply(iface, true);
+ if (stepResult.shouldBreak()) {
+ return stepResult;
+ }
+ worklist.addLast(iface);
+ }
+ }
+ }
+ }
+ return CONTINUE;
+ }
+
+ /**
+ * Iterate each super type of class.
+ *
+ * <p>Same as traverseSuperTypes, but unconditionally visits all.
+ */
+ public void forEachSuperType(final DexClass clazz, BiConsumer<DexType, Boolean> fn) {
+ traverseSuperTypes(
+ clazz,
+ (type, isInterface) -> {
+ fn.accept(type, isInterface);
+ return CONTINUE;
+ });
+ }
+
public boolean isSubtype(DexType subtype, DexType supertype) {
assert subtype != null;
assert supertype != null;
@@ -60,30 +152,15 @@
if (!subtype.isClassType() || !supertype.isClassType()) {
return false;
}
- Deque<DexType> workList = new ArrayDeque<>();
- workList.addFirst(subtype);
- while (!workList.isEmpty()) {
- DexType type = workList.pollFirst();
- DexClass subtypeClass = definitionFor(type);
- if (subtypeClass == null) {
- // Collect missing types for future reporting?
- continue;
- }
- if (subtypeClass.superType == supertype) {
- return true;
- }
- if (subtypeClass.superType != null) {
- workList.add(subtypeClass.superType);
- }
- for (DexType itf : subtypeClass.interfaces.values) {
- if (itf == supertype) {
- return true;
- }
- workList.add(itf);
- }
+ DexClass clazz = definitionFor(subtype);
+ if (clazz == null) {
+ return false;
}
// TODO(b/123506120): Report missing types when the predicate is inconclusive.
- return false;
+ return traverseSuperTypes(
+ clazz,
+ (type, isInterface) -> type == supertype ? BREAK : CONTINUE)
+ .shouldBreak();
}
public boolean isRelatedBySubtyping(DexType type, DexType other) {
@@ -105,33 +182,16 @@
return clazz.isInterface() ? Collections.singleton(type) : Collections.emptySet();
}
- // Slow path traverses the full hierarchy.
+ // Slow path traverses the full super type hierarchy.
Set<DexType> interfaces = Sets.newIdentityHashSet();
if (clazz.isInterface()) {
interfaces.add(type);
}
- Deque<DexType> workList = new ArrayDeque<>();
- if (clazz.superType != null && clazz.superType != dexItemFactory().objectType) {
- workList.add(clazz.superType);
- }
- Collections.addAll(interfaces, clazz.interfaces.values);
- Collections.addAll(workList, clazz.interfaces.values);
- while (!workList.isEmpty()) {
- DexType item = workList.pollFirst();
- DexClass definition = definitionFor(item);
- if (definition == null) {
- // Collect missing types for future reporting?
- continue;
+ forEachSuperType(clazz, (dexType, isInterface) -> {
+ if (isInterface) {
+ interfaces.add(dexType);
}
- if (definition.superType != null && definition.superType != dexItemFactory().objectType) {
- workList.add(definition.superType);
- }
- for (DexType iface : definition.interfaces.values) {
- if (interfaces.add(iface)) {
- workList.add(iface);
- }
- }
- }
+ });
return interfaces;
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 63074c4..9f7b4cf 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
import com.android.tools.r8.ir.desugar.PrefixRewritingMapper;
import com.android.tools.r8.ir.optimize.CallSiteOptimizationInfoPropagator;
+import com.android.tools.r8.ir.optimize.library.LibraryMethodOptimizer;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.utils.InternalOptions;
@@ -50,6 +51,7 @@
// Optimizations.
private final CallSiteOptimizationInfoPropagator callSiteOptimizationInfoPropagator;
+ private final LibraryMethodOptimizer libraryMethodOptimizer;
private final ProtoShrinker protoShrinker;
// Optimization results.
@@ -92,6 +94,8 @@
this.callSiteOptimizationInfoPropagator = null;
}
+ this.libraryMethodOptimizer = new LibraryMethodOptimizer(this);
+
if (enableWholeProgramOptimizations() && options.protoShrinking().isProtoShrinkingEnabled()) {
this.protoShrinker = new ProtoShrinker(withLiveness());
} else {
@@ -222,6 +226,10 @@
return callSiteOptimizationInfoPropagator;
}
+ public LibraryMethodOptimizer libraryMethodOptimizer() {
+ return libraryMethodOptimizer;
+ }
+
public ProtoShrinker protoShrinker() {
return protoShrinker;
}
diff --git a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
index 2ee2c0c..2a6154d 100644
--- a/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
+++ b/src/main/java/com/android/tools/r8/graph/AssemblyWriter.java
@@ -59,7 +59,7 @@
ps.println("# Bytecode for");
ps.println("# Class: '" + clazzName + "'");
if (writeAllClassInfo) {
- writeAnnotations(clazz.annotations, ps);
+ writeAnnotations(clazz.annotations(), ps);
ps.println("# Flags: '" + clazz.accessFlags + "'");
if (clazz.superType != application.dexItemFactory.objectType) {
ps.println("# Extends: '" + clazz.superType.toSourceString() + "'");
@@ -87,7 +87,7 @@
FieldSignature fieldSignature = naming != null
? naming.originalSignatureOf(field.field)
: FieldSignature.fromDexField(field.field);
- writeAnnotations(field.annotations, ps);
+ writeAnnotations(field.annotations(), ps);
ps.print(field.accessFlags + " ");
ps.println(fieldSignature);
}
@@ -106,7 +106,7 @@
: method.method.name.toString();
ps.println("#");
ps.println("# Method: '" + methodName + "':");
- writeAnnotations(method.annotations, ps);
+ writeAnnotations(method.annotations(), ps);
ps.println("# " + method.accessFlags);
ps.println("#");
ps.println();
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
index 0f60e07..50b4b2f 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
@@ -338,30 +338,25 @@
}
public static Collection<DexType> readAnnotationSynthesizedClassMap(
- DexProgramClass programClass,
- DexItemFactory dexItemFactory) {
- DexAnnotation foundAnnotation = programClass.annotations.getFirstMatching(
- dexItemFactory.annotationSynthesizedClassMap);
+ DexProgramClass clazz, DexItemFactory dexItemFactory) {
+ DexAnnotation foundAnnotation =
+ clazz.annotations().getFirstMatching(dexItemFactory.annotationSynthesizedClassMap);
if (foundAnnotation != null) {
if (foundAnnotation.annotation.elements.length != 1) {
- throw new CompilationError(
- getInvalidSynthesizedClassMapMessage(programClass, foundAnnotation));
+ throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
}
DexAnnotationElement value = foundAnnotation.annotation.elements[0];
if (!value.name.toSourceString().equals("value")) {
- throw new CompilationError(
- getInvalidSynthesizedClassMapMessage(programClass, foundAnnotation));
+ throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
}
if (!(value.value instanceof DexValueArray)) {
- throw new CompilationError(
- getInvalidSynthesizedClassMapMessage(programClass, foundAnnotation));
+ throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
}
DexValueArray existingList = (DexValueArray) value.value;
Collection<DexType> synthesized = new ArrayList<>(existingList.values.length);
for (DexValue element : existingList.getValues()) {
if (!(element instanceof DexValueType)) {
- throw new CompilationError(
- getInvalidSynthesizedClassMapMessage(programClass, foundAnnotation));
+ throw new CompilationError(getInvalidSynthesizedClassMapMessage(clazz, foundAnnotation));
}
synthesized.add(((DexValueType) element).value);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
index 1f2d9f1..e616e9e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
@@ -30,7 +30,7 @@
parameterAnnotations = new ArrayList<>();
while (methods.hasNext()) {
DexEncodedMethod method = methods.next();
- if (!method.annotations.isEmpty()) {
+ if (!method.annotations().isEmpty()) {
methodAnnotations.add(method);
}
if (!method.parameterAnnotationsList.isEmpty()) {
@@ -44,14 +44,14 @@
fieldAnnotations = new ArrayList<>();
while (fields.hasNext()) {
DexEncodedField field = fields.next();
- if (!field.annotations.isEmpty()) {
+ if (!field.annotations().isEmpty()) {
fieldAnnotations.add(field);
}
}
}
public DexAnnotationSet getClazzAnnotations() {
- return clazz.annotations;
+ return clazz.annotations();
}
public List<DexEncodedMethod> getMethodAnnotations() {
@@ -83,7 +83,7 @@
if (!other.clazz.hasOnlyInternalizableAnnotations()) {
return false;
}
- return clazz.annotations.equals(other.clazz.annotations);
+ return clazz.annotations().equals(other.clazz.annotations());
}
return super.equals(obj);
}
@@ -91,7 +91,7 @@
@Override
public final int hashCode() {
if (classHasOnlyInternalizableAnnotations) {
- return clazz.annotations.hashCode();
+ return clazz.annotations().hashCode();
}
return super.hashCode();
}
@@ -108,8 +108,8 @@
}
private static <T extends PresortedComparable<T>> boolean isSorted(
- List<? extends KeyedDexItem<T>> items) {
- return isSorted(items, KeyedDexItem::getKey);
+ List<? extends DexEncodedMember<T>> items) {
+ return isSorted(items, DexEncodedMember::getKey);
}
private static <S, T extends Comparable<T>> boolean isSorted(
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 04251a6..dd24ed6 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
@@ -6,12 +6,15 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.utils.ArrayUtils;
+import com.google.common.collect.Sets;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.Comparator;
import java.util.List;
import java.util.Set;
+import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
+import java.util.stream.Stream;
public class DexAnnotationSet extends CachedHashValueDexItem {
@@ -33,7 +36,7 @@
}
public static DexType findDuplicateEntryType(List<DexAnnotation> annotations) {
- Set<DexType> seenTypes = new HashSet<>();
+ Set<DexType> seenTypes = Sets.newIdentityHashSet();
for (DexAnnotation annotation : annotations) {
if (!seenTypes.add(annotation.annotation.type)) {
return annotation.annotation.type;
@@ -46,6 +49,16 @@
return THE_EMPTY_ANNOTATIONS_SET;
}
+ public void forEach(Consumer<DexAnnotation> consumer) {
+ for (DexAnnotation annotation : annotations) {
+ consumer.accept(annotation);
+ }
+ }
+
+ public Stream<DexAnnotation> stream() {
+ return Arrays.stream(annotations);
+ }
+
public int size() {
return annotations.length;
}
@@ -85,7 +98,7 @@
assert sorted == sortedHashCode();
return;
}
- Arrays.sort(annotations, (a, b) -> a.annotation.type.compareTo(b.annotation.type));
+ Arrays.sort(annotations, Comparator.comparing(a -> a.annotation.type));
for (DexAnnotation annotation : annotations) {
annotation.annotation.sort();
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java
index 321b5c7..3e1a144 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -69,8 +69,6 @@
private NestHostClassAttribute nestHost;
private final List<NestMemberClassAttribute> nestMembers;
- public DexAnnotationSet annotations;
-
public DexClass(
DexString sourceFile,
DexTypeList interfaces,
@@ -88,6 +86,7 @@
DexAnnotationSet annotations,
Origin origin,
boolean skipNameValidationForTesting) {
+ super(annotations);
assert origin != null;
this.origin = origin;
this.sourceFile = sourceFile;
@@ -104,7 +103,6 @@
assert nestMembers != null;
this.enclosingMethod = enclosingMethod;
this.innerClasses = innerClasses;
- this.annotations = annotations;
if (type == superType) {
throw new CompilationError("Class " + type.toString() + " cannot extend itself");
}
@@ -131,6 +129,10 @@
Iterables.filter(Arrays.asList(staticFields), predicate::test));
}
+ public Iterable<DexEncodedMember<?>> members() {
+ return Iterables.concat(fields(), methods());
+ }
+
public Iterable<DexEncodedMethod> methods() {
return methods(Predicates.alwaysTrue());
}
@@ -369,30 +371,13 @@
* specified consumer.
*/
public void forEachAnnotation(Consumer<DexAnnotation> consumer) {
- for (DexAnnotation annotation : annotations.annotations) {
- consumer.accept(annotation);
- }
- for (DexEncodedMethod method : directMethods()) {
- for (DexAnnotation annotation : method.annotations.annotations) {
- consumer.accept(annotation);
- }
+ annotations().forEach(consumer);
+ for (DexEncodedMethod method : methods()) {
+ method.annotations().forEach(consumer);
method.parameterAnnotationsList.forEachAnnotation(consumer);
}
- for (DexEncodedMethod method : virtualMethods()) {
- for (DexAnnotation annotation : method.annotations.annotations) {
- consumer.accept(annotation);
- }
- method.parameterAnnotationsList.forEachAnnotation(consumer);
- }
- for (DexEncodedField field : instanceFields()) {
- for (DexAnnotation annotation : field.annotations.annotations) {
- consumer.accept(annotation);
- }
- }
- for (DexEncodedField field : staticFields()) {
- for (DexAnnotation annotation : field.annotations.annotations) {
- consumer.accept(annotation);
- }
+ for (DexEncodedField field : fields()) {
+ field.annotations().forEach(consumer);
}
}
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 df8a65f..dbf18c3 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDefinition.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinition.java
@@ -12,6 +12,25 @@
*/
public abstract class DexDefinition extends DexItem {
+ private DexAnnotationSet annotations;
+
+ public DexDefinition(DexAnnotationSet annotations) {
+ assert annotations != null : "Should use DexAnnotationSet.THE_EMPTY_ANNOTATIONS_SET";
+ this.annotations = annotations;
+ }
+
+ public DexAnnotationSet annotations() {
+ return annotations;
+ }
+
+ public void clearAnnotations() {
+ setAnnotations(DexAnnotationSet.empty());
+ }
+
+ public void setAnnotations(DexAnnotationSet annotations) {
+ this.annotations = annotations;
+ }
+
public boolean isDexClass() {
return false;
}
@@ -28,6 +47,14 @@
return null;
}
+ public boolean isDexEncodedMember() {
+ return false;
+ }
+
+ public DexEncodedMember<?> asDexEncodedMember() {
+ return null;
+ }
+
public boolean isDexEncodedField() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index a920005..4f332f9 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -19,12 +19,11 @@
import com.android.tools.r8.kotlin.KotlinMemberInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-public class DexEncodedField extends KeyedDexItem<DexField> {
+public class DexEncodedField extends DexEncodedMember<DexField> {
public static final DexEncodedField[] EMPTY_ARRAY = {};
public final DexField field;
public final FieldAccessFlags accessFlags;
- public DexAnnotationSet annotations;
private DexValue staticValue;
private FieldOptimizationInfo optimizationInfo = DefaultFieldOptimizationInfo.getInstance();
@@ -35,9 +34,9 @@
FieldAccessFlags accessFlags,
DexAnnotationSet annotations,
DexValue staticValue) {
+ super(annotations);
this.field = field;
this.accessFlags = accessFlags;
- this.annotations = annotations;
this.staticValue = staticValue;
}
@@ -84,7 +83,7 @@
public void collectIndexedItems(
IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
field.collectIndexedItems(indexedItems, method, instructionOffset);
- annotations.collectIndexedItems(indexedItems, method, instructionOffset);
+ annotations().collectIndexedItems(indexedItems, method, instructionOffset);
if (accessFlags.isStatic()) {
getStaticValue().collectIndexedItems(indexedItems, method, instructionOffset);
}
@@ -92,7 +91,7 @@
@Override
void collectMixedSectionItems(MixedSectionCollection mixedItems) {
- annotations.collectMixedSectionItems(mixedItems);
+ annotations().collectMixedSectionItems(mixedItems);
}
@Override
@@ -149,7 +148,7 @@
}
public boolean hasAnnotation() {
- return !annotations.isEmpty();
+ return !annotations().isEmpty();
}
public boolean hasExplicitStaticValue() {
@@ -238,7 +237,7 @@
if (this.field == field) {
return this;
}
- DexEncodedField result = new DexEncodedField(field, accessFlags, annotations, staticValue);
+ DexEncodedField result = new DexEncodedField(field, accessFlags, annotations(), staticValue);
result.optimizationInfo =
optimizationInfo.isMutableFieldOptimizationInfo()
? optimizationInfo.asMutableFieldOptimizationInfo().mutableCopy()
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
new file mode 100644
index 0000000..6987227
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMember.java
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.graph;
+
+public abstract class DexEncodedMember<T extends PresortedComparable<T>> extends DexDefinition {
+
+ public DexEncodedMember(DexAnnotationSet annotations) {
+ super(annotations);
+ }
+
+ public abstract T getKey();
+
+ @Override
+ public boolean isDexEncodedMember() {
+ return true;
+ }
+
+ @Override
+ public DexEncodedMember<?> asDexEncodedMember() {
+ return this;
+ }
+
+ @Override
+ public final boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ return other.getClass() == getClass()
+ && ((DexEncodedMember<?>) other).getKey().equals(getKey());
+ }
+
+ @Override
+ public final int hashCode() {
+ return getKey().hashCode();
+ }
+}
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 7af203c..184e15e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -76,7 +76,7 @@
import java.util.function.IntPredicate;
import org.objectweb.asm.Opcodes;
-public class DexEncodedMethod extends KeyedDexItem<DexMethod> {
+public class DexEncodedMethod extends DexEncodedMember<DexMethod> {
public static final String CONFIGURATION_DEBUGGING_PREFIX = "Shaking error: Missing method in ";
@@ -118,15 +118,16 @@
public static final DexEncodedMethod[] EMPTY_ARRAY = {};
public static final DexEncodedMethod SENTINEL =
- new DexEncodedMethod(null, null, null, ParameterAnnotationsList.empty(), null);
+ new DexEncodedMethod(
+ null, null, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null);
public static final DexEncodedMethod ANNOTATION_REFERENCE =
- new DexEncodedMethod(null, null, null, ParameterAnnotationsList.empty(), null);
+ new DexEncodedMethod(
+ null, null, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null);
public static final Int2ReferenceMap<DebugLocalInfo> NO_PARAMETER_INFO =
new Int2ReferenceArrayMap<>(0);
public final DexMethod method;
public final MethodAccessFlags accessFlags;
- public DexAnnotationSet annotations;
public ParameterAnnotationsList parameterAnnotationsList;
private Code code;
// TODO(b/128967328): towards finer-grained inlining constraints,
@@ -241,9 +242,9 @@
Code code,
int classFileVersion,
boolean d8R8Synthesized) {
+ super(annotations);
this.method = method;
this.accessFlags = accessFlags;
- this.annotations = annotations;
this.parameterAnnotationsList = parameterAnnotationsList;
this.code = code;
this.classFileVersion = classFileVersion;
@@ -605,7 +606,7 @@
if (code != null) {
code.collectIndexedItems(indexedItems, this.method);
}
- annotations.collectIndexedItems(indexedItems);
+ annotations().collectIndexedItems(indexedItems);
parameterAnnotationsList.collectIndexedItems(indexedItems);
}
@@ -620,7 +621,7 @@
if (code != null) {
code.collectMixedSectionItems(mixedItems);
}
- annotations.collectMixedSectionItems(mixedItems);
+ annotations().collectMixedSectionItems(mixedItems);
parameterAnnotationsList.collectMixedSectionItems(mixedItems);
}
@@ -821,8 +822,8 @@
DexProto proto = itemFactory.createProto(itemFactory.intType, args);
DexMethod logMethod =
itemFactory.createMethod(
- itemFactory.createType("Landroid/util/Log;"), proto, itemFactory.createString("e"));
- DexType exceptionType = itemFactory.createType("Ljava/lang/RuntimeException;");
+ itemFactory.androidUtilLogType, proto, itemFactory.createString("e"));
+ DexType exceptionType = itemFactory.runtimeExceptionType;
DexMethod exceptionInitMethod =
itemFactory.createMethod(
exceptionType,
@@ -851,7 +852,7 @@
itemFactory.createString(
CONFIGURATION_DEBUGGING_PREFIX + method.holder.toSourceString() + ": " + signature);
DexString tag = itemFactory.createString("[R8]");
- DexType logger = itemFactory.createType("Ljava/util/logging/Logger;");
+ DexType logger = itemFactory.javaUtilLoggingLoggerType;
DexMethod getLogger =
itemFactory.createMethod(
logger,
@@ -862,7 +863,7 @@
logger,
itemFactory.createProto(itemFactory.voidType, itemFactory.stringType),
itemFactory.createString("severe"));
- DexType exceptionType = itemFactory.createType("Ljava/lang/RuntimeException;");
+ DexType exceptionType = itemFactory.runtimeExceptionType;
DexMethod exceptionInitMethod =
itemFactory.createMethod(
exceptionType,
@@ -1108,7 +1109,7 @@
return new DexEncodedMethod(
newMethod,
newFlags,
- target.annotations,
+ target.annotations(),
target.parameterAnnotationsList,
new SynthesizedCode(forwardSourceCodeBuilder::build),
true);
@@ -1188,7 +1189,7 @@
public boolean hasAnnotation() {
checkIfObsolete();
- return !annotations.isEmpty() || !parameterAnnotationsList.isEmpty();
+ return !annotations().isEmpty() || !parameterAnnotationsList.isEmpty();
}
public void registerCodeReferences(UseRegistry registry) {
@@ -1271,7 +1272,7 @@
// Copy all the mutable state of a DexEncodedMethod here.
method = from.method;
accessFlags = from.accessFlags.copy();
- annotations = from.annotations;
+ annotations = from.annotations();
code = from.code;
compilationState = from.compilationState;
optimizationInfo = from.optimizationInfo.mutableCopy();
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index c38f7c6..df2402f 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -37,6 +37,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
@@ -61,6 +62,9 @@
public static final String throwableDescriptorString = "Ljava/lang/Throwable;";
+ /** Set of types that may be synthesized during compilation. */
+ private final Set<DexType> possibleCompilerSynthesizedTypes = Sets.newIdentityHashSet();
+
private final Map<DexString, DexString> strings = new ConcurrentHashMap<>();
private final Map<DexString, DexType> types = new ConcurrentHashMap<>();
private final Map<DexField, DexField> fields = new ConcurrentHashMap<>();
@@ -281,96 +285,120 @@
public final DexString throwableArrayDescriptor = createString("[Ljava/lang/Throwable;");
- public final DexType booleanType = createType(booleanDescriptor);
- public final DexType byteType = createType(byteDescriptor);
- public final DexType charType = createType(charDescriptor);
- public final DexType doubleType = createType(doubleDescriptor);
- public final DexType floatType = createType(floatDescriptor);
- public final DexType intType = createType(intDescriptor);
- public final DexType longType = createType(longDescriptor);
- public final DexType shortType = createType(shortDescriptor);
- public final DexType voidType = createType(voidDescriptor);
+ public final DexType booleanType = createStaticallyKnownType(booleanDescriptor);
+ public final DexType byteType = createStaticallyKnownType(byteDescriptor);
+ public final DexType charType = createStaticallyKnownType(charDescriptor);
+ public final DexType doubleType = createStaticallyKnownType(doubleDescriptor);
+ public final DexType floatType = createStaticallyKnownType(floatDescriptor);
+ public final DexType intType = createStaticallyKnownType(intDescriptor);
+ public final DexType longType = createStaticallyKnownType(longDescriptor);
+ public final DexType shortType = createStaticallyKnownType(shortDescriptor);
+ public final DexType voidType = createStaticallyKnownType(voidDescriptor);
- public final DexType booleanArrayType = createType(booleanArrayDescriptor);
- public final DexType byteArrayType = createType(byteArrayDescriptor);
- public final DexType charArrayType = createType(charArrayDescriptor);
- public final DexType doubleArrayType = createType(doubleArrayDescriptor);
- public final DexType floatArrayType = createType(floatArrayDescriptor);
- public final DexType intArrayType = createType(intArrayDescriptor);
- public final DexType longArrayType = createType(longArrayDescriptor);
- public final DexType shortArrayType = createType(shortArrayDescriptor);
+ public final DexType booleanArrayType = createStaticallyKnownType(booleanArrayDescriptor);
+ public final DexType byteArrayType = createStaticallyKnownType(byteArrayDescriptor);
+ public final DexType charArrayType = createStaticallyKnownType(charArrayDescriptor);
+ public final DexType doubleArrayType = createStaticallyKnownType(doubleArrayDescriptor);
+ public final DexType floatArrayType = createStaticallyKnownType(floatArrayDescriptor);
+ public final DexType intArrayType = createStaticallyKnownType(intArrayDescriptor);
+ public final DexType longArrayType = createStaticallyKnownType(longArrayDescriptor);
+ public final DexType shortArrayType = createStaticallyKnownType(shortArrayDescriptor);
- public final DexType boxedBooleanType = createType(boxedBooleanDescriptor);
- public final DexType boxedByteType = createType(boxedByteDescriptor);
- public final DexType boxedCharType = createType(boxedCharDescriptor);
- public final DexType boxedDoubleType = createType(boxedDoubleDescriptor);
- public final DexType boxedFloatType = createType(boxedFloatDescriptor);
- public final DexType boxedIntType = createType(boxedIntDescriptor);
- public final DexType boxedLongType = createType(boxedLongDescriptor);
- public final DexType boxedShortType = createType(boxedShortDescriptor);
- public final DexType boxedNumberType = createType(boxedNumberDescriptor);
- public final DexType boxedVoidType = createType(boxedVoidDescriptor);
+ public final DexType boxedBooleanType = createStaticallyKnownType(boxedBooleanDescriptor);
+ public final DexType boxedByteType = createStaticallyKnownType(boxedByteDescriptor);
+ public final DexType boxedCharType = createStaticallyKnownType(boxedCharDescriptor);
+ public final DexType boxedDoubleType = createStaticallyKnownType(boxedDoubleDescriptor);
+ public final DexType boxedFloatType = createStaticallyKnownType(boxedFloatDescriptor);
+ public final DexType boxedIntType = createStaticallyKnownType(boxedIntDescriptor);
+ public final DexType boxedLongType = createStaticallyKnownType(boxedLongDescriptor);
+ public final DexType boxedShortType = createStaticallyKnownType(boxedShortDescriptor);
+ public final DexType boxedNumberType = createStaticallyKnownType(boxedNumberDescriptor);
+ public final DexType boxedVoidType = createStaticallyKnownType(boxedVoidDescriptor);
- public final DexType charSequenceType = createType(charSequenceDescriptor);
- public final DexType charSequenceArrayType = createType(charSequenceArrayDescriptor);
- public final DexType stringType = createType(stringDescriptor);
- public final DexType stringArrayType = createType(stringArrayDescriptor);
- public final DexType objectType = createType(objectDescriptor);
- public final DexType objectArrayType = createType(objectArrayDescriptor);
- public final DexType classArrayType = createType(classArrayDescriptor);
- public final DexType enumType = createType(enumDescriptor);
- public final DexType annotationType = createType(annotationDescriptor);
- public final DexType objectsType = createType(objectsDescriptor);
- public final DexType collectionsType = createType(collectionsDescriptor);
- public final DexType iterableType = createType(iterableDescriptor);
- public final DexType mathType = createType(mathDescriptor);
- public final DexType strictMathType = createType(strictMathDescriptor);
- public final DexType referenceFieldUpdaterType = createType(referenceFieldUpdaterDescriptor);
+ public final DexType charSequenceType = createStaticallyKnownType(charSequenceDescriptor);
+ public final DexType charSequenceArrayType =
+ createStaticallyKnownType(charSequenceArrayDescriptor);
+ public final DexType stringType = createStaticallyKnownType(stringDescriptor);
+ public final DexType stringArrayType = createStaticallyKnownType(stringArrayDescriptor);
+ public final DexType objectType = createStaticallyKnownType(objectDescriptor);
+ public final DexType objectArrayType = createStaticallyKnownType(objectArrayDescriptor);
+ public final DexType classArrayType = createStaticallyKnownType(classArrayDescriptor);
+ public final DexType enumType = createStaticallyKnownType(enumDescriptor);
+ public final DexType annotationType = createStaticallyKnownType(annotationDescriptor);
+ public final DexType objectsType = createStaticallyKnownType(objectsDescriptor);
+ public final DexType collectionsType = createStaticallyKnownType(collectionsDescriptor);
+ public final DexType iterableType = createStaticallyKnownType(iterableDescriptor);
+ public final DexType mathType = createStaticallyKnownType(mathDescriptor);
+ public final DexType strictMathType = createStaticallyKnownType(strictMathDescriptor);
+ public final DexType referenceFieldUpdaterType =
+ createStaticallyKnownType(referenceFieldUpdaterDescriptor);
- public final DexType classType = createType(classDescriptor);
- public final DexType classLoaderType = createType(classLoaderDescriptor);
- public final DexType fieldType = createType(fieldDescriptor);
- public final DexType methodType = createType(methodDescriptor);
- public final DexType autoCloseableType = createType(autoCloseableDescriptor);
+ public final DexType classType = createStaticallyKnownType(classDescriptor);
+ public final DexType classLoaderType = createStaticallyKnownType(classLoaderDescriptor);
+ public final DexType fieldType = createStaticallyKnownType(fieldDescriptor);
+ public final DexType methodType = createStaticallyKnownType(methodDescriptor);
+ public final DexType autoCloseableType = createStaticallyKnownType(autoCloseableDescriptor);
- public final DexType stringBuilderType = createType(stringBuilderDescriptor);
- public final DexType stringBufferType = createType(stringBufferDescriptor);
+ public final DexType stringBuilderType = createStaticallyKnownType(stringBuilderDescriptor);
+ public final DexType stringBufferType = createStaticallyKnownType(stringBufferDescriptor);
- public final DexType varHandleType = createType(varHandleDescriptor);
- public final DexType methodHandleType = createType(methodHandleDescriptor);
- public final DexType methodTypeType = createType(methodTypeDescriptor);
- public final DexType invocationHandlerType = createType(invocationHandlerDescriptor);
- public final DexType proxyType = createType(proxyDescriptor);
- public final DexType serviceLoaderType = createType(serviceLoaderDescriptor);
+ public final DexType javaLangSystemType = createStaticallyKnownType("Ljava/lang/System;");
+ public final DexType javaIoPrintStreamType = createStaticallyKnownType("Ljava/io/PrintStream;");
+
+ public final DexType varHandleType = createStaticallyKnownType(varHandleDescriptor);
+ public final DexType methodHandleType = createStaticallyKnownType(methodHandleDescriptor);
+ public final DexType methodTypeType = createStaticallyKnownType(methodTypeDescriptor);
+ public final DexType invocationHandlerType =
+ createStaticallyKnownType(invocationHandlerDescriptor);
+ public final DexType proxyType = createStaticallyKnownType(proxyDescriptor);
+ public final DexType serviceLoaderType = createStaticallyKnownType(serviceLoaderDescriptor);
+
public final DexType serviceLoaderConfigurationErrorType =
- createType(serviceLoaderConfigurationErrorDescriptor);
- public final DexType listType = createType(listDescriptor);
- public final DexType setType = createType(setDescriptor);
- public final DexType mapType = createType(mapDescriptor);
- public final DexType mapEntryType = createType(mapEntryDescriptor);
- public final DexType collectionType = createType(collectionDescriptor);
- public final DexType comparatorType = createType(comparatorDescriptor);
- public final DexType callableType = createType(callableDescriptor);
- public final DexType supplierType = createType(supplierDescriptor);
- public final DexType consumerType = createType(consumerDescriptor);
- public final DexType runnableType = createType(runnableDescriptor);
- public final DexType optionalType = createType(optionalDescriptor);
- public final DexType optionalDoubleType = createType(optionalDoubleDescriptor);
- public final DexType optionalIntType = createType(optionalIntDescriptor);
- public final DexType optionalLongType = createType(optionalLongDescriptor);
- public final DexType streamType = createType(streamDescriptor);
+ createStaticallyKnownType(serviceLoaderConfigurationErrorDescriptor);
+ public final DexType listType = createStaticallyKnownType(listDescriptor);
+ public final DexType setType = createStaticallyKnownType(setDescriptor);
+ public final DexType mapType = createStaticallyKnownType(mapDescriptor);
+ public final DexType mapEntryType = createStaticallyKnownType(mapEntryDescriptor);
+ public final DexType abstractMapSimpleEntryType =
+ createStaticallyKnownType("Ljava/util/AbstractMap$SimpleEntry;");
+ public final DexType collectionType = createStaticallyKnownType(collectionDescriptor);
+ public final DexType comparatorType = createStaticallyKnownType(comparatorDescriptor);
+ public final DexType callableType = createStaticallyKnownType(callableDescriptor);
+ public final DexType supplierType = createStaticallyKnownType(supplierDescriptor);
+ public final DexType consumerType = createStaticallyKnownType(consumerDescriptor);
+ public final DexType runnableType = createStaticallyKnownType(runnableDescriptor);
+ public final DexType optionalType = createStaticallyKnownType(optionalDescriptor);
+ public final DexType optionalDoubleType = createStaticallyKnownType(optionalDoubleDescriptor);
+ public final DexType optionalIntType = createStaticallyKnownType(optionalIntDescriptor);
+ public final DexType optionalLongType = createStaticallyKnownType(optionalLongDescriptor);
+ public final DexType streamType = createStaticallyKnownType(streamDescriptor);
- public final DexType runtimeExceptionType = createType(runtimeExceptionDescriptor);
- public final DexType throwableType = createType(throwableDescriptor);
- public final DexType illegalAccessErrorType = createType(illegalAccessErrorDescriptor);
- public final DexType icceType = createType(icceDescriptor);
+ public final DexType doubleConsumer =
+ createStaticallyKnownType("Ljava/util/function/DoubleConsumer;");
+ public final DexType longConsumer =
+ createStaticallyKnownType("Ljava/util/function/LongConsumer;");
+ public final DexType intConsumer = createStaticallyKnownType("Ljava/util/function/IntConsumer;");
+
+ public final DexType runtimeExceptionType = createStaticallyKnownType(runtimeExceptionDescriptor);
+ public final DexType throwableType = createStaticallyKnownType(throwableDescriptor);
+ public final DexType illegalAccessErrorType =
+ createStaticallyKnownType(illegalAccessErrorDescriptor);
+ public final DexType icceType = createStaticallyKnownType(icceDescriptor);
public final DexType exceptionInInitializerErrorType =
- createType(exceptionInInitializerErrorDescriptor);
- public final DexType noClassDefFoundErrorType = createType(noClassDefFoundErrorDescriptor);
- public final DexType noSuchFieldErrorType = createType(noSuchFieldErrorDescriptor);
- public final DexType npeType = createType(npeDescriptor);
+ createStaticallyKnownType(exceptionInInitializerErrorDescriptor);
+ public final DexType noClassDefFoundErrorType =
+ createStaticallyKnownType(noClassDefFoundErrorDescriptor);
+ public final DexType noSuchFieldErrorType = createStaticallyKnownType(noSuchFieldErrorDescriptor);
+ public final DexType npeType = createStaticallyKnownType(npeDescriptor);
public final DexType reflectiveOperationExceptionType =
- createType(reflectiveOperationExceptionDescriptor);
+ createStaticallyKnownType(reflectiveOperationExceptionDescriptor);
+
+ public final DexType javaUtilLoggingLoggerType =
+ createStaticallyKnownType("Ljava/util/logging/Logger;");
+ public final DexType androidUtilLogType = createStaticallyKnownType("Landroid/util/Log;");
+
+ public final DexType androidOsBuildVersionType =
+ createStaticallyKnownType("Landroid/os/Build$VERSION;");
public final StringBuildingMethods stringBuilderMethods =
new StringBuildingMethods(stringBuilderType);
@@ -381,6 +409,7 @@
public final ObjectMethods objectMethods = new ObjectMethods();
public final StringMethods stringMethods = new StringMethods();
public final LongMethods longMethods = new LongMethods();
+ public final DoubleMethods doubleMethods = new DoubleMethods();
public final JavaUtilArraysMethods utilArraysMethods = new JavaUtilArraysMethods();
public final ThrowableMethods throwableMethods = new ThrowableMethods();
public final AssertionErrorMethods assertionErrorMethods = new AssertionErrorMethods();
@@ -402,50 +431,58 @@
public final DexString deserializeLambdaMethodName = createString("$deserializeLambda$");
public final DexProto deserializeLambdaMethodProto =
- createProto(objectType, createType("Ljava/lang/invoke/SerializedLambda;"));
+ createProto(objectType, createStaticallyKnownType("Ljava/lang/invoke/SerializedLambda;"));
// Dex system annotations.
// See https://source.android.com/devices/tech/dalvik/dex-format.html#system-annotation
- public final DexType annotationDefault = createType("Ldalvik/annotation/AnnotationDefault;");
- public final DexType annotationEnclosingClass = createType("Ldalvik/annotation/EnclosingClass;");
- public final DexType annotationEnclosingMethod = createType(
- "Ldalvik/annotation/EnclosingMethod;");
- public final DexType annotationInnerClass = createType("Ldalvik/annotation/InnerClass;");
- public final DexType annotationMemberClasses = createType("Ldalvik/annotation/MemberClasses;");
- public final DexType annotationMethodParameters = createType(
- "Ldalvik/annotation/MethodParameters;");
- public final DexType annotationSignature = createType("Ldalvik/annotation/Signature;");
- public final DexType annotationSourceDebugExtension = createType(
- "Ldalvik/annotation/SourceDebugExtension;");
- public final DexType annotationThrows = createType("Ldalvik/annotation/Throws;");
+ public final DexType annotationDefault =
+ createStaticallyKnownType("Ldalvik/annotation/AnnotationDefault;");
+ public final DexType annotationEnclosingClass =
+ createStaticallyKnownType("Ldalvik/annotation/EnclosingClass;");
+ public final DexType annotationEnclosingMethod =
+ createStaticallyKnownType("Ldalvik/annotation/EnclosingMethod;");
+ public final DexType annotationInnerClass =
+ createStaticallyKnownType("Ldalvik/annotation/InnerClass;");
+ public final DexType annotationMemberClasses =
+ createStaticallyKnownType("Ldalvik/annotation/MemberClasses;");
+ public final DexType annotationMethodParameters =
+ createStaticallyKnownType("Ldalvik/annotation/MethodParameters;");
+ public final DexType annotationSignature =
+ createStaticallyKnownType("Ldalvik/annotation/Signature;");
+ public final DexType annotationSourceDebugExtension =
+ createStaticallyKnownType("Ldalvik/annotation/SourceDebugExtension;");
+ public final DexType annotationThrows = createStaticallyKnownType("Ldalvik/annotation/Throws;");
public final DexType annotationSynthesizedClassMap =
- createType("Lcom/android/tools/r8/annotations/SynthesizedClassMap;");
+ createStaticallyKnownType("Lcom/android/tools/r8/annotations/SynthesizedClassMap;");
public final DexType annotationCovariantReturnType =
- createType("Ldalvik/annotation/codegen/CovariantReturnType;");
+ createStaticallyKnownType("Ldalvik/annotation/codegen/CovariantReturnType;");
public final DexType annotationCovariantReturnTypes =
- createType("Ldalvik/annotation/codegen/CovariantReturnType$CovariantReturnTypes;");
+ createStaticallyKnownType(
+ "Ldalvik/annotation/codegen/CovariantReturnType$CovariantReturnTypes;");
public final DexType annotationReachabilitySensitive =
- createType("Ldalvik/annotation/optimization/ReachabilitySensitive;");
+ createStaticallyKnownType("Ldalvik/annotation/optimization/ReachabilitySensitive;");
// Runtime affecting yet class-retained annotations.
public final DexType dalvikFastNativeAnnotation =
- createType("Ldalvik/annotation/optimization/FastNative;");
+ createStaticallyKnownType("Ldalvik/annotation/optimization/FastNative;");
public final DexType dalvikCriticalNativeAnnotation =
- createType("Ldalvik/annotation/optimization/CriticalNative;");
+ createStaticallyKnownType("Ldalvik/annotation/optimization/CriticalNative;");
private static final String METAFACTORY_METHOD_NAME = "metafactory";
private static final String METAFACTORY_ALT_METHOD_NAME = "altMetafactory";
- public final DexType metafactoryType = createType("Ljava/lang/invoke/LambdaMetafactory;");
- public final DexType callSiteType = createType("Ljava/lang/invoke/CallSite;");
- public final DexType lookupType = createType("Ljava/lang/invoke/MethodHandles$Lookup;");
- public final DexType iteratorType = createType("Ljava/util/Iterator;");
- public final DexType listIteratorType = createType("Ljava/util/ListIterator;");
- public final DexType enumerationType = createType("Ljava/util/Enumeration;");
- public final DexType serializableType = createType("Ljava/io/Serializable;");
- public final DexType externalizableType = createType("Ljava/io/Externalizable;");
- public final DexType cloneableType = createType("Ljava/lang/Cloneable;");
- public final DexType comparableType = createType("Ljava/lang/Comparable;");
+ public final DexType metafactoryType =
+ createStaticallyKnownType("Ljava/lang/invoke/LambdaMetafactory;");
+ public final DexType callSiteType = createStaticallyKnownType("Ljava/lang/invoke/CallSite;");
+ public final DexType lookupType =
+ createStaticallyKnownType("Ljava/lang/invoke/MethodHandles$Lookup;");
+ public final DexType iteratorType = createStaticallyKnownType("Ljava/util/Iterator;");
+ public final DexType listIteratorType = createStaticallyKnownType("Ljava/util/ListIterator;");
+ public final DexType enumerationType = createStaticallyKnownType("Ljava/util/Enumeration;");
+ public final DexType serializableType = createStaticallyKnownType("Ljava/io/Serializable;");
+ public final DexType externalizableType = createStaticallyKnownType("Ljava/io/Externalizable;");
+ public final DexType cloneableType = createStaticallyKnownType("Ljava/lang/Cloneable;");
+ public final DexType comparableType = createStaticallyKnownType("Ljava/lang/Comparable;");
public final ServiceLoaderMethods serviceLoaderMethods = new ServiceLoaderMethods();
@@ -509,7 +546,7 @@
createMethod(objectType, deserializeLambdaMethodProto, deserializeLambdaMethodName);
public final DexType stringConcatFactoryType =
- createType("Ljava/lang/invoke/StringConcatFactory;");
+ createStaticallyKnownType("Ljava/lang/invoke/StringConcatFactory;");
public final DexMethod stringConcatWithConstantsMethod =
createMethod(
@@ -633,6 +670,20 @@
}
}
+ public class DoubleMethods {
+
+ public final DexMethod isNaN;
+
+ private DoubleMethods() {
+ isNaN =
+ createMethod(
+ boxedDoubleDescriptor,
+ createString("isNaN"),
+ booleanDescriptor,
+ new DexString[] {doubleDescriptor});
+ }
+ }
+
public class JavaUtilArraysMethods {
public final DexMethod asList;
@@ -1315,20 +1366,60 @@
return markers;
}
- synchronized public DexType createType(DexString descriptor) {
+ // Non-synchronized internal create.
+ private DexType internalCreateType(DexString descriptor) {
assert !sorted;
assert descriptor != null;
DexType result = types.get(descriptor);
if (result == null) {
result = new DexType(descriptor);
- assert result.isArrayType() || result.isClassType() || result.isPrimitiveType() ||
- result.isVoidType();
+ assert result.isArrayType()
+ || result.isClassType()
+ || result.isPrimitiveType()
+ || result.isVoidType();
assert !isInternalSentinel(result);
types.put(descriptor, result);
}
return result;
}
+ private DexType createStaticallyKnownType(String descriptor) {
+ return createStaticallyKnownType(createString(descriptor));
+ }
+
+ private DexType createStaticallyKnownType(DexString descriptor) {
+ DexType type = internalCreateType(descriptor);
+ // Conservatively add all statically known types to "compiler synthesized types set".
+ addPossiblySynthesizedType(type);
+ return type;
+ }
+
+ // Safe synchronized external create. May be used for statically known types in synthetic code.
+ // See the generated BackportedMethods.java for reference.
+ public synchronized DexType createSynthesizedType(String descriptor) {
+ DexType type = internalCreateType(createString(descriptor));
+ addPossiblySynthesizedType(type);
+ return type;
+ }
+
+ private void addPossiblySynthesizedType(DexType type) {
+ if (type.isArrayType()) {
+ type = type.toBaseType(this);
+ }
+ if (type.isClassType()) {
+ possibleCompilerSynthesizedTypes.add(type);
+ }
+ }
+
+ public void forEachPossiblyCompilerSynthesizedType(Consumer<DexType> fn) {
+ possibleCompilerSynthesizedTypes.forEach(fn);
+ }
+
+ // Safe synchronized external create. Should never be used to create a statically known type!
+ public synchronized DexType createType(DexString descriptor) {
+ return internalCreateType(descriptor);
+ }
+
public DexType createType(String descriptor) {
return createType(createString(descriptor));
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 5904f98..1ac7c58 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -148,9 +148,7 @@
if (sourceFile != null) {
sourceFile.collectIndexedItems(indexedItems, method, instructionOffset);
}
- if (annotations != null) {
- annotations.collectIndexedItems(indexedItems, method, instructionOffset);
- }
+ annotations().collectIndexedItems(indexedItems, method, instructionOffset);
if (interfaces != null) {
interfaces.collectIndexedItems(indexedItems, method, instructionOffset);
}
@@ -203,13 +201,10 @@
synchronizedCollectAll(collector, staticFields);
synchronizedCollectAll(collector, instanceFields);
}
- if (annotations != null) {
- annotations.collectMixedSectionItems(collector);
- }
+ annotations().collectMixedSectionItems(collector);
if (interfaces != null) {
interfaces.collectMixedSectionItems(collector);
}
- annotations.collectMixedSectionItems(collector);
}
private static <T extends DexItem> void synchronizedCollectAll(MixedSectionCollection collection,
@@ -291,7 +286,7 @@
}
public boolean hasAnnotations() {
- return !annotations.isEmpty()
+ return !annotations().isEmpty()
|| hasAnnotations(virtualMethods)
|| hasAnnotations(directMethods)
|| hasAnnotations(staticFields)
@@ -357,11 +352,11 @@
&& isSorted(instanceFields);
}
- private static <T extends KeyedDexItem<S>, S extends PresortedComparable<S>> boolean isSorted(
+ private static <T extends DexEncodedMember<S>, S extends PresortedComparable<S>> boolean isSorted(
T[] items) {
synchronized (items) {
T[] sorted = items.clone();
- Arrays.sort(sorted, Comparator.comparing(KeyedDexItem::getKey));
+ Arrays.sort(sorted, Comparator.comparing(DexEncodedMember::getKey));
return Arrays.equals(items, sorted);
}
}
@@ -446,29 +441,8 @@
* entire scope.
*/
public boolean hasReachabilitySensitiveAnnotation(DexItemFactory factory) {
- for (DexEncodedMethod directMethod : directMethods) {
- for (DexAnnotation annotation : directMethod.annotations.annotations) {
- if (annotation.annotation.type == factory.annotationReachabilitySensitive) {
- return true;
- }
- }
- }
- for (DexEncodedMethod virtualMethod : virtualMethods) {
- for (DexAnnotation annotation : virtualMethod.annotations.annotations) {
- if (annotation.annotation.type == factory.annotationReachabilitySensitive) {
- return true;
- }
- }
- }
- for (DexEncodedField staticField : staticFields) {
- for (DexAnnotation annotation : staticField.annotations.annotations) {
- if (annotation.annotation.type == factory.annotationReachabilitySensitive) {
- return true;
- }
- }
- }
- for (DexEncodedField instanceField : instanceFields) {
- for (DexAnnotation annotation : instanceField.annotations.annotations) {
+ for (DexEncodedMember<?> member : members()) {
+ for (DexAnnotation annotation : member.annotations().annotations) {
if (annotation.annotation.type == factory.annotationReachabilitySensitive) {
return true;
}
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 3e1ed8a..b8210c8 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -210,7 +210,7 @@
public static class Builder extends DexApplication.Builder<Builder> {
- private final ImmutableList<DexLibraryClass> libraryClasses;
+ private ImmutableList<DexLibraryClass> libraryClasses;
private ImmutableList<DexClasspathClass> classpathClasses;
Builder(LazyLoadedDexApplication application) {
@@ -233,6 +233,16 @@
return this;
}
+ public Builder replaceLibraryClasses(Collection<DexLibraryClass> libraryClasses) {
+ this.libraryClasses = ImmutableList.copyOf(libraryClasses);
+ return self();
+ }
+
+ public Builder replaceClasspathClasses(Collection<DexClasspathClass> classpathClasses) {
+ this.classpathClasses = ImmutableList.copyOf(classpathClasses);
+ return self();
+ }
+
public Builder addClasspathClasses(List<DexClasspathClass> classes) {
classpathClasses =
ImmutableList.<DexClasspathClass>builder()
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 cf4a98e..eb17913 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -40,6 +40,7 @@
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.base.Equivalence.Wrapper;
+import com.google.common.collect.Iterables;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -475,13 +476,7 @@
// or method is annotated, all methods get parsed with locals information.
private void checkReachabilitySensitivity() {
if (hasReachabilitySensitiveMethod || hasReachabilitySensitiveField()) {
- for (DexEncodedMethod method : directMethods) {
- Code code = method.getCode();
- if (code != null && code.isCfCode()) {
- code.asLazyCfCode().markReachabilitySensitive();
- }
- }
- for (DexEncodedMethod method : virtualMethods) {
+ for (DexEncodedMethod method : Iterables.concat(directMethods, virtualMethods)) {
Code code = method.getCode();
if (code != null && code.isCfCode()) {
code.asLazyCfCode().markReachabilitySensitive();
@@ -492,15 +487,8 @@
private boolean hasReachabilitySensitiveField() {
DexType reachabilitySensitive = application.getFactory().annotationReachabilitySensitive;
- for (DexEncodedField field : instanceFields) {
- for (DexAnnotation annotation : field.annotations.annotations) {
- if (annotation.annotation.type == reachabilitySensitive) {
- return true;
- }
- }
- }
- for (DexEncodedField field : staticFields) {
- for (DexAnnotation annotation : field.annotations.annotations) {
+ for (DexEncodedField field : Iterables.concat(instanceFields, staticFields)) {
+ for (DexAnnotation annotation : field.annotations().annotations) {
if (annotation.annotation.type == reachabilitySensitive) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/graph/KeyedDexItem.java b/src/main/java/com/android/tools/r8/graph/KeyedDexItem.java
deleted file mode 100644
index 239a85d..0000000
--- a/src/main/java/com/android/tools/r8/graph/KeyedDexItem.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.graph;
-
-public abstract class KeyedDexItem<T extends PresortedComparable<T>> extends DexDefinition {
-
- public abstract T getKey();
-
- @Override
- public final boolean equals(Object other) {
- if (other == this) {
- return true;
- }
- return (other.getClass() == getClass()) && ((KeyedDexItem<?>) other).getKey().equals(getKey());
- }
-
- @Override
- public final int hashCode() {
- return getKey().hashCode();
- }
-}
diff --git a/src/main/java/com/android/tools/r8/graph/LookupResult.java b/src/main/java/com/android/tools/r8/graph/LookupResult.java
new file mode 100644
index 0000000..7a923de
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/LookupResult.java
@@ -0,0 +1,102 @@
+// 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.graph;
+
+import com.android.tools.r8.graph.LookupResult.LookupResultSuccess.LookupResultCollectionState;
+import java.util.Collections;
+import java.util.Set;
+
+public abstract class LookupResult {
+
+ public boolean isLookupResultFailure() {
+ return false;
+ }
+
+ public boolean isLookupResultSuccess() {
+ return false;
+ }
+
+ public LookupResultFailure asLookupResultFailure() {
+ return null;
+ }
+
+ public LookupResultSuccess asLookupResultSuccess() {
+ return null;
+ }
+
+ public static LookupResultSuccess createResult(
+ Set<DexEncodedMethod> methodTargets, LookupResultCollectionState state) {
+ return new LookupResultSuccess(methodTargets, state);
+ }
+
+ public static LookupResultFailure createFailedResult() {
+ return LookupResultFailure.INSTANCE;
+ }
+
+ public static LookupResultSuccess getIncompleteEmptyResult() {
+ return LookupResultSuccess.EMPTY_INSTANCE;
+ }
+
+ public static class LookupResultSuccess extends LookupResult {
+
+ private static final LookupResultSuccess EMPTY_INSTANCE =
+ new LookupResultSuccess(Collections.emptySet(), LookupResultCollectionState.Incomplete);
+
+ private final Set<DexEncodedMethod> methodTargets;
+ private final LookupResultCollectionState state;
+
+ private LookupResultSuccess(
+ Set<DexEncodedMethod> methodTargets, LookupResultCollectionState state) {
+ this.methodTargets = methodTargets;
+ this.state = state;
+ }
+
+ public boolean isEmpty() {
+ return methodTargets == null || methodTargets.isEmpty();
+ }
+
+ public Set<DexEncodedMethod> getMethodTargets() {
+ return methodTargets;
+ }
+
+ @Override
+ public LookupResultSuccess asLookupResultSuccess() {
+ return this;
+ }
+
+ @Override
+ public boolean isLookupResultSuccess() {
+ return true;
+ }
+
+ public boolean isIncomplete() {
+ return state == LookupResultCollectionState.Incomplete;
+ }
+
+ public enum LookupResultCollectionState {
+ Complete,
+ Incomplete,
+ }
+ }
+
+ public static class LookupResultFailure extends LookupResult {
+
+ private static final LookupResultFailure INSTANCE = new LookupResultFailure();
+
+ private LookupResultFailure() {
+ // Empty to only allow creation locally.
+ }
+
+ @Override
+ public LookupResultFailure asLookupResultFailure() {
+ return this;
+ }
+
+ @Override
+ public boolean isLookupResultFailure() {
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java
new file mode 100644
index 0000000..2ed505e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollection.java
@@ -0,0 +1,25 @@
+// 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.graph;
+
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+/**
+ * Provides immutable access to {@link ObjectAllocationInfoCollectionImpl}, which stores the set of
+ * instantiated classes along with their allocation sites.
+ */
+public interface ObjectAllocationInfoCollection {
+
+ void forEachClassWithKnownAllocationSites(
+ BiConsumer<DexProgramClass, Set<DexEncodedMethod>> consumer);
+
+ boolean isAllocationSitesKnown(DexProgramClass clazz);
+
+ boolean isInstantiatedDirectly(DexProgramClass clazz);
+
+ ObjectAllocationInfoCollection rewrittenWithLens(
+ DexDefinitionSupplier definitions, GraphLense lens);
+}
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
new file mode 100644
index 0000000..fa13c74
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ObjectAllocationInfoCollectionImpl.java
@@ -0,0 +1,165 @@
+// 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.graph;
+
+import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
+
+import com.android.tools.r8.shaking.GraphReporter;
+import com.android.tools.r8.shaking.InstantiationReason;
+import com.android.tools.r8.shaking.KeepReason;
+import com.android.tools.r8.utils.LensUtils;
+import com.google.common.collect.Sets;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+/** Stores the set of instantiated classes along with their allocation sites. */
+public class ObjectAllocationInfoCollectionImpl implements ObjectAllocationInfoCollection {
+
+ private final Map<DexProgramClass, Set<DexEncodedMethod>> classesWithAllocationSiteTracking;
+ private final Set<DexProgramClass> classesWithoutAllocationSiteTracking;
+
+ private ObjectAllocationInfoCollectionImpl(
+ Map<DexProgramClass, Set<DexEncodedMethod>> classesWithAllocationSiteTracking,
+ Set<DexProgramClass> classesWithoutAllocationSiteTracking) {
+ this.classesWithAllocationSiteTracking = classesWithAllocationSiteTracking;
+ this.classesWithoutAllocationSiteTracking = classesWithoutAllocationSiteTracking;
+ }
+
+ public static Builder builder(boolean trackAllocationSites, GraphReporter reporter) {
+ return new Builder(trackAllocationSites, reporter);
+ }
+
+ @Override
+ public void forEachClassWithKnownAllocationSites(
+ BiConsumer<DexProgramClass, Set<DexEncodedMethod>> consumer) {
+ classesWithAllocationSiteTracking.forEach(consumer);
+ }
+
+ @Override
+ public boolean isAllocationSitesKnown(DexProgramClass clazz) {
+ return classesWithAllocationSiteTracking.containsKey(clazz);
+ }
+
+ @Override
+ public boolean isInstantiatedDirectly(DexProgramClass clazz) {
+ if (classesWithAllocationSiteTracking.containsKey(clazz)) {
+ assert !classesWithAllocationSiteTracking.get(clazz).isEmpty();
+ return true;
+ }
+ return classesWithoutAllocationSiteTracking.contains(clazz);
+ }
+
+ @Override
+ public ObjectAllocationInfoCollectionImpl rewrittenWithLens(
+ DexDefinitionSupplier definitions, GraphLense lens) {
+ return builder(true, null).rewrittenWithLens(this, definitions, lens).build();
+ }
+
+ public static class Builder {
+
+ private final boolean trackAllocationSites;
+
+ private final Map<DexProgramClass, Set<DexEncodedMethod>> classesWithAllocationSiteTracking =
+ new IdentityHashMap<>();
+ private final Set<DexProgramClass> classesWithoutAllocationSiteTracking =
+ Sets.newIdentityHashSet();
+
+ private GraphReporter reporter;
+
+ private Builder(boolean trackAllocationSites, GraphReporter reporter) {
+ this.trackAllocationSites = trackAllocationSites;
+ this.reporter = reporter;
+ }
+
+ private boolean shouldTrackAllocationSitesForClass(
+ DexProgramClass clazz, InstantiationReason instantiationReason) {
+ if (!trackAllocationSites) {
+ return false;
+ }
+ if (instantiationReason != InstantiationReason.NEW_INSTANCE_INSTRUCTION) {
+ // There is an allocation site which is not a new-instance instruction.
+ return false;
+ }
+ if (classesWithoutAllocationSiteTracking.contains(clazz)) {
+ // We already gave up on tracking the allocation sites for `clazz` previously.
+ return false;
+ }
+ // We currently only use allocation site information for instance field value propagation.
+ return !clazz.instanceFields().isEmpty();
+ }
+
+ public boolean isInstantiatedDirectly(DexProgramClass clazz) {
+ if (classesWithAllocationSiteTracking.containsKey(clazz)) {
+ assert !classesWithAllocationSiteTracking.get(clazz).isEmpty();
+ return true;
+ }
+ return classesWithoutAllocationSiteTracking.contains(clazz);
+ }
+
+ /**
+ * Records that {@param clazz} is instantiated in {@param context}.
+ *
+ * @return true if {@param clazz} was not instantiated before.
+ */
+ public boolean recordDirectAllocationSite(
+ DexProgramClass clazz,
+ DexEncodedMethod context,
+ InstantiationReason instantiationReason,
+ KeepReason keepReason) {
+ assert !clazz.isInterface();
+ if (reporter != null) {
+ reporter.registerClass(clazz, keepReason);
+ }
+ if (shouldTrackAllocationSitesForClass(clazz, instantiationReason)) {
+ assert context != null;
+ Set<DexEncodedMethod> allocationSitesForClass =
+ classesWithAllocationSiteTracking.computeIfAbsent(
+ clazz, ignore -> Sets.newIdentityHashSet());
+ allocationSitesForClass.add(context);
+ return allocationSitesForClass.size() == 1;
+ }
+ if (classesWithoutAllocationSiteTracking.add(clazz)) {
+ Set<DexEncodedMethod> allocationSitesForClass =
+ classesWithAllocationSiteTracking.remove(clazz);
+ return allocationSitesForClass == null;
+ }
+ return false;
+ }
+
+ Builder rewrittenWithLens(
+ ObjectAllocationInfoCollectionImpl objectAllocationInfos,
+ DexDefinitionSupplier definitions,
+ GraphLense lens) {
+ objectAllocationInfos.classesWithAllocationSiteTracking.forEach(
+ (clazz, allocationSitesForClass) -> {
+ DexProgramClass rewrittenClass =
+ asProgramClassOrNull(definitions.definitionFor(lens.lookupType(clazz.type)));
+ assert rewrittenClass != null;
+ assert !classesWithAllocationSiteTracking.containsKey(rewrittenClass);
+ classesWithAllocationSiteTracking.put(
+ rewrittenClass,
+ LensUtils.rewrittenWithRenamedSignature(
+ allocationSitesForClass, definitions, lens));
+ });
+ objectAllocationInfos.classesWithoutAllocationSiteTracking.forEach(
+ clazz -> {
+ DexProgramClass rewrittenClass =
+ asProgramClassOrNull(definitions.definitionFor(lens.lookupType(clazz.type)));
+ assert rewrittenClass != null;
+ assert !classesWithAllocationSiteTracking.containsKey(rewrittenClass);
+ assert !classesWithoutAllocationSiteTracking.contains(rewrittenClass);
+ classesWithoutAllocationSiteTracking.add(rewrittenClass);
+ });
+ return this;
+ }
+
+ public ObjectAllocationInfoCollectionImpl build() {
+ return new ObjectAllocationInfoCollectionImpl(
+ classesWithAllocationSiteTracking, classesWithoutAllocationSiteTracking);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/graph/PresortedComparable.java b/src/main/java/com/android/tools/r8/graph/PresortedComparable.java
index 563b40a..81e6d56 100644
--- a/src/main/java/com/android/tools/r8/graph/PresortedComparable.java
+++ b/src/main/java/com/android/tools/r8/graph/PresortedComparable.java
@@ -11,8 +11,8 @@
public interface PresortedComparable<T> extends Presorted, Comparable<T> {
static <T extends PresortedComparable<T>> boolean isSorted(
- List<? extends KeyedDexItem<T>> items) {
- return isSorted(items, KeyedDexItem::getKey);
+ List<? extends DexEncodedMember<T>> items) {
+ return isSorted(items, DexEncodedMember::getKey);
}
static <S, T extends Comparable<T>> boolean isSorted(S[] items, Function<S, T> getter) {
diff --git a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
index f3f308f..c2bd3a4 100644
--- a/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
+++ b/src/main/java/com/android/tools/r8/graph/ResolutionResult.java
@@ -4,6 +4,9 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.LiveSubTypeInfo.LiveSubTypeResult;
+import com.android.tools.r8.graph.LookupResult.LookupResultSuccess.LookupResultCollectionState;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.SetUtils;
import com.google.common.collect.Sets;
import java.util.Collection;
@@ -75,7 +78,12 @@
public abstract DexEncodedMethod lookupInvokeStaticTarget(
DexProgramClass context, AppInfoWithClassHierarchy appInfo);
- public abstract Set<DexEncodedMethod> lookupVirtualDispatchTargets(AppInfoWithSubtyping appInfo);
+ public abstract LookupResult lookupVirtualDispatchTargets(
+ AppView<?> appView, LiveSubTypeInfo liveSubTypes);
+
+ public final LookupResult lookupVirtualDispatchTargets(AppView<AppInfoWithLiveness> appView) {
+ return lookupVirtualDispatchTargets(appView, appView.appInfo());
+ }
/** Result for a resolution that succeeds with a known declaration/definition. */
public static class SingleResolutionResult extends ResolutionResult {
@@ -322,19 +330,21 @@
}
@Override
- public Set<DexEncodedMethod> lookupVirtualDispatchTargets(AppInfoWithSubtyping appInfo) {
+ public LookupResult lookupVirtualDispatchTargets(
+ AppView<?> appView, LiveSubTypeInfo liveSubTypeInfo) {
return initialResolutionHolder.isInterface()
- ? lookupInterfaceTargets(appInfo)
- : lookupVirtualTargets(appInfo);
+ ? lookupInterfaceTargets(appView, liveSubTypeInfo)
+ : lookupVirtualTargets(appView, liveSubTypeInfo);
}
// TODO(b/140204899): Leverage refined receiver type if available.
- private Set<DexEncodedMethod> lookupVirtualTargets(AppInfoWithSubtyping appInfo) {
+ private LookupResult lookupVirtualTargets(AppView<?> appView, LiveSubTypeInfo liveSubTypeInfo) {
assert !initialResolutionHolder.isInterface();
if (resolvedMethod.isPrivateMethod()) {
// If the resolved reference is private there is no dispatch.
// This is assuming that the method is accessible, which implies self/nest access.
- return Collections.singleton(resolvedMethod);
+ return LookupResult.createResult(
+ Collections.singleton(resolvedMethod), LookupResultCollectionState.Complete);
}
assert resolvedMethod.isNonPrivateVirtualMethod();
// First add the target for receiver type method.type.
@@ -343,27 +353,29 @@
DexMethod method = resolvedMethod.method;
// TODO(b/140204899): Instead of subtypes of holder, we could iterate subtypes of refined
// receiver type if available.
- for (DexType type : appInfo.subtypes(method.holder)) {
- DexClass clazz = appInfo.definitionFor(type);
- if (!clazz.isInterface()) {
- ResolutionResult methods = appInfo.resolveMethodOnClass(clazz, method);
+ for (DexProgramClass programClass :
+ liveSubTypeInfo.getLiveSubTypes(method.holder).getProgramClasses()) {
+ if (!programClass.isInterface()) {
+ ResolutionResult methods = appView.appInfo().resolveMethodOnClass(programClass, method);
DexEncodedMethod target = methods.getSingleTarget();
if (target != null && target.isNonPrivateVirtualMethod()) {
result.add(target);
}
}
}
- return result;
+ return LookupResult.createResult(result, LookupResultCollectionState.Complete);
}
// TODO(b/140204899): Leverage refined receiver type if available.
- private Set<DexEncodedMethod> lookupInterfaceTargets(AppInfoWithSubtyping appInfo) {
+ private LookupResult lookupInterfaceTargets(
+ AppView<?> appView, LiveSubTypeInfo liveSubTypeInfo) {
assert initialResolutionHolder.isInterface();
if (resolvedMethod.isPrivateMethod()) {
// If the resolved reference is private there is no dispatch.
// This is assuming that the method is accessible, which implies self/nest access.
assert resolvedMethod.hasCode();
- return Collections.singleton(resolvedMethod);
+ return LookupResult.createResult(
+ Collections.singleton(resolvedMethod), LookupResultCollectionState.Complete);
}
assert resolvedMethod.isNonPrivateVirtualMethod();
Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
@@ -389,7 +401,7 @@
// public void bar() { }
// }
//
- addIfDefaultMethodWithLambdaInstantiations(appInfo, resolvedMethod, result);
+ addIfDefaultMethodWithLambdaInstantiations(liveSubTypeInfo, resolvedMethod, result);
DexMethod method = resolvedMethod.method;
Consumer<DexEncodedMethod> addIfNotAbstract =
@@ -410,35 +422,38 @@
// TODO(b/140204899): Instead of subtypes of holder, we could iterate subtypes of refined
// receiver type if available.
- for (DexType type : appInfo.subtypes(method.holder)) {
- DexClass clazz = appInfo.definitionFor(type);
+ for (DexProgramClass clazz :
+ liveSubTypeInfo.getLiveSubTypes(method.holder).getProgramClasses()) {
if (clazz.isInterface()) {
- ResolutionResult targetMethods = appInfo.resolveMethodOnInterface(clazz, method);
+ ResolutionResult targetMethods =
+ appView.appInfo().resolveMethodOnInterface(clazz, method);
if (targetMethods.isSingleResolution()) {
// Sub-interfaces can have default implementations that override the resolved method.
// Therefore we have to add default methods in sub interfaces.
DexEncodedMethod singleTarget = targetMethods.getSingleTarget();
- addIfDefaultMethodWithLambdaInstantiations(appInfo, singleTarget, result);
+ addIfDefaultMethodWithLambdaInstantiations(liveSubTypeInfo, singleTarget, result);
addIfNotAbstractAndBridge.accept(singleTarget);
}
} else {
- ResolutionResult targetMethods = appInfo.resolveMethodOnClass(clazz, method);
+ ResolutionResult targetMethods = appView.appInfo().resolveMethodOnClass(clazz, method);
if (targetMethods.isSingleResolution()) {
addIfNotAbstract.accept(targetMethods.getSingleTarget());
}
}
}
- return result;
+ return LookupResult.createResult(result, LookupResultCollectionState.Complete);
}
private void addIfDefaultMethodWithLambdaInstantiations(
- AppInfoWithSubtyping appInfo, DexEncodedMethod method, Set<DexEncodedMethod> result) {
+ LiveSubTypeInfo liveSubTypesInfo, DexEncodedMethod method, Set<DexEncodedMethod> result) {
if (method == null) {
return;
}
if (method.hasCode()) {
- DexProgramClass holder = appInfo.definitionForProgramType(method.method.holder);
- if (appInfo.hasAnyInstantiatedLambdas(holder)) {
+ LiveSubTypeResult liveSubTypes = liveSubTypesInfo.getLiveSubTypes(method.method.holder);
+ // TODO(b/148769279): The below is basically if (true), but should be changed when we
+ // have live sub type information.
+ if (liveSubTypes.getCallSites() == null || liveSubTypes.getCallSites() != null) {
result.add(method);
}
}
@@ -472,8 +487,9 @@
}
@Override
- public Set<DexEncodedMethod> lookupVirtualDispatchTargets(AppInfoWithSubtyping appInfo) {
- return null;
+ public LookupResult lookupVirtualDispatchTargets(
+ AppView<?> appView, LiveSubTypeInfo liveSubTypeInfo) {
+ return LookupResult.getIncompleteEmptyResult();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
index 35bbf2f..29dc41b 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
@@ -43,7 +43,7 @@
import java.util.Map;
import java.util.Map.Entry;
-public class FieldValueAnalysis {
+public abstract class FieldValueAnalysis {
private final AppView<AppInfoWithLiveness> appView;
private final DexProgramClass clazz;
@@ -53,7 +53,7 @@
private Map<BasicBlock, AbstractFieldSet> fieldsMaybeReadBeforeBlockInclusiveCache;
- private FieldValueAnalysis(
+ FieldValueAnalysis(
AppView<AppInfoWithLiveness> appView,
IRCode code,
OptimizationFeedback feedback,
@@ -68,37 +68,6 @@
this.method = method;
}
- public static void run(
- AppView<?> appView,
- IRCode code,
- ClassInitializerDefaultsResult classInitializerDefaultsResult,
- OptimizationFeedback feedback,
- DexEncodedMethod method) {
- if (!appView.enableWholeProgramOptimizations()) {
- return;
- }
- assert appView.appInfo().hasLiveness();
- if (!method.isInitializer()) {
- return;
- }
- DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
- if (method.isInstanceInitializer()) {
- if (!appView.options().enableValuePropagationForInstanceFields) {
- return;
- }
- DexEncodedMethod otherInstanceInitializer =
- clazz.lookupDirectMethod(other -> other.isInstanceInitializer() && other != method);
- if (otherInstanceInitializer != null) {
- // Conservatively bail out.
- // TODO(b/125282093): Handle multiple instance initializers on the same class.
- return;
- }
- }
-
- new FieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
- .computeFieldOptimizationInfo(classInitializerDefaultsResult);
- }
-
private Map<BasicBlock, AbstractFieldSet> getOrCreateFieldsMaybeReadBeforeBlockInclusive() {
if (fieldsMaybeReadBeforeBlockInclusiveCache == null) {
fieldsMaybeReadBeforeBlockInclusiveCache = createFieldsMaybeReadBeforeBlockInclusive();
@@ -107,8 +76,7 @@
}
/** This method analyzes initializers with the purpose of computing field optimization info. */
- private void computeFieldOptimizationInfo(
- ClassInitializerDefaultsResult classInitializerDefaultsResult) {
+ void computeFieldOptimizationInfo(ClassInitializerDefaultsResult classInitializerDefaultsResult) {
AppInfoWithLiveness appInfo = appView.appInfo();
DominatorTree dominatorTree = null;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
new file mode 100644
index 0000000..d636715
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
@@ -0,0 +1,49 @@
+// 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.ir.analysis.fieldvalueanalysis;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.optimize.ClassInitializerDefaultsOptimization.ClassInitializerDefaultsResult;
+import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class InstanceFieldValueAnalysis extends FieldValueAnalysis {
+
+ private InstanceFieldValueAnalysis(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ OptimizationFeedback feedback,
+ DexProgramClass clazz,
+ DexEncodedMethod method) {
+ super(appView, code, feedback, clazz, method);
+ }
+
+ public static void run(
+ AppView<?> appView,
+ IRCode code,
+ ClassInitializerDefaultsResult classInitializerDefaultsResult,
+ OptimizationFeedback feedback,
+ DexEncodedMethod method) {
+ assert appView.appInfo().hasLiveness();
+ assert appView.enableWholeProgramOptimizations();
+ assert method.isInstanceInitializer();
+ DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
+ if (!appView.options().enableValuePropagationForInstanceFields) {
+ return;
+ }
+ DexEncodedMethod otherInstanceInitializer =
+ clazz.lookupDirectMethod(other -> other.isInstanceInitializer() && other != method);
+ if (otherInstanceInitializer != null) {
+ // Conservatively bail out.
+ // TODO(b/125282093): Handle multiple instance initializers on the same class.
+ return;
+ }
+ new InstanceFieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
+ .computeFieldOptimizationInfo(classInitializerDefaultsResult);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
new file mode 100644
index 0000000..0c91855
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -0,0 +1,39 @@
+// 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.ir.analysis.fieldvalueanalysis;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.optimize.ClassInitializerDefaultsOptimization.ClassInitializerDefaultsResult;
+import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class StaticFieldValueAnalysis extends FieldValueAnalysis {
+
+ private StaticFieldValueAnalysis(
+ AppView<AppInfoWithLiveness> appView,
+ IRCode code,
+ OptimizationFeedback feedback,
+ DexProgramClass clazz,
+ DexEncodedMethod method) {
+ super(appView, code, feedback, clazz, method);
+ }
+
+ public static void run(
+ AppView<?> appView,
+ IRCode code,
+ ClassInitializerDefaultsResult classInitializerDefaultsResult,
+ OptimizationFeedback feedback,
+ DexEncodedMethod method) {
+ assert appView.appInfo().hasLiveness();
+ assert appView.enableWholeProgramOptimizations();
+ assert method.isClassInitializer();
+ DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass();
+ new StaticFieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method)
+ .computeFieldOptimizationInfo(classInitializerDefaultsResult);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
index 9b980b9..0596d7b 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/type/TypeAnalysis.java
@@ -3,13 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.analysis.type;
-import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
-import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
-import static com.android.tools.r8.ir.analysis.type.TypeLatticeElement.fromDexType;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
@@ -57,10 +53,10 @@
}
}
- public void widening(DexEncodedMethod context, DexEncodedMethod encodedMethod, IRCode code) {
+ public void widening(IRCode code) {
mode = Mode.WIDENING;
assert worklist.isEmpty();
- code.topologicallySortedBlocks().forEach(b -> analyzeBasicBlock(context, encodedMethod, b));
+ code.topologicallySortedBlocks().forEach(this::analyzeBasicBlock);
analyze();
}
@@ -95,31 +91,14 @@
}
}
- private void analyzeBasicBlock(
- DexEncodedMethod context, DexEncodedMethod encodedMethod, BasicBlock block) {
- int argumentsSeen = encodedMethod.accessFlags.isStatic() ? 0 : -1;
+ private void analyzeBasicBlock(BasicBlock block) {
for (Instruction instruction : block.getInstructions()) {
Value outValue = instruction.outValue();
if (outValue == null) {
continue;
}
- // The type for Argument, a quasi instruction, can be inferred from the method signature.
if (instruction.isArgument()) {
- TypeLatticeElement derived;
- if (argumentsSeen < 0) {
- // Receiver
- derived =
- fromDexType(
- encodedMethod.method.holder,
- // Now we try inlining even when the receiver could be null.
- encodedMethod == context ? definitelyNotNull() : maybeNull(),
- appView);
- } else {
- DexType argType = encodedMethod.method.proto.parameters.values[argumentsSeen];
- derived = fromDexType(argType, maybeNull(), appView);
- }
- argumentsSeen++;
- updateTypeOfValue(outValue, derived);
+ // The type for Argument, a quasi instruction is already set correctly during IR building.
// Note that we don't need to enqueue the out value of arguments here because it's constant.
} else if (instruction.hasInvariantOutType()) {
TypeLatticeElement derived = instruction.evaluate(appView);
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
index 7624412..bdba162 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.LookupResult.LookupResultSuccess;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.ClassInitializationAnalysis;
import com.android.tools.r8.ir.analysis.fieldvalueanalysis.AbstractFieldSet;
@@ -83,14 +84,16 @@
if (!isInvokeMethodWithDynamicDispatch() || !appView.appInfo().hasLiveness()) {
return null;
}
- Collection<DexEncodedMethod> targets =
+ LookupResultSuccess lookupResult =
appView
.appInfo()
.resolveMethod(method.holder, method)
- .lookupVirtualDispatchTargets(appView.appInfo());
- if (targets == null) {
+ .lookupVirtualDispatchTargets(appView.withLiveness())
+ .asLookupResultSuccess();
+ if (lookupResult == null) {
return null;
}
+ assert lookupResult.getMethodTargets() != null;
DexType staticReceiverType = getInvokedMethod().holder;
DexType refinedReceiverType =
TypeAnalysis.getRefinedReceiverType(
@@ -103,7 +106,7 @@
if (refinedResolution.isSingleResolution()) {
DexEncodedMethod refinedTarget = refinedResolution.getSingleTarget();
Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
- for (DexEncodedMethod target : targets) {
+ for (DexEncodedMethod target : lookupResult.getMethodTargets()) {
if (target == refinedTarget
|| appView.isSubtype(target.method.holder, refinedReceiverType).isPossiblyTrue()) {
result.add(target);
@@ -113,7 +116,7 @@
}
// If resolution at the refined type fails, conservatively return the full set of targets.
}
- return targets;
+ return lookupResult.getMethodTargets();
}
public abstract InlineAction computeInlining(
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 e1d3d75..6ba4a3a 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
@@ -112,7 +112,8 @@
}
// Allow optimizing static library invokes in D8.
DexClass clazz = appView.definitionFor(getInvokedMethod().holder);
- if (clazz != null && clazz.isLibraryClass()) {
+ if (clazz != null
+ && (clazz.isLibraryClass() || appView.libraryMethodOptimizer().isModeled(clazz.type))) {
return appView.definitionFor(getInvokedMethod());
}
// In D8, we can treat invoke-static instructions as having a single target if the invoke is
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index bdc7ce4..e1f67a9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -105,7 +105,8 @@
DexType holder = getInvokedMethod().holder;
if (holder.isClassType()) {
DexClass clazz = appView.definitionFor(holder);
- if (clazz != null && clazz.isLibraryClass()) {
+ if (clazz != null
+ && (clazz.isLibraryClass() || appView.libraryMethodOptimizer().isModeled(clazz.type))) {
DexEncodedMethod singleTargetCandidate = appView.definitionFor(getInvokedMethod());
if (singleTargetCandidate != null && (clazz.isFinal() || singleTargetCandidate.isFinal())) {
return singleTargetCandidate;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
index 610240e..56462db 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CallGraphBuilderBase.java
@@ -18,6 +18,7 @@
import com.android.tools.r8.graph.FieldAccessInfo;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.GraphLense.GraphLenseLookupResult;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.Invoke;
@@ -212,7 +213,11 @@
ResolutionResult resolution =
appView.appInfo().resolveMethod(method.holder, method, isInterface);
if (resolution.isVirtualTarget()) {
- return resolution.lookupVirtualDispatchTargets(appView.appInfo());
+ LookupResult lookupResult =
+ resolution.lookupVirtualDispatchTargets(appView, appView.appInfo());
+ if (lookupResult.isLookupResultSuccess()) {
+ return lookupResult.asLookupResultSuccess().getMethodTargets();
+ }
}
return null;
});
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 3d0fed3..a39a66b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -619,9 +619,9 @@
if (hasImpreciseValues || impreciseInstructions != null) {
// In DEX we may need to constrain all values and instructions to precise types.
assert source instanceof DexSourceCode;
- new TypeConstraintResolver(appView, this).resolve(impreciseInstructions, ir, method, context);
+ new TypeConstraintResolver(appView, this).resolve(impreciseInstructions, ir);
} else {
- new TypeAnalysis(appView).widening(context, method, ir);
+ new TypeAnalysis(appView).widening(ir);
}
// Update the IR code if collected call site optimization info has something useful.
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 b1b6e81..94df8fb 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
@@ -27,7 +27,8 @@
import com.android.tools.r8.ir.analysis.TypeChecker;
import com.android.tools.r8.ir.analysis.constant.SparseConditionalConstantPropagation;
import com.android.tools.r8.ir.analysis.fieldaccess.FieldAccessAnalysis;
-import com.android.tools.r8.ir.analysis.fieldvalueanalysis.FieldValueAnalysis;
+import com.android.tools.r8.ir.analysis.fieldvalueanalysis.InstanceFieldValueAnalysis;
+import com.android.tools.r8.ir.analysis.fieldvalueanalysis.StaticFieldValueAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.code.AlwaysMaterializingDefinition;
import com.android.tools.r8.ir.code.AlwaysMaterializingUser;
@@ -77,7 +78,6 @@
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
import com.android.tools.r8.ir.optimize.lambda.LambdaMerger;
-import com.android.tools.r8.ir.optimize.library.LibraryMethodOptimizer;
import com.android.tools.r8.ir.optimize.staticizer.ClassStaticizer;
import com.android.tools.r8.ir.optimize.string.StringBuilderOptimizer;
import com.android.tools.r8.ir.optimize.string.StringOptimizer;
@@ -129,7 +129,6 @@
private final Outliner outliner;
private final ClassInitializerDefaultsOptimization classInitializerDefaultsOptimization;
private final FieldAccessAnalysis fieldAccessAnalysis;
- private final LibraryMethodOptimizer libraryMethodOptimizer;
private final LibraryMethodOverrideAnalysis libraryMethodOverrideAnalysis;
private final StringConcatRewriter stringConcatRewriter;
private final StringOptimizer stringOptimizer;
@@ -234,7 +233,6 @@
this.classInliner = null;
this.classStaticizer = null;
this.fieldAccessAnalysis = null;
- this.libraryMethodOptimizer = null;
this.libraryMethodOverrideAnalysis = null;
this.inliner = null;
this.outliner = null;
@@ -268,7 +266,6 @@
options.processCovariantReturnTypeAnnotations
? new CovariantReturnTypeAnnotationTransformer(this, appView.dexItemFactory())
: null;
- this.libraryMethodOptimizer = new LibraryMethodOptimizer(appView);
if (options.testing.forceAssumeNoneInsertion) {
assumers.add(new AliasIntroducer(appView));
}
@@ -510,9 +507,9 @@
}
private void clearSynthesizedClassMapping(Builder<?> builder) {
- for (DexProgramClass programClass : builder.getProgramClasses()) {
- programClass.annotations =
- programClass.annotations.getWithout(builder.dexItemFactory.annotationSynthesizedClassMap);
+ for (DexProgramClass clazz : builder.getProgramClasses()) {
+ clazz.setAnnotations(
+ clazz.annotations().getWithout(builder.dexItemFactory.annotationSynthesizedClassMap));
}
}
@@ -542,7 +539,7 @@
DexAnnotation updatedAnnotation =
DexAnnotation.createAnnotationSynthesizedClassMap(synthesized, builder.dexItemFactory);
- original.annotations = original.annotations.getWithAddedOrReplaced(updatedAnnotation);
+ original.setAnnotations(original.annotations().getWithAddedOrReplaced(updatedAnnotation));
}
}
@@ -1230,11 +1227,9 @@
stringOptimizer.computeTrivialOperationsOnConstString(code);
stringOptimizer.removeTrivialConversions(code);
timing.end();
- if (libraryMethodOptimizer != null) {
- timing.begin("Optimize library methods");
- libraryMethodOptimizer.optimize(code, feedback, methodProcessor);
- timing.end();
- }
+ timing.begin("Optimize library methods");
+ appView.libraryMethodOptimizer().optimize(code, feedback, methodProcessor);
+ timing.end();
assert code.isConsistentSSA();
}
@@ -1570,7 +1565,16 @@
methodOptimizationInfoCollector
.collectMethodOptimizationInfo(code.method, code, feedback, dynamicTypeOptimization);
- FieldValueAnalysis.run(appView, code, classInitializerDefaultsResult, feedback, code.method);
+
+ if (method.isInitializer()) {
+ if (method.isClassInitializer()) {
+ StaticFieldValueAnalysis.run(
+ appView, code, classInitializerDefaultsResult, feedback, code.method);
+ } else {
+ InstanceFieldValueAnalysis.run(
+ appView, code, classInitializerDefaultsResult, feedback, code.method);
+ }
+ }
}
public void removeDeadCodeAndFinalizeIR(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
index 2c41a2a..7257d49 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/TypeConstraintResolver.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.ir.analysis.type.ArrayTypeLatticeElement;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
@@ -92,16 +91,12 @@
}
}
- public void resolve(
- List<ImpreciseMemberTypeInstruction> impreciseInstructions,
- IRCode code,
- DexEncodedMethod method,
- DexEncodedMethod context) {
+ public void resolve(List<ImpreciseMemberTypeInstruction> impreciseInstructions, IRCode code) {
// Round one will resolve at least all object vs single types.
List<Value> remainingImpreciseValues = resolveRoundOne(code);
// Round two will resolve any remaining single and wide types. These can depend on the types
// of array instructions, thus we need to complete the type fixed point prior to resolving.
- new TypeAnalysis(appView, true).widening(context, method, code);
+ new TypeAnalysis(appView, true).widening(code);
// Round two resolves any remaining imprecision and finally selects a final precise type for
// any unconstrained imprecise type.
resolveRoundTwo(code, impreciseInstructions, remainingImpreciseValues);
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 6ff25d9..fd0e452 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
@@ -527,6 +527,19 @@
return rewritableMethods.getProvider(original);
}
+ public static void checkForAssumedLibraryTypes(AppView<?> appView) {
+ Map<DexString, Map<DexType, DexType>> retargetCoreLibMember =
+ appView.options().desugaredLibraryConfiguration.getRetargetCoreLibMember();
+ for (DexString methodName : retargetCoreLibMember.keySet()) {
+ for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
+ DexClass typeClass = appView.definitionFor(inType);
+ if (typeClass == null) {
+ RewritableMethods.warnMissingRetargetCoreLibraryMember(inType, appView);
+ }
+ }
+ }
+ }
+
private static final class RewritableMethods {
// Map backported method to a provider for creating the actual target method (with code).
@@ -1574,9 +1587,9 @@
DexType[] consumerTypes =
new DexType[]{
factory.consumerType,
- factory.createType("Ljava/util/function/DoubleConsumer;"),
- factory.createType("Ljava/util/function/LongConsumer;"),
- factory.createType("Ljava/util/function/IntConsumer;")
+ factory.doubleConsumer,
+ factory.longConsumer,
+ factory.intConsumer
};
TemplateMethodFactory[] methodFactories =
new TemplateMethodFactory[]{
@@ -1666,7 +1679,7 @@
method, BackportedMethods::StreamMethods_ofNullable, "ofNullable"));
}
- private void warnMissingRetargetCoreLibraryMember(DexType type, AppView<?> appView) {
+ private static void warnMissingRetargetCoreLibraryMember(DexType type, AppView<?> appView) {
StringDiagnostic warning =
new StringDiagnostic(
"Cannot retarget core library member "
@@ -1683,9 +1696,7 @@
for (DexString methodName : retargetCoreLibMember.keySet()) {
for (DexType inType : retargetCoreLibMember.get(methodName).keySet()) {
DexClass typeClass = appView.definitionFor(inType);
- if (typeClass == null) {
- warnMissingRetargetCoreLibraryMember(inType, appView);
- } else {
+ if (typeClass != null) {
DexType newHolder = retargetCoreLibMember.get(methodName).get(inType);
List<DexEncodedMethod> found = findDexEncodedMethodsWithName(methodName, typeClass);
for (DexEncodedMethod encodedMethod : found) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
index a0fb1c8..3cadabf 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
@@ -92,8 +92,8 @@
}
// Remove the CovariantReturnType annotations.
for (DexEncodedMethod method : methodsWithCovariantReturnTypeAnnotation) {
- method.annotations =
- method.annotations.keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation));
+ method.setAnnotations(
+ method.annotations().keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)));
}
// Add the newly constructed methods to the class.
clazz.appendVirtualMethods(covariantReturnTypeMethods);
@@ -115,7 +115,7 @@
}
private boolean methodHasCovariantReturnTypeAnnotation(DexEncodedMethod method) {
- for (DexAnnotation annotation : method.annotations.annotations) {
+ for (DexAnnotation annotation : method.annotations().annotations) {
if (isCovariantReturnTypeAnnotation(annotation.annotation)) {
return true;
}
@@ -162,7 +162,7 @@
new DexEncodedMethod(
newMethod,
newAccessFlags,
- method.annotations.keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)),
+ method.annotations().keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)),
method.parameterAnnotationsList.keepIf(Predicates.alwaysTrue()),
new SynthesizedCode(forwardSourceCodeBuilder::build),
true);
@@ -181,7 +181,7 @@
// then this method returns the set { SubOfFoo, SubOfSubOfFoo }.
private Set<DexType> getCovariantReturnTypes(DexClass clazz, DexEncodedMethod method) {
Set<DexType> covariantReturnTypes = new HashSet<>();
- for (DexAnnotation annotation : method.annotations.annotations) {
+ for (DexAnnotation annotation : method.annotations().annotations) {
if (isCovariantReturnTypeAnnotation(annotation.annotation)) {
getCovariantReturnTypesFromAnnotation(
clazz, method, annotation.annotation, covariantReturnTypes);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index 04ce705..4409c30 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -94,8 +94,14 @@
newFlags.promoteToStatic();
DexEncodedMethod.setDebugInfoWithFakeThisParameter(
code, companionMethod.getArity(), appView);
- DexEncodedMethod implMethod = new DexEncodedMethod(
- companionMethod, newFlags, virtual.annotations, virtual.parameterAnnotationsList, code, true);
+ DexEncodedMethod implMethod =
+ new DexEncodedMethod(
+ companionMethod,
+ newFlags,
+ virtual.annotations(),
+ virtual.parameterAnnotationsList,
+ code,
+ true);
implMethod.copyMetadata(virtual);
virtual.setDefaultInterfaceMethodImplementation(implMethod);
companionMethods.add(implMethod);
@@ -129,12 +135,11 @@
: "Static interface method " + direct.toSourceString() + " is expected to "
+ "either be public or private in " + iface.origin;
DexMethod companionMethod = rewriter.staticAsMethodOfCompanionClass(oldMethod);
- Code code = direct.getCode();
DexEncodedMethod implMethod =
new DexEncodedMethod(
companionMethod,
newFlags,
- direct.annotations,
+ direct.annotations(),
direct.parameterAnnotationsList,
direct.getCode(),
true);
@@ -161,7 +166,7 @@
new DexEncodedMethod(
companionMethod,
newFlags,
- direct.annotations,
+ direct.annotations(),
direct.parameterAnnotationsList,
code,
true);
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 330d72a..fae9325 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
@@ -631,7 +631,7 @@
new DexEncodedMethod(
callTarget,
newAccessFlags,
- encodedMethod.annotations,
+ encodedMethod.annotations(),
encodedMethod.parameterAnnotationsList,
encodedMethod.getCode(),
true);
@@ -686,7 +686,7 @@
new DexEncodedMethod(
callTarget,
newAccessFlags,
- encodedMethod.annotations,
+ encodedMethod.annotations(),
encodedMethod.parameterAnnotationsList,
encodedMethod.getCode(),
true);
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 02cb581..0546e9d 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
@@ -204,8 +204,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/CharSequence;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
true),
new CfStore(ValueType.INT, 2),
@@ -214,8 +214,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/CharSequence;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.charSequenceType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
true),
new CfStore(ValueType.INT, 3),
@@ -235,11 +235,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Math;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.intType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("min")),
false),
new CfStore(ValueType.INT, 5),
@@ -253,9 +253,9 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/CharSequence;"),
+ options.itemFactory.charSequenceType,
options.itemFactory.createProto(
- options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+ options.itemFactory.charType, options.itemFactory.intType),
options.itemFactory.createString("charAt")),
true),
new CfStore(ValueType.INT, 6),
@@ -265,9 +265,9 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/CharSequence;"),
+ options.itemFactory.charSequenceType,
options.itemFactory.createProto(
- options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+ options.itemFactory.charType, options.itemFactory.intType),
options.itemFactory.createString("charAt")),
true),
new CfStore(ValueType.INT, 7),
@@ -321,23 +321,23 @@
1,
ImmutableList.of(
label0,
- new CfNew(options.itemFactory.createType("Ljava/lang/String;")),
+ new CfNew(options.itemFactory.stringType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.INT, 0),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("[C"), options.itemFactory.createType("I")),
+ options.itemFactory.charArrayType, options.itemFactory.intType),
options.itemFactory.createString("toChars")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("[C")),
+ options.itemFactory.voidType, options.itemFactory.charArrayType),
options.itemFactory.createString("<init>")),
false),
new CfReturn(ValueType.OBJECT),
@@ -373,16 +373,16 @@
ImmutableList.of(
label0,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("Ljava/lang/AutoCloseable;")),
+ new CfInstanceOf(options.itemFactory.autoCloseableType),
new CfIf(If.Type.EQ, ValueType.INT, label2),
label1,
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("Ljava/lang/AutoCloseable;")),
+ new CfCheckCast(options.itemFactory.autoCloseableType),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/AutoCloseable;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.autoCloseableType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("close")),
true),
new CfGoto(label11),
@@ -391,22 +391,21 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Class;")),
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.classType),
options.itemFactory.createString("getClass")),
false),
new CfConstString(options.itemFactory.createString("close")),
new CfConstNumber(0, ValueType.INT),
- new CfNewArray(options.itemFactory.createType("[Ljava/lang/Class;")),
+ new CfNewArray(options.itemFactory.createSynthesizedType("[Ljava/lang/Class;")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Class;"),
+ options.itemFactory.classType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/reflect/Method;"),
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("[Ljava/lang/Class;")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/reflect/Method;"),
+ options.itemFactory.stringType,
+ options.itemFactory.createSynthesizedType("[Ljava/lang/Class;")),
options.itemFactory.createString("getMethod")),
false),
new CfStore(ValueType.OBJECT, 2),
@@ -414,15 +413,15 @@
new CfLoad(ValueType.OBJECT, 2),
new CfLoad(ValueType.OBJECT, 1),
new CfConstNumber(0, ValueType.INT),
- new CfNewArray(options.itemFactory.createType("[Ljava/lang/Object;")),
+ new CfNewArray(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/reflect/Method;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/reflect/Method;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("[Ljava/lang/Object;")),
+ options.itemFactory.objectType,
+ options.itemFactory.objectType,
+ options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
options.itemFactory.createString("invoke")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -431,124 +430,116 @@
label5,
new CfStore(ValueType.OBJECT, 2),
label6,
- new CfNew(options.itemFactory.createType("Ljava/lang/AssertionError;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/AssertionError;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Class;")),
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.classType),
options.itemFactory.createString("getClass")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.objectType),
options.itemFactory.createString("append")),
false),
new CfConstString(options.itemFactory.createString(" does not have a close() method.")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/AssertionError;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/AssertionError;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("Ljava/lang/Throwable;")),
+ options.itemFactory.voidType,
+ options.itemFactory.stringType,
+ options.itemFactory.throwableType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
label7,
new CfStore(ValueType.OBJECT, 2),
label8,
- new CfNew(options.itemFactory.createType("Ljava/lang/AssertionError;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/AssertionError;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfConstString(options.itemFactory.createString("Fail to call close() on ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Class;")),
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.classType),
options.itemFactory.createString("getClass")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.objectType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/AssertionError;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/AssertionError;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("Ljava/lang/Throwable;")),
+ options.itemFactory.voidType,
+ options.itemFactory.stringType,
+ options.itemFactory.throwableType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -559,9 +550,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/reflect/InvocationTargetException;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Throwable;")),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/reflect/InvocationTargetException;"),
+ options.itemFactory.createProto(options.itemFactory.throwableType),
options.itemFactory.createString("getCause")),
false),
new CfThrow(),
@@ -586,42 +577,46 @@
label2,
label4,
ImmutableList.of(
- options.itemFactory.createType("Ljava/lang/NoSuchMethodException;")),
- ImmutableList.of(label5)),
- new CfTryCatch(
- label2,
- label4,
- ImmutableList.of(options.itemFactory.createType("Ljava/lang/SecurityException;")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NoSuchMethodException;")),
ImmutableList.of(label5)),
new CfTryCatch(
label2,
label4,
ImmutableList.of(
- options.itemFactory.createType("Ljava/lang/IllegalAccessException;")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/SecurityException;")),
+ ImmutableList.of(label5)),
+ new CfTryCatch(
+ label2,
+ label4,
+ ImmutableList.of(
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/IllegalAccessException;")),
ImmutableList.of(label7)),
new CfTryCatch(
label2,
label4,
ImmutableList.of(
- options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/IllegalArgumentException;")),
ImmutableList.of(label7)),
new CfTryCatch(
label2,
label4,
ImmutableList.of(
- options.itemFactory.createType("Ljava/lang/ExceptionInInitializerError;")),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/ExceptionInInitializerError;")),
ImmutableList.of(label7)),
new CfTryCatch(
label2,
label4,
ImmutableList.of(
- options.itemFactory.createType(
+ options.itemFactory.createSynthesizedType(
"Ljava/lang/reflect/InvocationTargetException;")),
ImmutableList.of(label9)),
new CfTryCatch(
label0,
label11,
- ImmutableList.of(options.itemFactory.createType("Ljava/lang/Throwable;")),
+ ImmutableList.of(options.itemFactory.throwableType),
ImmutableList.of(label12))),
ImmutableList.of());
}
@@ -640,16 +635,16 @@
6,
ImmutableList.of(
label0,
- new CfNew(options.itemFactory.createType("Ljava/util/ArrayList;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 0),
new CfArrayLength(),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/ArrayList;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+ options.itemFactory.voidType, options.itemFactory.intType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 1),
@@ -675,19 +670,17 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/ArrayList;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.booleanType, options.itemFactory.objectType),
options.itemFactory.createString("add")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -699,10 +692,10 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/List;"),
- options.itemFactory.createType("Ljava/util/List;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;")),
options.itemFactory.createString("unmodifiableList")),
false),
new CfReturn(ValueType.OBJECT),
@@ -724,17 +717,17 @@
ImmutableList.of(
label0,
new CfNew(
- options.itemFactory.createType("Ljava/util/AbstractMap$SimpleImmutableEntry;")),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/util/AbstractMap$SimpleImmutableEntry;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 0),
label1,
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfLoad(ValueType.OBJECT, 1),
@@ -742,20 +735,20 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/AbstractMap$SimpleImmutableEntry;"),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/util/AbstractMap$SimpleImmutableEntry;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.voidType,
+ options.itemFactory.objectType,
+ options.itemFactory.objectType),
options.itemFactory.createString("<init>")),
false),
label3,
@@ -782,16 +775,16 @@
8,
ImmutableList.of(
label0,
- new CfNew(options.itemFactory.createType("Ljava/util/HashMap;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/HashMap;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 0),
new CfArrayLength(),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/HashMap;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/HashMap;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+ options.itemFactory.voidType, options.itemFactory.intType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 1),
@@ -816,18 +809,16 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Map$Entry;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("getKey")),
true),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfStore(ValueType.OBJECT, 6),
@@ -836,18 +827,16 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Map$Entry;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("getValue")),
true),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfStore(ValueType.OBJECT, 7),
@@ -858,61 +847,59 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/HashMap;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/HashMap;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType,
+ options.itemFactory.objectType,
+ options.itemFactory.objectType),
options.itemFactory.createString("put")),
false),
new CfIf(If.Type.EQ, ValueType.OBJECT, label7),
label6,
- new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/IllegalArgumentException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfConstString(options.itemFactory.createString("duplicate key: ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.OBJECT, 6),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.objectType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/IllegalArgumentException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -924,10 +911,10 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Map;"),
- options.itemFactory.createType("Ljava/util/Map;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map;")),
options.itemFactory.createString("unmodifiableMap")),
false),
new CfReturn(ValueType.OBJECT),
@@ -951,16 +938,16 @@
6,
ImmutableList.of(
label0,
- new CfNew(options.itemFactory.createType("Ljava/util/HashSet;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/HashSet;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 0),
new CfArrayLength(),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/HashSet;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/HashSet;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+ options.itemFactory.voidType, options.itemFactory.intType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 1),
@@ -986,69 +973,65 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/HashSet;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/HashSet;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.booleanType, options.itemFactory.objectType),
options.itemFactory.createString("add")),
false),
new CfIf(If.Type.NE, ValueType.INT, label5),
label4,
- new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/IllegalArgumentException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfConstString(options.itemFactory.createString("duplicate element: ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.OBJECT, 5),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.objectType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/IllegalArgumentException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -1060,10 +1043,10 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Set;"),
- options.itemFactory.createType("Ljava/util/Set;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Set;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Set;")),
options.itemFactory.createString("unmodifiableSet")),
false),
new CfReturn(ValueType.OBJECT),
@@ -1086,22 +1069,22 @@
4,
ImmutableList.of(
label0,
- new CfNew(options.itemFactory.createType("Ljava/util/ArrayList;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collection;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collection;"),
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("size")),
true),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/ArrayList;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+ options.itemFactory.voidType, options.itemFactory.intType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 1),
@@ -1110,9 +1093,9 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collection;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collection;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Iterator;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
options.itemFactory.createString("iterator")),
true),
new CfStore(ValueType.OBJECT, 2),
@@ -1121,8 +1104,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("hasNext")),
true),
new CfIf(If.Type.EQ, ValueType.INT, label5),
@@ -1130,9 +1113,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("next")),
true),
new CfStore(ValueType.OBJECT, 3),
@@ -1142,19 +1124,17 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/ArrayList;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/ArrayList;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.booleanType, options.itemFactory.objectType),
options.itemFactory.createString("add")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -1165,10 +1145,10 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/List;"),
- options.itemFactory.createType("Ljava/util/List;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;")),
options.itemFactory.createString("unmodifiableList")),
false),
new CfReturn(ValueType.OBJECT),
@@ -1194,22 +1174,22 @@
4,
ImmutableList.of(
label0,
- new CfNew(options.itemFactory.createType("Ljava/util/HashMap;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/HashMap;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Map;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map;"),
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("size")),
true),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/HashMap;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/HashMap;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+ options.itemFactory.voidType, options.itemFactory.intType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 1),
@@ -1218,17 +1198,17 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Map;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Set;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Set;")),
options.itemFactory.createString("entrySet")),
true),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Set;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Set;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Iterator;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
options.itemFactory.createString("iterator")),
true),
new CfStore(ValueType.OBJECT, 2),
@@ -1237,8 +1217,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("hasNext")),
true),
new CfIf(If.Type.EQ, ValueType.INT, label8),
@@ -1246,12 +1226,11 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("next")),
true),
- new CfCheckCast(options.itemFactory.createType("Ljava/util/Map$Entry;")),
+ new CfCheckCast(options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;")),
new CfStore(ValueType.OBJECT, 3),
label3,
new CfLoad(ValueType.OBJECT, 1),
@@ -1260,18 +1239,16 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Map$Entry;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("getKey")),
true),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfLoad(ValueType.OBJECT, 3),
@@ -1279,29 +1256,27 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Map$Entry;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map$Entry;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("getValue")),
true),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
label6,
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/HashMap;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/HashMap;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType,
+ options.itemFactory.objectType,
+ options.itemFactory.objectType),
options.itemFactory.createString("put")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -1312,10 +1287,10 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Map;"),
- options.itemFactory.createType("Ljava/util/Map;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Map;")),
options.itemFactory.createString("unmodifiableMap")),
false),
new CfReturn(ValueType.OBJECT),
@@ -1338,22 +1313,22 @@
4,
ImmutableList.of(
label0,
- new CfNew(options.itemFactory.createType("Ljava/util/HashSet;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/util/HashSet;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collection;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collection;"),
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("size")),
true),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/HashSet;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/HashSet;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+ options.itemFactory.voidType, options.itemFactory.intType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 1),
@@ -1362,9 +1337,9 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collection;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collection;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Iterator;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
options.itemFactory.createString("iterator")),
true),
new CfStore(ValueType.OBJECT, 2),
@@ -1373,8 +1348,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("hasNext")),
true),
new CfIf(If.Type.EQ, ValueType.INT, label5),
@@ -1382,9 +1357,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("next")),
true),
new CfStore(ValueType.OBJECT, 3),
@@ -1394,19 +1368,17 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/HashSet;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/HashSet;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.booleanType, options.itemFactory.objectType),
options.itemFactory.createString("add")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -1417,10 +1389,10 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Set;"),
- options.itemFactory.createType("Ljava/util/Set;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Set;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Set;")),
options.itemFactory.createString("unmodifiableSet")),
false),
new CfReturn(ValueType.OBJECT),
@@ -1441,18 +1413,18 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/List;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;")),
options.itemFactory.createString("emptyList")),
false),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Enumeration;"),
- options.itemFactory.createType("Ljava/util/Collection;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Enumeration;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collection;")),
options.itemFactory.createString("enumeration")),
false),
new CfReturn(ValueType.OBJECT)),
@@ -1471,17 +1443,17 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/List;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;")),
options.itemFactory.createString("emptyList")),
false),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/List;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Iterator;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
options.itemFactory.createString("iterator")),
true),
new CfReturn(ValueType.OBJECT)),
@@ -1501,17 +1473,17 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Collections;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Collections;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/List;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;")),
options.itemFactory.createString("emptyList")),
false),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/List;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/List;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/ListIterator;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/ListIterator;")),
options.itemFactory.createString("listIterator")),
true),
new CfReturn(ValueType.OBJECT)),
@@ -1533,9 +1505,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Double;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Double;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"), options.itemFactory.createType("D")),
+ options.itemFactory.longType, options.itemFactory.doubleType),
options.itemFactory.createString("doubleToLongBits")),
false),
new CfStore(ValueType.LONG, 2),
@@ -1567,9 +1539,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Double;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Double;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("D")),
+ options.itemFactory.booleanType, options.itemFactory.doubleType),
options.itemFactory.createString("isInfinite")),
false),
new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -1577,9 +1549,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Double;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Double;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("D")),
+ options.itemFactory.booleanType, options.itemFactory.doubleType),
options.itemFactory.createString("isNaN")),
false),
new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -1609,9 +1581,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Float;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Float;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("F")),
+ options.itemFactory.booleanType, options.itemFactory.floatType),
options.itemFactory.createString("isInfinite")),
false),
new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -1619,9 +1591,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Float;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Float;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("F")),
+ options.itemFactory.booleanType, options.itemFactory.floatType),
options.itemFactory.createString("isNaN")),
false),
new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -1694,11 +1666,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Integer;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Integer;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.intType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("compare")),
false),
new CfReturn(ValueType.INT),
@@ -1754,11 +1726,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Integer;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Integer;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"),
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.intType,
+ options.itemFactory.stringType,
+ options.itemFactory.intType),
options.itemFactory.createString("parseUnsignedInt")),
false),
new CfReturn(ValueType.INT),
@@ -1786,8 +1758,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
false),
new CfConstNumber(1, ValueType.INT),
@@ -1797,9 +1769,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+ options.itemFactory.charType, options.itemFactory.intType),
options.itemFactory.createString("charAt")),
false),
new CfConstNumber(43, ValueType.INT),
@@ -1810,10 +1782,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType, options.itemFactory.intType),
options.itemFactory.createString("substring")),
false),
new CfStore(ValueType.OBJECT, 0),
@@ -1823,11 +1794,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"),
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.longType,
+ options.itemFactory.stringType,
+ options.itemFactory.intType),
options.itemFactory.createString("parseLong")),
false),
new CfStore(ValueType.LONG, 2),
@@ -1839,55 +1810,52 @@
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
new CfIf(If.Type.EQ, ValueType.INT, label5),
label4,
- new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfConstString(options.itemFactory.createString("Input ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfConstString(options.itemFactory.createString(" in base ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 1),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfConstString(
@@ -1895,27 +1863,24 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -1994,11 +1959,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Integer;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Integer;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("toUnsignedString")),
false),
new CfReturn(ValueType.OBJECT),
@@ -2029,11 +1994,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.longType,
+ options.itemFactory.intType),
options.itemFactory.createString("toString")),
false),
new CfReturn(ValueType.OBJECT),
@@ -2068,11 +2033,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J")),
+ options.itemFactory.intType,
+ options.itemFactory.longType,
+ options.itemFactory.longType),
options.itemFactory.createString("compare")),
false),
new CfReturn(ValueType.INT),
@@ -2219,11 +2184,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"),
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.longType,
+ options.itemFactory.stringType,
+ options.itemFactory.intType),
options.itemFactory.createString("parseUnsignedLong")),
false),
new CfReturn(ValueType.LONG),
@@ -2266,8 +2231,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
false),
new CfStore(ValueType.INT, 2),
@@ -2275,16 +2240,16 @@
new CfLoad(ValueType.INT, 2),
new CfIf(If.Type.NE, ValueType.INT, label3),
label2,
- new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfConstString(options.itemFactory.createString("empty string")),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -2296,35 +2261,33 @@
new CfConstNumber(36, ValueType.INT),
new CfIfCmp(If.Type.LE, ValueType.INT, label5),
label4,
- new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfConstString(options.itemFactory.createString("illegal radix: ")),
new CfLoad(ValueType.INT, 1),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType, options.itemFactory.intType),
options.itemFactory.createString("valueOf")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringType, options.itemFactory.stringType),
options.itemFactory.createString("concat")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -2335,11 +2298,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J")),
+ options.itemFactory.longType,
+ options.itemFactory.longType,
+ options.itemFactory.longType),
options.itemFactory.createString("divideUnsigned")),
false),
new CfStore(ValueType.LONG, 3),
@@ -2349,9 +2312,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+ options.itemFactory.charType, options.itemFactory.intType),
options.itemFactory.createString("charAt")),
false),
new CfConstNumber(43, ValueType.INT),
@@ -2381,20 +2344,20 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("C"), options.itemFactory.createType("I")),
+ options.itemFactory.charType, options.itemFactory.intType),
options.itemFactory.createString("charAt")),
false),
new CfLoad(ValueType.INT, 1),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"),
- options.itemFactory.createType("C"),
- options.itemFactory.createType("I")),
+ options.itemFactory.intType,
+ options.itemFactory.charType,
+ options.itemFactory.intType),
options.itemFactory.createString("digit")),
false),
new CfStore(ValueType.INT, 9),
@@ -2403,16 +2366,16 @@
new CfConstNumber(-1, ValueType.INT),
new CfIfCmp(If.Type.NE, ValueType.INT, label15),
label14,
- new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -2437,36 +2400,35 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J")),
+ options.itemFactory.longType,
+ options.itemFactory.longType,
+ options.itemFactory.longType),
options.itemFactory.createString("remainderUnsigned")),
false),
new CfNumberConversion(NumericType.LONG, NumericType.INT),
new CfIfCmp(If.Type.LE, ValueType.INT, label18),
label17,
- new CfNew(options.itemFactory.createType("Ljava/lang/NumberFormatException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfConstString(options.itemFactory.createString("Too large for unsigned long: ")),
new CfLoad(ValueType.OBJECT, 0),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringType, options.itemFactory.stringType),
options.itemFactory.createString("concat")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/NumberFormatException;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NumberFormatException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -2608,11 +2570,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.longType,
+ options.itemFactory.intType),
options.itemFactory.createString("toUnsignedString")),
false),
new CfReturn(ValueType.OBJECT),
@@ -2674,11 +2636,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.longType,
+ options.itemFactory.intType),
options.itemFactory.createString("toString")),
false),
new CfReturn(ValueType.OBJECT),
@@ -2694,7 +2656,7 @@
new CfStore(ValueType.INT, 2),
label6,
new CfConstNumber(64, ValueType.INT),
- new CfNewArray(options.itemFactory.createType("[C")),
+ new CfNewArray(options.itemFactory.charArrayType),
new CfStore(ValueType.OBJECT, 3),
label7,
new CfLoad(ValueType.OBJECT, 3),
@@ -2712,9 +2674,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Integer;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Integer;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("numberOfTrailingZeros")),
false),
new CfStore(ValueType.INT, 5),
@@ -2735,11 +2697,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("C"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.charType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("forDigit")),
false),
new CfArrayStore(MemberType.CHAR),
@@ -2779,11 +2741,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J")),
+ options.itemFactory.longType,
+ options.itemFactory.longType,
+ options.itemFactory.longType),
options.itemFactory.createString("divideUnsigned")),
false),
new CfStore(ValueType.LONG, 5),
@@ -2805,11 +2767,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("C"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.charType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("forDigit")),
false),
new CfArrayStore(MemberType.CHAR),
@@ -2834,11 +2796,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("C"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.charType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("forDigit")),
false),
new CfArrayStore(MemberType.CHAR),
@@ -2850,7 +2812,7 @@
new CfStore(ValueType.LONG, 0),
new CfGoto(label22),
label25,
- new CfNew(options.itemFactory.createType("Ljava/lang/String;")),
+ new CfNew(options.itemFactory.stringType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 3),
new CfLoad(ValueType.INT, 4),
@@ -2861,12 +2823,12 @@
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("[C"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.voidType,
+ options.itemFactory.charArrayType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("<init>")),
false),
new CfReturn(ValueType.OBJECT),
@@ -2908,13 +2870,13 @@
new CfLoad(ValueType.INT, 4),
new CfReturn(ValueType.INT),
label4,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -2972,13 +2934,13 @@
new CfLoad(ValueType.LONG, 4),
new CfReturn(ValueType.LONG),
label7,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3002,13 +2964,13 @@
new CfConstNumber(-2147483648, ValueType.INT),
new CfIfCmp(If.Type.NE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3038,13 +3000,13 @@
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
new CfIf(If.Type.NE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3193,11 +3155,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Math;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J")),
+ options.itemFactory.longType,
+ options.itemFactory.longType,
+ options.itemFactory.longType),
options.itemFactory.createString("floorDiv")),
false),
new CfReturn(ValueType.LONG),
@@ -3325,11 +3287,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Math;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J")),
+ options.itemFactory.longType,
+ options.itemFactory.longType,
+ options.itemFactory.longType),
options.itemFactory.createString("floorMod")),
false),
new CfNumberConversion(NumericType.LONG, NumericType.INT),
@@ -3354,13 +3316,13 @@
new CfConstNumber(2147483647, ValueType.INT),
new CfIfCmp(If.Type.NE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3390,13 +3352,13 @@
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
new CfIf(If.Type.NE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3443,13 +3405,13 @@
new CfLoad(ValueType.INT, 4),
new CfReturn(ValueType.INT),
label4,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3487,9 +3449,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("J")),
+ options.itemFactory.intType, options.itemFactory.longType),
options.itemFactory.createString("numberOfLeadingZeros")),
false),
new CfLoad(ValueType.LONG, 0),
@@ -3499,9 +3461,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("J")),
+ options.itemFactory.intType, options.itemFactory.longType),
options.itemFactory.createString("numberOfLeadingZeros")),
false),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -3510,9 +3472,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("J")),
+ options.itemFactory.intType, options.itemFactory.longType),
options.itemFactory.createString("numberOfLeadingZeros")),
false),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -3523,9 +3485,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Long;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Long;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("J")),
+ options.itemFactory.intType, options.itemFactory.longType),
options.itemFactory.createString("numberOfLeadingZeros")),
false),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -3583,13 +3545,13 @@
new CfLoad(ValueType.LONG, 5),
new CfReturn(ValueType.LONG),
label15,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3613,11 +3575,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Math;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
options.itemFactory.createProto(
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J"),
- options.itemFactory.createType("J")),
+ options.itemFactory.longType,
+ options.itemFactory.longType,
+ options.itemFactory.longType),
options.itemFactory.createString("multiplyExact")),
false),
new CfReturn(ValueType.LONG),
@@ -3765,13 +3727,13 @@
new CfConstNumber(-2147483648, ValueType.INT),
new CfIfCmp(If.Type.NE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3800,13 +3762,13 @@
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
new CfIf(If.Type.NE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3833,9 +3795,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Math;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
options.itemFactory.createProto(
- options.itemFactory.createType("D"), options.itemFactory.createType("D")),
+ options.itemFactory.doubleType, options.itemFactory.doubleType),
options.itemFactory.createString("nextUp")),
false),
new CfNeg(NumericType.DOUBLE),
@@ -3859,9 +3821,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Math;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Math;"),
options.itemFactory.createProto(
- options.itemFactory.createType("F"), options.itemFactory.createType("F")),
+ options.itemFactory.floatType, options.itemFactory.floatType),
options.itemFactory.createString("nextUp")),
false),
new CfNeg(NumericType.FLOAT),
@@ -3904,13 +3866,13 @@
new CfLoad(ValueType.INT, 4),
new CfReturn(ValueType.INT),
label4,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -3968,13 +3930,13 @@
new CfLoad(ValueType.LONG, 4),
new CfReturn(ValueType.LONG),
label7,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -4005,13 +3967,13 @@
new CfCmp(Cmp.Bias.NONE, NumericType.LONG),
new CfIf(If.Type.EQ, ValueType.INT, label3),
label2,
- new CfNew(options.itemFactory.createType("Ljava/lang/ArithmeticException;")),
+ new CfNew(options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/ArithmeticException;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/ArithmeticException;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -4047,112 +4009,104 @@
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
new CfIfCmp(If.Type.LE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/IndexOutOfBoundsException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfConstString(options.itemFactory.createString("Range [")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 0),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfConstString(options.itemFactory.createString(", ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 0),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfConstString(options.itemFactory.createString(" + ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 1),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfConstString(options.itemFactory.createString(") out of bounds for length ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 2),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/IndexOutOfBoundsException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -4184,92 +4138,86 @@
new CfLoad(ValueType.INT, 2),
new CfIfCmp(If.Type.LE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/IndexOutOfBoundsException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfConstString(options.itemFactory.createString("Range [")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 0),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfConstString(options.itemFactory.createString(", ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 1),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfConstString(options.itemFactory.createString(") out of bounds for length ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 2),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/IndexOutOfBoundsException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -4298,72 +4246,68 @@
new CfLoad(ValueType.INT, 1),
new CfIfCmp(If.Type.LT, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/IndexOutOfBoundsException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfConstString(options.itemFactory.createString("Index ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 0),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfConstString(options.itemFactory.createString(" out of bounds for length ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 1),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/IndexOutOfBoundsException;"),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/IndexOutOfBoundsException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -4398,11 +4342,11 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Comparator;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Comparator;"),
options.itemFactory.createProto(
- options.itemFactory.createType("I"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.intType,
+ options.itemFactory.objectType,
+ options.itemFactory.objectType),
options.itemFactory.createString("compare")),
true),
label2,
@@ -4471,24 +4415,24 @@
new CfReturn(ValueType.INT),
label2,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[Z")),
+ new CfInstanceOf(options.itemFactory.booleanArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label6),
label3,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[Z")),
+ new CfInstanceOf(options.itemFactory.booleanArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label4),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[Z")),
+ new CfCheckCast(options.itemFactory.booleanArrayType),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[Z")),
+ new CfCheckCast(options.itemFactory.booleanArrayType),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[Z"),
- options.itemFactory.createType("[Z")),
+ options.itemFactory.booleanType,
+ options.itemFactory.booleanArrayType,
+ options.itemFactory.booleanArrayType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label4),
@@ -4500,24 +4444,24 @@
new CfReturn(ValueType.INT),
label6,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[B")),
+ new CfInstanceOf(options.itemFactory.byteArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label10),
label7,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[B")),
+ new CfInstanceOf(options.itemFactory.byteArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label8),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[B")),
+ new CfCheckCast(options.itemFactory.byteArrayType),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[B")),
+ new CfCheckCast(options.itemFactory.byteArrayType),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[B"),
- options.itemFactory.createType("[B")),
+ options.itemFactory.booleanType,
+ options.itemFactory.byteArrayType,
+ options.itemFactory.byteArrayType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label8),
@@ -4529,24 +4473,24 @@
new CfReturn(ValueType.INT),
label10,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[C")),
+ new CfInstanceOf(options.itemFactory.charArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label14),
label11,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[C")),
+ new CfInstanceOf(options.itemFactory.charArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label12),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[C")),
+ new CfCheckCast(options.itemFactory.charArrayType),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[C")),
+ new CfCheckCast(options.itemFactory.charArrayType),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[C"),
- options.itemFactory.createType("[C")),
+ options.itemFactory.booleanType,
+ options.itemFactory.charArrayType,
+ options.itemFactory.charArrayType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label12),
@@ -4558,24 +4502,24 @@
new CfReturn(ValueType.INT),
label14,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[D")),
+ new CfInstanceOf(options.itemFactory.doubleArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label18),
label15,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[D")),
+ new CfInstanceOf(options.itemFactory.doubleArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label16),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[D")),
+ new CfCheckCast(options.itemFactory.doubleArrayType),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[D")),
+ new CfCheckCast(options.itemFactory.doubleArrayType),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[D"),
- options.itemFactory.createType("[D")),
+ options.itemFactory.booleanType,
+ options.itemFactory.doubleArrayType,
+ options.itemFactory.doubleArrayType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label16),
@@ -4587,24 +4531,24 @@
new CfReturn(ValueType.INT),
label18,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[F")),
+ new CfInstanceOf(options.itemFactory.floatArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label22),
label19,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[F")),
+ new CfInstanceOf(options.itemFactory.floatArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label20),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[F")),
+ new CfCheckCast(options.itemFactory.floatArrayType),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[F")),
+ new CfCheckCast(options.itemFactory.floatArrayType),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[F"),
- options.itemFactory.createType("[F")),
+ options.itemFactory.booleanType,
+ options.itemFactory.floatArrayType,
+ options.itemFactory.floatArrayType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label20),
@@ -4616,24 +4560,24 @@
new CfReturn(ValueType.INT),
label22,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[I")),
+ new CfInstanceOf(options.itemFactory.intArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label26),
label23,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[I")),
+ new CfInstanceOf(options.itemFactory.intArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label24),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[I")),
+ new CfCheckCast(options.itemFactory.intArrayType),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[I")),
+ new CfCheckCast(options.itemFactory.intArrayType),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[I"),
- options.itemFactory.createType("[I")),
+ options.itemFactory.booleanType,
+ options.itemFactory.intArrayType,
+ options.itemFactory.intArrayType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label24),
@@ -4645,24 +4589,24 @@
new CfReturn(ValueType.INT),
label26,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[J")),
+ new CfInstanceOf(options.itemFactory.longArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label30),
label27,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[J")),
+ new CfInstanceOf(options.itemFactory.longArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label28),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[J")),
+ new CfCheckCast(options.itemFactory.longArrayType),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[J")),
+ new CfCheckCast(options.itemFactory.longArrayType),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[J"),
- options.itemFactory.createType("[J")),
+ options.itemFactory.booleanType,
+ options.itemFactory.longArrayType,
+ options.itemFactory.longArrayType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label28),
@@ -4674,24 +4618,24 @@
new CfReturn(ValueType.INT),
label30,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[S")),
+ new CfInstanceOf(options.itemFactory.shortArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label34),
label31,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[S")),
+ new CfInstanceOf(options.itemFactory.shortArrayType),
new CfIf(If.Type.EQ, ValueType.INT, label32),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[S")),
+ new CfCheckCast(options.itemFactory.shortArrayType),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[S")),
+ new CfCheckCast(options.itemFactory.shortArrayType),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[S"),
- options.itemFactory.createType("[S")),
+ options.itemFactory.booleanType,
+ options.itemFactory.shortArrayType,
+ options.itemFactory.shortArrayType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label32),
@@ -4703,24 +4647,24 @@
new CfReturn(ValueType.INT),
label34,
new CfLoad(ValueType.OBJECT, 0),
- new CfInstanceOf(options.itemFactory.createType("[Ljava/lang/Object;")),
+ new CfInstanceOf(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
new CfIf(If.Type.EQ, ValueType.INT, label38),
label35,
new CfLoad(ValueType.OBJECT, 1),
- new CfInstanceOf(options.itemFactory.createType("[Ljava/lang/Object;")),
+ new CfInstanceOf(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
new CfIf(If.Type.EQ, ValueType.INT, label36),
new CfLoad(ValueType.OBJECT, 0),
- new CfCheckCast(options.itemFactory.createType("[Ljava/lang/Object;")),
+ new CfCheckCast(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
new CfLoad(ValueType.OBJECT, 1),
- new CfCheckCast(options.itemFactory.createType("[Ljava/lang/Object;")),
+ new CfCheckCast(options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Arrays;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Arrays;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("[Ljava/lang/Object;"),
- options.itemFactory.createType("[Ljava/lang/Object;")),
+ options.itemFactory.booleanType,
+ options.itemFactory.createSynthesizedType("[Ljava/lang/Object;"),
+ options.itemFactory.createSynthesizedType("[Ljava/lang/Object;")),
options.itemFactory.createString("deepEquals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label36),
@@ -4736,10 +4680,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Object;"),
+ options.itemFactory.objectType,
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.booleanType, options.itemFactory.objectType),
options.itemFactory.createString("equals")),
false),
new CfReturn(ValueType.INT),
@@ -4770,10 +4713,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Object;"),
+ options.itemFactory.objectType,
options.itemFactory.createProto(
- options.itemFactory.createType("Z"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.booleanType, options.itemFactory.objectType),
options.itemFactory.createString("equals")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -4809,8 +4751,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("hashCode")),
false),
label2,
@@ -4889,11 +4831,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.objectType,
+ options.itemFactory.objectType,
+ options.itemFactory.stringType),
options.itemFactory.createString("requireNonNull")),
false),
new CfReturn(ValueType.OBJECT),
@@ -4924,20 +4866,20 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.objectType,
+ options.itemFactory.objectType,
+ options.itemFactory.stringType),
options.itemFactory.createString("requireNonNull")),
false),
- new CfCheckCast(options.itemFactory.createType("Ljava/util/function/Supplier;")),
+ new CfCheckCast(
+ options.itemFactory.createSynthesizedType("Ljava/util/function/Supplier;")),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/function/Supplier;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/function/Supplier;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("get")),
true),
new CfStore(ValueType.OBJECT, 2),
@@ -4947,11 +4889,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.objectType,
+ options.itemFactory.objectType,
+ options.itemFactory.stringType),
options.itemFactory.createString("requireNonNull")),
false),
new CfReturn(ValueType.OBJECT),
@@ -4975,16 +4917,16 @@
new CfLoad(ValueType.OBJECT, 0),
new CfIf(If.Type.NE, ValueType.OBJECT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.OBJECT, 1),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -5010,11 +4952,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringType,
+ options.itemFactory.objectType,
+ options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfReturn(ValueType.OBJECT),
@@ -5043,9 +4985,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.objectType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
label2,
@@ -5071,8 +5012,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Optional;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5082,18 +5023,16 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Optional;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("get")),
false),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/function/Consumer;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/function/Consumer;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.voidType, options.itemFactory.objectType),
options.itemFactory.createString("accept")),
true),
new CfGoto(label3),
@@ -5102,8 +5041,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Runnable;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Runnable;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("run")),
true),
label3,
@@ -5130,8 +5069,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalDouble;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5141,16 +5080,17 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalDouble;"),
- options.itemFactory.createProto(options.itemFactory.createType("D")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+ options.itemFactory.createProto(options.itemFactory.doubleType),
options.itemFactory.createString("getAsDouble")),
false),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/function/DoubleConsumer;"),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/util/function/DoubleConsumer;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("D")),
+ options.itemFactory.voidType, options.itemFactory.doubleType),
options.itemFactory.createString("accept")),
true),
new CfGoto(label3),
@@ -5159,8 +5099,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Runnable;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Runnable;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("run")),
true),
label3,
@@ -5187,8 +5127,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalInt;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5198,16 +5138,16 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalInt;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("getAsInt")),
false),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/function/IntConsumer;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/function/IntConsumer;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+ options.itemFactory.voidType, options.itemFactory.intType),
options.itemFactory.createString("accept")),
true),
new CfGoto(label3),
@@ -5216,8 +5156,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Runnable;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Runnable;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("run")),
true),
label3,
@@ -5244,8 +5184,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalLong;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5255,16 +5195,16 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalLong;"),
- options.itemFactory.createProto(options.itemFactory.createType("J")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+ options.itemFactory.createProto(options.itemFactory.longType),
options.itemFactory.createString("getAsLong")),
false),
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/function/LongConsumer;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/function/LongConsumer;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("J")),
+ options.itemFactory.voidType, options.itemFactory.longType),
options.itemFactory.createString("accept")),
true),
new CfGoto(label3),
@@ -5273,8 +5213,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Runnable;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Runnable;"),
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("run")),
true),
label3,
@@ -5299,8 +5239,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Optional;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -5330,8 +5270,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalDouble;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -5361,8 +5301,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalInt;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -5392,8 +5332,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalLong;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.NE, ValueType.INT, label1),
@@ -5425,10 +5365,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -5437,8 +5376,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Optional;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label3),
@@ -5450,25 +5389,23 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/function/Supplier;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/function/Supplier;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("get")),
true),
- new CfCheckCast(options.itemFactory.createType("Ljava/util/Optional;")),
+ new CfCheckCast(options.itemFactory.createSynthesizedType("Ljava/util/Optional;")),
new CfStore(ValueType.OBJECT, 2),
label4,
new CfLoad(ValueType.OBJECT, 2),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Objects;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/Objects;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.objectType, options.itemFactory.objectType),
options.itemFactory.createString("requireNonNull")),
false),
- new CfCheckCast(options.itemFactory.createType("Ljava/util/Optional;")),
+ new CfCheckCast(options.itemFactory.createSynthesizedType("Ljava/util/Optional;")),
new CfReturn(ValueType.OBJECT),
label5),
ImmutableList.of(),
@@ -5490,8 +5427,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Optional;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5500,18 +5437,17 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Optional;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Optional;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("get")),
false),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/Stream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/Stream;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
+ options.itemFactory.objectType),
options.itemFactory.createString("of")),
true),
new CfReturn(ValueType.OBJECT),
@@ -5519,9 +5455,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/Stream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/Stream;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;")),
options.itemFactory.createString("empty")),
true),
new CfReturn(ValueType.OBJECT),
@@ -5545,8 +5481,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalDouble;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5555,17 +5491,18 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalDouble;"),
- options.itemFactory.createProto(options.itemFactory.createType("D")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalDouble;"),
+ options.itemFactory.createProto(options.itemFactory.doubleType),
options.itemFactory.createString("getAsDouble")),
false),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/DoubleStream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
- options.itemFactory.createType("D")),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/util/stream/DoubleStream;"),
+ options.itemFactory.doubleType),
options.itemFactory.createString("of")),
true),
new CfReturn(ValueType.OBJECT),
@@ -5573,9 +5510,10 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/DoubleStream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/DoubleStream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/DoubleStream;")),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/util/stream/DoubleStream;")),
options.itemFactory.createString("empty")),
true),
new CfReturn(ValueType.OBJECT),
@@ -5599,8 +5537,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalInt;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5609,17 +5547,17 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalInt;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalInt;"),
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("getAsInt")),
false),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/IntStream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/IntStream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/IntStream;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/IntStream;"),
+ options.itemFactory.intType),
options.itemFactory.createString("of")),
true),
new CfReturn(ValueType.OBJECT),
@@ -5627,9 +5565,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/IntStream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/IntStream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/IntStream;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/IntStream;")),
options.itemFactory.createString("empty")),
true),
new CfReturn(ValueType.OBJECT),
@@ -5653,8 +5591,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalLong;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("isPresent")),
false),
new CfIf(If.Type.EQ, ValueType.INT, label2),
@@ -5663,17 +5601,17 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/OptionalLong;"),
- options.itemFactory.createProto(options.itemFactory.createType("J")),
+ options.itemFactory.createSynthesizedType("Ljava/util/OptionalLong;"),
+ options.itemFactory.createProto(options.itemFactory.longType),
options.itemFactory.createString("getAsLong")),
false),
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/LongStream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/LongStream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/LongStream;"),
- options.itemFactory.createType("J")),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/LongStream;"),
+ options.itemFactory.longType),
options.itemFactory.createString("of")),
true),
new CfReturn(ValueType.OBJECT),
@@ -5681,9 +5619,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/LongStream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/LongStream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/LongStream;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/LongStream;")),
options.itemFactory.createString("empty")),
true),
new CfReturn(ValueType.OBJECT),
@@ -5785,9 +5723,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/Stream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/Stream;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;")),
options.itemFactory.createString("empty")),
true),
new CfGoto(label2),
@@ -5796,10 +5734,10 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/stream/Stream;"),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/stream/Stream;"),
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/stream/Stream;"),
+ options.itemFactory.objectType),
options.itemFactory.createString("of")),
true),
label2,
@@ -5833,8 +5771,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
false),
new CfStore(ValueType.INT, 2),
@@ -5848,9 +5786,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("codePointAt")),
false),
new CfStore(ValueType.INT, 3),
@@ -5859,9 +5797,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+ options.itemFactory.booleanType, options.itemFactory.intType),
options.itemFactory.createString("isWhitespace")),
false),
new CfIf(If.Type.NE, ValueType.INT, label6),
@@ -5874,9 +5812,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("charCount")),
false),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -5911,27 +5849,27 @@
label0,
new CfLoad(ValueType.OBJECT, 0),
new CfIf(If.Type.NE, ValueType.OBJECT, label1),
- new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfConstString(options.itemFactory.createString("delimiter")),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 2),
@@ -5947,10 +5885,10 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/CharSequence;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.charSequenceType),
options.itemFactory.createString("append")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -5968,10 +5906,10 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/CharSequence;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.charSequenceType),
options.itemFactory.createString("append")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -5983,10 +5921,10 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/CharSequence;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.charSequenceType),
options.itemFactory.createString("append")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -5998,9 +5936,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfReturn(ValueType.OBJECT),
@@ -6028,27 +5965,27 @@
label0,
new CfLoad(ValueType.OBJECT, 0),
new CfIf(If.Type.NE, ValueType.OBJECT, label1),
- new CfNew(options.itemFactory.createType("Ljava/lang/NullPointerException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfConstString(options.itemFactory.createString("delimiter")),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/NullPointerException;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/NullPointerException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 2),
@@ -6057,9 +5994,9 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Iterable;"),
+ options.itemFactory.createSynthesizedType("Ljava/lang/Iterable;"),
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/util/Iterator;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;")),
options.itemFactory.createString("iterator")),
true),
new CfStore(ValueType.OBJECT, 3),
@@ -6068,8 +6005,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("hasNext")),
true),
new CfIf(If.Type.EQ, ValueType.INT, label8),
@@ -6079,19 +6016,18 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("next")),
true),
- new CfCheckCast(options.itemFactory.createType("Ljava/lang/CharSequence;")),
+ new CfCheckCast(options.itemFactory.charSequenceType),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/CharSequence;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.charSequenceType),
options.itemFactory.createString("append")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -6100,8 +6036,8 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(options.itemFactory.createType("Z")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.booleanType),
options.itemFactory.createString("hasNext")),
true),
new CfIf(If.Type.EQ, ValueType.INT, label8),
@@ -6111,10 +6047,10 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/CharSequence;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.charSequenceType),
options.itemFactory.createString("append")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -6124,19 +6060,18 @@
new CfInvoke(
185,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/util/Iterator;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/Object;")),
+ options.itemFactory.createSynthesizedType("Ljava/util/Iterator;"),
+ options.itemFactory.createProto(options.itemFactory.objectType),
options.itemFactory.createString("next")),
true),
- new CfCheckCast(options.itemFactory.createType("Ljava/lang/CharSequence;")),
+ new CfCheckCast(options.itemFactory.charSequenceType),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/CharSequence;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.charSequenceType),
options.itemFactory.createString("append")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -6146,9 +6081,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfReturn(ValueType.OBJECT),
@@ -6181,52 +6115,50 @@
new CfLoad(ValueType.INT, 1),
new CfIf(If.Type.GE, ValueType.INT, label2),
label1,
- new CfNew(options.itemFactory.createType("Ljava/lang/IllegalArgumentException;")),
+ new CfNew(
+ options.itemFactory.createSynthesizedType("Ljava/lang/IllegalArgumentException;")),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(options.itemFactory.createType("V")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.voidType),
options.itemFactory.createString("<init>")),
false),
new CfConstString(options.itemFactory.createString("count is negative: ")),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfLoad(ValueType.INT, 1),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringBuilderType, options.itemFactory.intType),
options.itemFactory.createString("append")),
false),
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/IllegalArgumentException;"),
+ options.itemFactory.createSynthesizedType(
+ "Ljava/lang/IllegalArgumentException;"),
options.itemFactory.createProto(
- options.itemFactory.createType("V"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.voidType, options.itemFactory.stringType),
options.itemFactory.createString("<init>")),
false),
new CfThrow(),
@@ -6235,8 +6167,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
false),
new CfStore(ValueType.INT, 2),
@@ -6256,7 +6188,7 @@
new CfLoad(ValueType.OBJECT, 0),
new CfReturn(ValueType.OBJECT),
label7,
- new CfNew(options.itemFactory.createType("Ljava/lang/StringBuilder;")),
+ new CfNew(options.itemFactory.stringBuilderType),
new CfStackInstruction(CfStackInstruction.Opcode.Dup),
new CfLoad(ValueType.INT, 2),
new CfLoad(ValueType.INT, 1),
@@ -6264,9 +6196,9 @@
new CfInvoke(
183,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("V"), options.itemFactory.createType("I")),
+ options.itemFactory.voidType, options.itemFactory.intType),
options.itemFactory.createString("<init>")),
false),
new CfStore(ValueType.OBJECT, 3),
@@ -6283,10 +6215,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
+ options.itemFactory.stringBuilderType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType, options.itemFactory.stringType),
options.itemFactory.createString("append")),
false),
new CfStackInstruction(CfStackInstruction.Opcode.Pop),
@@ -6298,9 +6229,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/StringBuilder;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;")),
+ options.itemFactory.stringBuilderType,
+ options.itemFactory.createProto(options.itemFactory.stringType),
options.itemFactory.createString("toString")),
false),
new CfReturn(ValueType.OBJECT),
@@ -6339,8 +6269,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
false),
new CfStore(ValueType.INT, 2),
@@ -6354,9 +6284,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("codePointAt")),
false),
new CfStore(ValueType.INT, 3),
@@ -6365,9 +6295,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+ options.itemFactory.booleanType, options.itemFactory.intType),
options.itemFactory.createString("isWhitespace")),
false),
new CfIf(If.Type.NE, ValueType.INT, label6),
@@ -6379,9 +6309,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("charCount")),
false),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -6398,11 +6328,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"),
- options.itemFactory.createType("Ljava/lang/CharSequence;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.intType,
+ options.itemFactory.charSequenceType,
+ options.itemFactory.intType),
options.itemFactory.createString("codePointBefore")),
false),
new CfStore(ValueType.INT, 3),
@@ -6411,9 +6341,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+ options.itemFactory.booleanType, options.itemFactory.intType),
options.itemFactory.createString("isWhitespace")),
false),
new CfIf(If.Type.NE, ValueType.INT, label12),
@@ -6425,9 +6355,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("charCount")),
false),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
@@ -6441,11 +6371,11 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("substring")),
false),
new CfReturn(ValueType.OBJECT),
@@ -6478,8 +6408,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
false),
new CfStore(ValueType.INT, 2),
@@ -6493,9 +6423,9 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("codePointAt")),
false),
new CfStore(ValueType.INT, 3),
@@ -6504,9 +6434,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+ options.itemFactory.booleanType, options.itemFactory.intType),
options.itemFactory.createString("isWhitespace")),
false),
new CfIf(If.Type.NE, ValueType.INT, label6),
@@ -6518,9 +6448,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("charCount")),
false),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, NumericType.INT),
@@ -6534,11 +6464,11 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("substring")),
false),
new CfReturn(ValueType.OBJECT),
@@ -6567,8 +6497,8 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createProto(options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.createProto(options.itemFactory.intType),
options.itemFactory.createString("length")),
false),
new CfStore(ValueType.INT, 1),
@@ -6581,11 +6511,11 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"),
- options.itemFactory.createType("Ljava/lang/CharSequence;"),
- options.itemFactory.createType("I")),
+ options.itemFactory.intType,
+ options.itemFactory.charSequenceType,
+ options.itemFactory.intType),
options.itemFactory.createString("codePointBefore")),
false),
new CfStore(ValueType.INT, 2),
@@ -6594,9 +6524,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("Z"), options.itemFactory.createType("I")),
+ options.itemFactory.booleanType, options.itemFactory.intType),
options.itemFactory.createString("isWhitespace")),
false),
new CfIf(If.Type.NE, ValueType.INT, label5),
@@ -6608,9 +6538,9 @@
new CfInvoke(
184,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Character;"),
+ options.itemFactory.boxedCharType,
options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("I")),
+ options.itemFactory.intType, options.itemFactory.intType),
options.itemFactory.createString("charCount")),
false),
new CfArithmeticBinop(CfArithmeticBinop.Opcode.Sub, NumericType.INT),
@@ -6624,11 +6554,11 @@
new CfInvoke(
182,
options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/String;"),
+ options.itemFactory.stringType,
options.itemFactory.createProto(
- options.itemFactory.createType("Ljava/lang/String;"),
- options.itemFactory.createType("I"),
- options.itemFactory.createType("I")),
+ options.itemFactory.stringType,
+ options.itemFactory.intType,
+ options.itemFactory.intType),
options.itemFactory.createString("substring")),
false),
new CfReturn(ValueType.OBJECT),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
index 9e78a3b..ee175f9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodGenerators.java
@@ -73,7 +73,7 @@
InternalOptions options, DexMethod method, int formalCount) {
DexType mapEntryArray =
options.itemFactory.createArrayType(1, options.itemFactory.mapEntryType);
- DexType simpleEntry = options.itemFactory.createType("Ljava/util/AbstractMap$SimpleEntry;");
+ DexType simpleEntry = options.itemFactory.abstractMapSimpleEntryType;
DexMethod simpleEntryConstructor = options.itemFactory.createMethod(
simpleEntry,
options.itemFactory.createProto(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 55db2fd..5b695a7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -25,7 +25,6 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.equivalence.BasicBlockBehavioralSubsumption;
-import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
@@ -86,7 +85,6 @@
import com.android.tools.r8.utils.SetUtils;
import com.google.common.base.Equivalence;
import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
@@ -131,6 +129,7 @@
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
+import java.util.function.Supplier;
public class CodeRewriter {
@@ -3113,7 +3112,7 @@
dexItemFactory.throwableMethods.initCause,
code.createValue(
TypeLatticeElement.fromDexType(
- dexItemFactory.throwableType, Nullability.maybeNull(), appView)),
+ dexItemFactory.throwableType, maybeNull(), appView)),
initCauseArguments);
initCause.setPosition(current.getPosition());
insnIterator.add(initCause);
@@ -3352,8 +3351,8 @@
// Now that the block is split there should not be any catch handlers in the block.
assert !block.hasCatchHandlers();
- DexType javaLangSystemType = dexItemFactory.createType("Ljava/lang/System;");
- DexType javaIoPrintStreamType = dexItemFactory.createType("Ljava/io/PrintStream;");
+ DexType javaLangSystemType = dexItemFactory.javaLangSystemType;
+ DexType javaIoPrintStreamType = dexItemFactory.javaIoPrintStreamType;
Value out =
code.createValue(
TypeLatticeElement.fromDexType(javaIoPrintStreamType, definitelyNotNull(), appView));
@@ -3583,13 +3582,6 @@
// See comment for InternalOptions.canHaveNumberConversionRegisterAllocationBug().
public void workaroundNumberConversionRegisterAllocationBug(IRCode code) {
- final Supplier<DexMethod> javaLangDoubleisNaN = Suppliers.memoize(() ->
- dexItemFactory.createMethod(
- dexItemFactory.createString("Ljava/lang/Double;"),
- dexItemFactory.createString("isNaN"),
- dexItemFactory.booleanDescriptor,
- new DexString[]{dexItemFactory.doubleDescriptor}));
-
ListIterator<BasicBlock> blocks = code.listIterator();
while (blocks.hasNext()) {
BasicBlock block = blocks.next();
@@ -3607,7 +3599,8 @@
&& value.definition.isNumberConversion()
&& value.definition.asNumberConversion().to == NumericType.DOUBLE) {
InvokeStatic invokeIsNaN =
- new InvokeStatic(javaLangDoubleisNaN.get(), null, ImmutableList.of(value));
+ new InvokeStatic(
+ dexItemFactory.doubleMethods.isNaN, null, ImmutableList.of(value));
invokeIsNaN.setPosition(instruction.getPosition());
// Insert the invoke before the current instruction.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index a4c70be..96819d0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -15,13 +15,13 @@
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.graph.ResolutionResult.SingleResolutionResult;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.optimize.Inliner.Constraint;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import java.util.Collection;
import java.util.function.BiFunction;
// Computes the inlining constraint for a given instruction.
@@ -442,9 +442,11 @@
// For each of the actual potential targets, derive constraints based on the accessibility
// of the method itself.
- Collection<DexEncodedMethod> targets =
- resolutionResult.lookupVirtualDispatchTargets(appView.appInfo());
- for (DexEncodedMethod target : targets) {
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ if (lookupResult.isLookupResultFailure()) {
+ return ConstraintWithTarget.NEVER;
+ }
+ for (DexEncodedMethod target : lookupResult.asLookupResultSuccess().getMethodTargets()) {
methodHolder = graphLense.lookupType(target.method.holder);
assert appView.definitionFor(methodHolder) != null;
methodConstraintWithTarget =
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
index cf4f72b..2c8e6b9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/SwitchMapCollector.java
@@ -73,7 +73,7 @@
DexItemFactory dexItemFactory = appView.dexItemFactory();
switchMapPrefix = dexItemFactory.createString("$SwitchMap$");
kotlinSwitchMapPrefix = dexItemFactory.createString("$EnumSwitchMapping$");
- intArrayType = dexItemFactory.createType("[I");
+ intArrayType = dexItemFactory.intArrayType;
}
public AppInfoWithLiveness run() {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
index 8fee6c5..6512985 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaMerger.java
@@ -234,7 +234,9 @@
cls.hasKotlinInfo()
&& cls.getKotlinInfo().isSyntheticClass()
&& cls.getKotlinInfo().asSyntheticClass().isLambda()
- && KotlinLambdaGroupIdFactory.hasValidAnnotations(kotlin, cls))
+ && KotlinLambdaGroupIdFactory.hasValidAnnotations(kotlin, cls)
+ && (appView.options().featureSplitConfiguration == null
+ || !appView.options().featureSplitConfiguration.isInFeature(cls)))
.sorted((a, b) -> a.type.slowCompareTo(b.type)) // Ensure stable ordering.
.forEachOrdered(
lambda -> {
@@ -358,7 +360,7 @@
// Rewrite lambda class references into lambda group class
// references inside methods from the processing queue.
- rewriteLambdaReferences(converter, executorService, feedback);
+ rewriteLambdaReferences(converter, executorService);
this.mode = null;
appView.setHorizontallyMergedLambdaClasses(
@@ -423,8 +425,7 @@
}
}
- private void rewriteLambdaReferences(
- IRConverter converter, ExecutorService executorService, OptimizationFeedback feedback)
+ private void rewriteLambdaReferences(IRConverter converter, ExecutorService executorService)
throws ExecutionException {
if (methodsToReprocess.isEmpty()) {
return;
@@ -440,27 +441,22 @@
private void analyzeClass(DexProgramClass clazz) {
lambdaInvalidator.accept(clazz.superType);
lambdaInvalidator.accept(clazz.interfaces);
- lambdaInvalidator.accept(clazz.annotations);
+ lambdaInvalidator.accept(clazz.annotations());
for (DexEncodedField field : clazz.staticFields()) {
- lambdaInvalidator.accept(field.annotations);
+ lambdaInvalidator.accept(field.annotations());
if (field.field.type != clazz.type) {
// Ignore static fields of the same type.
lambdaInvalidator.accept(field.field, clazz.type);
}
}
for (DexEncodedField field : clazz.instanceFields()) {
- lambdaInvalidator.accept(field.annotations);
+ lambdaInvalidator.accept(field.annotations());
lambdaInvalidator.accept(field.field, clazz.type);
}
- for (DexEncodedMethod method : clazz.directMethods()) {
- lambdaInvalidator.accept(method.annotations);
- lambdaInvalidator.accept(method.parameterAnnotationsList);
- lambdaInvalidator.accept(method.method, clazz.type);
- }
- for (DexEncodedMethod method : clazz.virtualMethods()) {
- lambdaInvalidator.accept(method.annotations);
+ for (DexEncodedMethod method : clazz.methods()) {
+ lambdaInvalidator.accept(method.annotations());
lambdaInvalidator.accept(method.parameterAnnotationsList);
lambdaInvalidator.accept(method.method, clazz.type);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupId.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupId.java
index 996099b..b1fabf6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupId.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupId.java
@@ -60,7 +60,7 @@
this.signature = signature;
this.mainMethodName = mainMethod.method.name;
this.mainMethodProto = mainMethod.method.proto;
- this.mainMethodAnnotations = mainMethod.annotations;
+ this.mainMethodAnnotations = mainMethod.annotations();
this.mainMethodParamAnnotations = mainMethod.parameterAnnotationsList;
this.innerClassAccess = inner != null ? inner.getAccess() : MISSING_INNER_CLASS_ATTRIBUTE;
this.enclosing = enclosing;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupIdFactory.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupIdFactory.java
index 568a8cb..9344464 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupIdFactory.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupIdFactory.java
@@ -87,40 +87,36 @@
}
public static boolean hasValidAnnotations(Kotlin kotlin, DexClass lambda) {
- if (!lambda.annotations.isEmpty()) {
- for (DexAnnotation annotation : lambda.annotations.annotations) {
- if (DexAnnotation.isSignatureAnnotation(annotation, kotlin.factory)) {
- continue;
- }
- if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
- continue;
- }
- return false;
+ for (DexAnnotation annotation : lambda.annotations().annotations) {
+ if (DexAnnotation.isSignatureAnnotation(annotation, kotlin.factory)) {
+ continue;
}
+ if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
+ continue;
+ }
+ return false;
}
return true;
}
String validateAnnotations(Kotlin kotlin, DexClass lambda) throws LambdaStructureError {
String signature = null;
- if (!lambda.annotations.isEmpty()) {
- for (DexAnnotation annotation : lambda.annotations.annotations) {
- if (DexAnnotation.isSignatureAnnotation(annotation, kotlin.factory)) {
- signature = DexAnnotation.getSignature(annotation);
- continue;
- }
-
- if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
- // Ignore kotlin metadata on lambda classes. Metadata on synthetic
- // classes exists but is not used in the current Kotlin version (1.2.21)
- // and newly generated lambda _group_ class is not exactly a kotlin class.
- continue;
- }
-
- assert !hasValidAnnotations(kotlin, lambda);
- throw new LambdaStructureError(
- "unexpected annotation: " + annotation.annotation.type.toSourceString());
+ for (DexAnnotation annotation : lambda.annotations().annotations) {
+ if (DexAnnotation.isSignatureAnnotation(annotation, kotlin.factory)) {
+ signature = DexAnnotation.getSignature(annotation);
+ continue;
}
+
+ if (annotation.annotation.type == kotlin.metadata.kotlinMetadataType) {
+ // Ignore kotlin metadata on lambda classes. Metadata on synthetic
+ // classes exists but is not used in the current Kotlin version (1.2.21)
+ // and newly generated lambda _group_ class is not exactly a kotlin class.
+ continue;
+ }
+
+ assert !hasValidAnnotations(kotlin, lambda);
+ throw new LambdaStructureError(
+ "unexpected annotation: " + annotation.annotation.type.toSourceString());
}
assert hasValidAnnotations(kotlin, lambda);
return signature;
@@ -206,21 +202,31 @@
}
}
- void checkDirectMethodAnnotations(DexEncodedMethod method) throws LambdaStructureError {
- if (!method.annotations.isEmpty()) {
- throw new LambdaStructureError("unexpected method annotations [" +
- method.annotations.toSmaliString() + "] on " + method.method.toSourceString());
+ private static void checkDirectMethodAnnotations(DexEncodedMethod method)
+ throws LambdaStructureError {
+ if (!method.annotations().isEmpty()) {
+ throw new LambdaStructureError(
+ "unexpected method annotations ["
+ + method.annotations().toSmaliString()
+ + "] on "
+ + method.method.toSourceString());
}
if (!method.parameterAnnotationsList.isEmpty()) {
- throw new LambdaStructureError("unexpected method parameters annotations [" +
- method.annotations.toSmaliString() + "] on " + method.method.toSourceString());
+ throw new LambdaStructureError(
+ "unexpected method parameters annotations ["
+ + method.parameterAnnotationsList.toSmaliString()
+ + "] on "
+ + method.method.toSourceString());
}
}
private static void checkFieldAnnotations(DexEncodedField field) throws LambdaStructureError {
- if (!field.annotations.isEmpty()) {
- throw new LambdaStructureError("unexpected field annotations [" +
- field.annotations.toSmaliString() + "] on " + field.field.toSourceString());
+ if (field.hasAnnotation()) {
+ throw new LambdaStructureError(
+ "unexpected field annotations ["
+ + field.annotations().toSmaliString()
+ + "] on "
+ + field.field.toSourceString());
}
}
@@ -231,8 +237,8 @@
}
@SafeVarargs
- static <T extends AccessFlags> void checkAccessFlags(String message, int actual, T... expected)
- throws LambdaStructureError {
+ private static <T extends AccessFlags> void checkAccessFlags(
+ String message, int actual, T... expected) throws LambdaStructureError {
for (T flag : expected) {
if (actual == flag.materialize()) {
return;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMethodOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMethodOptimizer.java
index e2999df..d61b6ae 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMethodOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryMethodOptimizer.java
@@ -25,6 +25,9 @@
private final AppView<?> appView;
+ /** The library types that are modeled. */
+ private final Set<DexType> modeledLibraryTypes = Sets.newIdentityHashSet();
+
private final Map<DexType, LibraryMethodModelCollection> libraryMethodModelCollections =
new IdentityHashMap<>();
@@ -37,12 +40,35 @@
if (LogMethodOptimizer.isEnabled(appView)) {
register(new LogMethodOptimizer(appView));
}
+
+ LibraryOptimizationInfoInitializer libraryOptimizationInfoInitializer =
+ new LibraryOptimizationInfoInitializer(appView);
+ libraryOptimizationInfoInitializer.run();
+ modeledLibraryTypes.addAll(libraryOptimizationInfoInitializer.getModeledLibraryTypes());
+ }
+
+ /**
+ * Returns true if {@param type} is a library type that is modeled in the compiler.
+ *
+ * <p>In order for library modeling to work in D8, we return a definition for invoke instructions
+ * that are guaranteed to dispatch to a library method in {@link
+ * InvokeMethod#lookupSingleTarget(AppView, DexType)}. As part of that, we bail-out if the holder
+ * of the targeted method is not a library class. However, what is usually on the library path
+ * will be on the program path when compiling the framework itself. To ensure that our library
+ * modeling works also for the framework compilation, we maintain the set of types that we model,
+ * and treat these types as library types in {@link InvokeMethod#lookupSingleTarget(AppView,
+ * DexType)} although they are on the program path.
+ */
+ public boolean isModeled(DexType type) {
+ return modeledLibraryTypes.contains(type);
}
private void register(LibraryMethodModelCollection optimizer) {
+ DexType modeledType = optimizer.getType();
LibraryMethodModelCollection existing =
- libraryMethodModelCollections.put(optimizer.getType(), optimizer);
+ libraryMethodModelCollections.put(modeledType, optimizer);
assert existing == null;
+ modeledLibraryTypes.add(modeledType);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
index 050640c..4cd152f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LibraryOptimizationInfoInitializer.java
@@ -8,8 +8,11 @@
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.DexType;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackSimple;
+import com.google.common.collect.Sets;
import java.util.BitSet;
+import java.util.Set;
public class LibraryOptimizationInfoInitializer {
@@ -17,21 +20,26 @@
private final DexItemFactory dexItemFactory;
private final OptimizationFeedbackSimple feedback = OptimizationFeedbackSimple.getInstance();
+ private final Set<DexType> modeledLibraryTypes = Sets.newIdentityHashSet();
- public LibraryOptimizationInfoInitializer(AppView<?> appView) {
+ LibraryOptimizationInfoInitializer(AppView<?> appView) {
this.appView = appView;
this.dexItemFactory = appView.dexItemFactory();
}
- public void run() {
+ void run() {
modelLibraryMethodsReturningNonNull();
modelLibraryMethodsReturningReceiver();
modelRequireNonNullMethods();
}
+ Set<DexType> getModeledLibraryTypes() {
+ return modeledLibraryTypes;
+ }
+
private void modelLibraryMethodsReturningNonNull() {
for (DexMethod method : dexItemFactory.libraryMethodsReturningNonNull) {
- DexEncodedMethod definition = appView.definitionFor(method);
+ DexEncodedMethod definition = lookupMethod(method);
if (definition != null) {
feedback.methodNeverReturnsNull(definition);
}
@@ -40,7 +48,7 @@
private void modelLibraryMethodsReturningReceiver() {
for (DexMethod method : dexItemFactory.libraryMethodsReturningReceiver) {
- DexEncodedMethod definition = appView.definitionFor(method);
+ DexEncodedMethod definition = lookupMethod(method);
if (definition != null) {
feedback.methodReturnsArgument(definition, 0);
}
@@ -49,7 +57,7 @@
private void modelRequireNonNullMethods() {
for (DexMethod requireNonNullMethod : dexItemFactory.objectsMethods.requireNonNullMethods()) {
- DexEncodedMethod definition = appView.definitionFor(requireNonNullMethod);
+ DexEncodedMethod definition = lookupMethod(requireNonNullMethod);
if (definition != null) {
feedback.methodReturnsArgument(definition, 0);
@@ -63,4 +71,13 @@
}
}
}
+
+ private DexEncodedMethod lookupMethod(DexMethod method) {
+ DexEncodedMethod encodedMethod = appView.definitionFor(method);
+ if (encodedMethod != null) {
+ modeledLibraryTypes.add(method.holder);
+ return encodedMethod;
+ }
+ return null;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/library/LogMethodOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/library/LogMethodOptimizer.java
index 6cd36b3..35220c7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/library/LogMethodOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/library/LogMethodOptimizer.java
@@ -42,7 +42,7 @@
this.appView = appView;
DexItemFactory dexItemFactory = appView.dexItemFactory();
- DexType logType = dexItemFactory.createType("Landroid/util/Log;");
+ DexType logType = dexItemFactory.androidUtilLogType;
this.logType = logType;
this.isLoggableMethod =
dexItemFactory.createMethod(
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 1600057..d458662 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -139,7 +139,7 @@
int access = clazz.accessFlags.getAsCfAccessFlags();
String desc = namingLens.lookupDescriptor(clazz.type).toString();
String name = namingLens.lookupInternalName(clazz.type);
- String signature = getSignature(clazz.annotations);
+ String signature = getSignature(clazz.annotations());
String superName =
clazz.type == options.itemFactory.objectType
? null
@@ -149,8 +149,8 @@
interfaces[i] = namingLens.lookupInternalName(clazz.interfaces.values[i]);
}
writer.visit(version, access, name, signature, superName, interfaces);
- writeAnnotations(writer::visitAnnotation, clazz.annotations.annotations);
- ImmutableMap<DexString, DexValue> defaults = getAnnotationDefaults(clazz.annotations);
+ writeAnnotations(writer::visitAnnotation, clazz.annotations().annotations);
+ ImmutableMap<DexString, DexValue> defaults = getAnnotationDefaults(clazz.annotations());
if (clazz.getEnclosingMethod() != null) {
clazz.getEnclosingMethod().write(writer, namingLens);
@@ -291,10 +291,10 @@
int access = field.accessFlags.getAsCfAccessFlags();
String name = namingLens.lookupName(field.field).toString();
String desc = namingLens.lookupDescriptor(field.field.type).toString();
- String signature = getSignature(field.annotations);
+ String signature = getSignature(field.annotations());
Object value = getStaticValue(field);
FieldVisitor visitor = writer.visitField(access, name, desc, signature, value);
- writeAnnotations(visitor::visitAnnotation, field.annotations.annotations);
+ writeAnnotations(visitor::visitAnnotation, field.annotations().annotations);
visitor.visitEnd();
}
@@ -306,8 +306,8 @@
int access = method.accessFlags.getAsCfAccessFlags();
String name = namingLens.lookupName(method.method).toString();
String desc = method.descriptor(namingLens);
- String signature = getSignature(method.annotations);
- String[] exceptions = getExceptions(method.annotations);
+ String signature = getSignature(method.annotations());
+ String[] exceptions = getExceptions(method.annotations());
MethodVisitor visitor = writer.visitMethod(access, name, desc, signature, exceptions);
if (defaults.containsKey(method.method.name)) {
AnnotationVisitor defaultVisitor = visitor.visitAnnotationDefault();
@@ -316,8 +316,8 @@
defaultVisitor.visitEnd();
}
}
- writeMethodParametersAnnotation(visitor, method.annotations.annotations);
- writeAnnotations(visitor::visitAnnotation, method.annotations.annotations);
+ writeMethodParametersAnnotation(visitor, method.annotations().annotations);
+ writeAnnotations(visitor::visitAnnotation, method.annotations().annotations);
writeParameterAnnotations(visitor, method.parameterAnnotationsList);
if (!method.shouldNotHaveCode()) {
writeCode(method, visitor, classFileVersion);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
index a195f97..fec6a34 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinClassMetadataReader.java
@@ -25,10 +25,7 @@
Kotlin kotlin,
DexClass clazz,
DiagnosticsHandler reporter) {
- if (clazz.annotations.isEmpty()) {
- return null;
- }
- DexAnnotation meta = clazz.annotations.getFirstMatching(kotlin.metadata.kotlinMetadataType);
+ DexAnnotation meta = clazz.annotations().getFirstMatching(kotlin.metadata.kotlinMetadataType);
if (meta != null) {
try {
return createKotlinInfo(kotlin, clazz, meta.annotation);
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
index 7a1a343..56d9359 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinInfo.java
@@ -5,7 +5,6 @@
package com.android.tools.r8.kotlin;
import static com.android.tools.r8.kotlin.KotlinMetadataSynthesizer.toRenamedKmFunction;
-import static com.android.tools.r8.kotlin.KotlinMetadataSynthesizer.toRenamedKmFunctionAsExtension;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
@@ -119,21 +118,14 @@
continue;
}
- if (method.isKotlinExtensionFunction()) {
- KmFunction extension = toRenamedKmFunctionAsExtension(method, appView, lens);
- if (extension != null) {
- functions.add(extension);
- }
- continue;
- }
- if (method.isKotlinFunction()) {
+ if (method.isKotlinFunction() || method.isKotlinExtensionFunction()) {
KmFunction function = toRenamedKmFunction(method, appView, lens);
if (function != null) {
functions.add(function);
}
continue;
}
- if (method.isKotlinProperty()) {
+ if (method.isKotlinProperty() || method.isKotlinExtensionProperty()) {
String name = method.getKotlinMemberInfo().propertyName;
assert name != null;
KmPropertyGroup.Builder builder =
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMemberInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMemberInfo.java
index 62b5355..50058ec 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMemberInfo.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMemberInfo.java
@@ -14,34 +14,84 @@
import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmFunctionProcessor;
import com.android.tools.r8.kotlin.KotlinMetadataJvmExtensionUtils.KmPropertyProcessor;
import com.android.tools.r8.utils.Reporter;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import kotlinx.metadata.KmDeclarationContainer;
import kotlinx.metadata.KmFunction;
import kotlinx.metadata.KmProperty;
+import kotlinx.metadata.KmValueParameter;
// Provides access to field/method-level Kotlin information.
public class KotlinMemberInfo {
- private static KotlinMemberInfo NO_KOTLIN_MEMBER_INFO = new KotlinMemberInfo(MemberKind.NONE, 0);
+ private static final List<KmValueParameter> EMPTY_PARAM = ImmutableList.of();
+ private static final List<KotlinValueParameterInfo> EMPTY_PARAM_INFO = ImmutableList.of();
+
+ private static final KotlinMemberInfo NO_KOTLIN_MEMBER_INFO =
+ new KotlinMemberInfo(MemberKind.NONE, 0, EMPTY_PARAM);
public static KotlinMemberInfo getNoKotlinMemberInfo() {
return NO_KOTLIN_MEMBER_INFO;
}
public final MemberKind memberKind;
- // Original flag. May be necessary to keep Kotlin-specific flag, e.g., inline function.
+ // Original member flag. May be necessary to keep Kotlin-specific flag, e.g., suspend function.
final int flag;
// Original property name for (extension) property. Otherwise, null.
final String propertyName;
+ // Information from original KmValueParameter(s) if available. Otherwise, null.
+ private final List<KotlinValueParameterInfo> valueParameterInfos;
- private KotlinMemberInfo(MemberKind memberKind, int flag) {
- this(memberKind, flag, null);
+ // Constructor for KmFunction
+ private KotlinMemberInfo(
+ MemberKind memberKind, int flag, List<KmValueParameter> kmValueParameters) {
+ this(memberKind, flag, null, kmValueParameters);
}
+ // Constructor for a backing field and a getter in KmProperty
private KotlinMemberInfo(MemberKind memberKind, int flag, String propertyName) {
+ this(memberKind, flag, propertyName, EMPTY_PARAM);
+ }
+
+ // Constructor for a setter in KmProperty
+ private KotlinMemberInfo(
+ MemberKind memberKind,
+ int flag,
+ String propertyName,
+ KmValueParameter kmValueParameter) {
+ this(memberKind, flag, propertyName,
+ kmValueParameter != null ? ImmutableList.of(kmValueParameter) : EMPTY_PARAM);
+ }
+
+ private KotlinMemberInfo(
+ MemberKind memberKind,
+ int flag,
+ String propertyName,
+ List<KmValueParameter> kmValueParameters) {
this.memberKind = memberKind;
this.flag = flag;
this.propertyName = propertyName;
+ assert kmValueParameters != null;
+ if (kmValueParameters.isEmpty()) {
+ this.valueParameterInfos = EMPTY_PARAM_INFO;
+ } else {
+ this.valueParameterInfos = new ArrayList<>(kmValueParameters.size());
+ for (KmValueParameter kmValueParameter : kmValueParameters) {
+ valueParameterInfos.add(KotlinValueParameterInfo.fromKmValueParameter(kmValueParameter));
+ }
+ }
+ }
+
+ KotlinValueParameterInfo getValueParameterInfo(int i) {
+ if (valueParameterInfos.isEmpty()) {
+ return null;
+ }
+ if (i < 0 || i >= valueParameterInfos.size()) {
+ return null;
+ }
+ return valueParameterInfos.get(i);
}
public enum MemberKind {
@@ -151,10 +201,16 @@
KmFunction kmFunction = kmFunctionMap.get(key);
if (isExtension(kmFunction)) {
method.setKotlinMemberInfo(
- new KotlinMemberInfo(MemberKind.EXTENSION_FUNCTION, kmFunction.getFlags()));
+ new KotlinMemberInfo(
+ MemberKind.EXTENSION_FUNCTION,
+ kmFunction.getFlags(),
+ kmFunction.getValueParameters()));
} else {
method.setKotlinMemberInfo(
- new KotlinMemberInfo(MemberKind.FUNCTION, kmFunction.getFlags()));
+ new KotlinMemberInfo(
+ MemberKind.FUNCTION,
+ kmFunction.getFlags(),
+ kmFunction.getValueParameters()));
}
} else if (kmPropertyGetterMap.containsKey(key)) {
KmProperty kmProperty = kmPropertyGetterMap.get(key);
@@ -176,11 +232,15 @@
new KotlinMemberInfo(
MemberKind.EXTENSION_PROPERTY_SETTER,
kmProperty.getFlags(),
- kmProperty.getName()));
+ kmProperty.getName(),
+ kmProperty.getSetterParameter()));
} else {
method.setKotlinMemberInfo(
new KotlinMemberInfo(
- MemberKind.PROPERTY_SETTER, kmProperty.getFlags(), kmProperty.getName()));
+ MemberKind.PROPERTY_SETTER,
+ kmProperty.getFlags(),
+ kmProperty.getName(),
+ kmProperty.getSetterParameter()));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
index b295da3..9507b32 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -47,7 +47,7 @@
public static void removeKotlinMetadataFromRenamedClass(AppView<?> appView, DexClass clazz) {
// Remove @Metadata in DexAnnotation form if a class is renamed.
- clazz.annotations = clazz.annotations.keepIf(anno -> isNotKotlinMetadata(appView, anno));
+ clazz.setAnnotations(clazz.annotations().keepIf(anno -> isNotKotlinMetadata(appView, anno)));
// Clear associated {@link KotlinInfo} to avoid accidentally deserialize it back to
// DexAnnotation we've just removed above.
if (clazz.isProgramClass()) {
@@ -72,11 +72,12 @@
// TODO(b/70169921): if this option is settled down, this assertion is meaningless.
assert lens.lookupType(clazz.type, appView.dexItemFactory()) == clazz.type
|| appView.options().enableKotlinMetadataRewritingForRenamedClasses
- : clazz.toSourceString() + " != "
+ : clazz.toSourceString()
+ + " != "
+ lens.lookupType(clazz.type, appView.dexItemFactory());
DexAnnotation oldMeta =
- clazz.annotations.getFirstMatching(kotlin.metadata.kotlinMetadataType);
+ clazz.annotations().getFirstMatching(kotlin.metadata.kotlinMetadataType);
// If @Metadata is already gone, e.g., by {@link AnnotationRemover} if type Metadata is
// determined as dead (e.g., due to no keep rule), nothing to do.
if (oldMeta == null) {
@@ -86,11 +87,11 @@
kotlinInfo.rewrite(appView, lens);
DexAnnotation newMeta = createKotlinMetadataAnnotation(kotlinInfo.createHeader());
- clazz.annotations = clazz.annotations.rewrite(anno -> anno == oldMeta ? newMeta : anno);
+ clazz.setAnnotations(
+ clazz.annotations().rewrite(anno -> anno == oldMeta ? newMeta : anno));
}
},
- executorService
- );
+ executorService);
}
private DexAnnotation createKotlinMetadataAnnotation(KotlinClassHeader header) {
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
index 94c65e3..6e959b6 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataSynthesizer.java
@@ -97,7 +97,7 @@
KmConstructor kmConstructor = new KmConstructor(method.accessFlags.getAsKotlinFlags());
JvmExtensionsKt.setSignature(kmConstructor, toJvmMethodSignature(method.method));
List<KmValueParameter> parameters = kmConstructor.getValueParameters();
- if (!populateKmValueParameters(parameters, method, appView, lens, false)) {
+ if (!populateKmValueParameters(parameters, method, appView, lens)) {
return null;
}
return kmConstructor;
@@ -107,21 +107,6 @@
DexEncodedMethod method,
AppView<AppInfoWithLiveness> appView,
NamingLens lens) {
- return toRenamedKmFunctionHelper(method, appView, lens, false);
- }
-
- static KmFunction toRenamedKmFunctionAsExtension(
- DexEncodedMethod method,
- AppView<AppInfoWithLiveness> appView,
- NamingLens lens) {
- return toRenamedKmFunctionHelper(method, appView, lens, true);
- }
-
- private static KmFunction toRenamedKmFunctionHelper(
- DexEncodedMethod method,
- AppView<AppInfoWithLiveness> appView,
- NamingLens lens,
- boolean isExtension) {
// For library overrides, synthesize @Metadata always.
// For regular methods, make sure it is live or pinned.
if (!method.isLibraryMethodOverride().isTrue()
@@ -146,7 +131,7 @@
return null;
}
kmFunction.setReturnType(kmReturnType);
- if (isExtension) {
+ if (method.isKotlinExtensionFunction()) {
assert method.method.proto.parameters.values.length > 0
: method.method.toSourceString();
KmType kmReceiverType =
@@ -157,7 +142,7 @@
kmFunction.setReceiverParameterType(kmReceiverType);
}
List<KmValueParameter> parameters = kmFunction.getValueParameters();
- if (!populateKmValueParameters(parameters, method, appView, lens, isExtension)) {
+ if (!populateKmValueParameters(parameters, method, appView, lens)) {
return null;
}
return kmFunction;
@@ -167,24 +152,53 @@
List<KmValueParameter> parameters,
DexEncodedMethod method,
AppView<AppInfoWithLiveness> appView,
- NamingLens lens,
- boolean isExtension) {
+ NamingLens lens) {
+ boolean isExtension = method.isKotlinExtensionFunction();
for (int i = isExtension ? 1 : 0; i < method.method.proto.parameters.values.length; i++) {
- DexType paramType = method.method.proto.parameters.values[i];
+ DexType parameterType = method.method.proto.parameters.values[i];
DebugLocalInfo debugLocalInfo = method.getParameterInfo().get(i);
String parameterName = debugLocalInfo != null ? debugLocalInfo.name.toString() : ("p" + i);
- // TODO(b/70169921): Consult kotlinx.metadata.Flag.ValueParameter.
- KmValueParameter kmValueParameter = new KmValueParameter(flagsOf(), parameterName);
- KmType kmParamType = toRenamedKmType(paramType, appView, lens);
- if (kmParamType == null) {
+ KotlinValueParameterInfo valueParameterInfo =
+ method.getKotlinMemberInfo().getValueParameterInfo(isExtension ? i - 1 : i);
+ KmValueParameter kmValueParameter =
+ toRewrittenKmValueParameter(
+ valueParameterInfo, parameterType, parameterName, appView, lens);
+ if (kmValueParameter == null) {
return false;
}
- kmValueParameter.setType(kmParamType);
parameters.add(kmValueParameter);
}
return true;
}
+ private static KmValueParameter toRewrittenKmValueParameter(
+ KotlinValueParameterInfo valueParameterInfo,
+ DexType parameterType,
+ String candidateParameterName,
+ AppView<AppInfoWithLiveness> appView,
+ NamingLens lens) {
+ KmType kmParamType = toRenamedKmType(parameterType, appView, lens);
+ if (kmParamType == null) {
+ return null;
+ }
+ int flag = valueParameterInfo != null ? valueParameterInfo.flag : flagsOf();
+ String name = valueParameterInfo != null ? valueParameterInfo.name : candidateParameterName;
+ KmValueParameter kmValueParameter = new KmValueParameter(flag, name);
+ kmValueParameter.setType(kmParamType);
+ if (valueParameterInfo != null && valueParameterInfo.isVararg) {
+ if (!parameterType.isArrayType()) {
+ return null;
+ }
+ DexType elementType = parameterType.toBaseType(appView.dexItemFactory());
+ KmType kmElementType = toRenamedKmType(elementType, appView, lens);
+ if (kmElementType == null) {
+ return null;
+ }
+ kmValueParameter.setVarargElementType(kmElementType);
+ }
+ return kmValueParameter;
+ }
+
/**
* A group of a field, and methods that correspond to a Kotlin property.
*
@@ -315,18 +329,26 @@
KmType kmPropertyType = null;
KmType kmReceiverType = null;
+ // A flag to indicate we can rename the property name. This will become false if any member
+ // is pinned. Then, we conservatively assume that users want the property to be pinned too.
+ // That is, we won't rename the property even though some other members could be renamed.
+ boolean canChangePropertyName = true;
+ // A candidate property name. Not overwritten by the following members, hence the order of
+ // preference: a backing field, getter, and setter.
+ String renamedPropertyName = name;
if (field != null) {
- DexField renamedField = lens.lookupField(field.field, appView.dexItemFactory());
- if (renamedField == null) {
- // Bail out if we can't find a renamed backing field.
- return null;
+ if (appView.appInfo().isPinned(field.field)) {
+ canChangePropertyName = false;
}
- kmProperty.setName(renamedField.name.toString());
+ DexField renamedField = lens.lookupField(field.field, appView.dexItemFactory());
+ if (canChangePropertyName && renamedField.name != field.field.name) {
+ renamedPropertyName = renamedField.name.toString();
+ }
kmPropertyType = toRenamedKmType(field.field.type, appView, lens);
if (kmPropertyType != null) {
kmProperty.setReturnType(kmPropertyType);
}
- JvmExtensionsKt.setFieldSignature(kmProperty, toJvmFieldSignature(field.field));
+ JvmExtensionsKt.setFieldSignature(kmProperty, toJvmFieldSignature(renamedField));
}
GetterSetterCriteria criteria = checkGetterCriteria();
@@ -360,8 +382,17 @@
return null;
}
}
+ if (appView.appInfo().isPinned(getter.method)) {
+ canChangePropertyName = false;
+ }
+ DexMethod renamedGetter = lens.lookupMethod(getter.method, appView.dexItemFactory());
+ if (canChangePropertyName
+ && renamedGetter.name != getter.method.name
+ && renamedPropertyName.equals(name)) {
+ renamedPropertyName = renamedGetter.name.toString();
+ }
kmProperty.setGetterFlags(getter.accessFlags.getAsKotlinFlags());
- JvmExtensionsKt.setGetterSignature(kmProperty, toJvmMethodSignature(getter.method));
+ JvmExtensionsKt.setGetterSignature(kmProperty, toJvmMethodSignature(renamedGetter));
}
criteria = checkSetterCriteria();
@@ -393,25 +424,40 @@
}
}
int valueIndex = isExtension ? 1 : 0;
+ DexType valueType = setter.method.proto.parameters.values[valueIndex];
if (kmPropertyType == null) {
// The property type is not set yet.
- kmPropertyType =
- toRenamedKmType(setter.method.proto.parameters.values[valueIndex], appView, lens);
+ kmPropertyType = toRenamedKmType(valueType, appView, lens);
if (kmPropertyType != null) {
kmProperty.setReturnType(kmPropertyType);
}
} else {
// If property type is set already (via either backing field or getter),
// make sure it's consistent.
- KmType kmPropertyTypeFromSetter =
- toRenamedKmType(setter.method.proto.parameters.values[valueIndex], appView, lens);
+ KmType kmPropertyTypeFromSetter = toRenamedKmType(valueType, appView, lens);
if (!getDescriptorFromKmType(kmPropertyType)
.equals(getDescriptorFromKmType(kmPropertyTypeFromSetter))) {
return null;
}
}
+ KotlinValueParameterInfo valueParameterInfo =
+ setter.getKotlinMemberInfo().getValueParameterInfo(valueIndex);
+ KmValueParameter kmValueParameter =
+ toRewrittenKmValueParameter(valueParameterInfo, valueType, "value", appView, lens);
+ if (kmValueParameter != null) {
+ kmProperty.setSetterParameter(kmValueParameter);
+ }
+ if (appView.appInfo().isPinned(setter.method)) {
+ canChangePropertyName = false;
+ }
+ DexMethod renamedSetter = lens.lookupMethod(setter.method, appView.dexItemFactory());
+ if (canChangePropertyName
+ && renamedSetter.name != setter.method.name
+ && renamedPropertyName.equals(name)) {
+ renamedPropertyName = renamedSetter.name.toString();
+ }
kmProperty.setSetterFlags(setter.accessFlags.getAsKotlinFlags());
- JvmExtensionsKt.setSetterSignature(kmProperty, toJvmMethodSignature(setter.method));
+ JvmExtensionsKt.setSetterSignature(kmProperty, toJvmMethodSignature(renamedSetter));
}
// If the property type remains null at the end, bail out to synthesize this property.
@@ -422,6 +468,11 @@
if (isExtension && kmReceiverType == null) {
return null;
}
+ // Rename the property name if and only if none of participating members is pinned, and
+ // any of them is indeed renamed (to a new name).
+ if (canChangePropertyName && !renamedPropertyName.equals(name)) {
+ kmProperty.setName(renamedPropertyName);
+ }
return kmProperty;
}
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.java
new file mode 100644
index 0000000..95d91f8
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinValueParameterInfo.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.kotlin;
+
+import kotlinx.metadata.KmValueParameter;
+
+// Provides access to Kotlin information about value parameter.
+class KotlinValueParameterInfo {
+ // TODO(b/70169921): When to use original param name v.s. when to *not* use?
+ // Original parameter name.
+ final String name;
+ // Original parameter flag, e.g., has default value.
+ final int flag;
+ // Indicates whether the formal parameter is originally `vararg`.
+ final boolean isVararg;
+
+ private KotlinValueParameterInfo(String name, int flag, boolean isVararg) {
+ this.name = name;
+ this.flag = flag;
+ this.isVararg = isVararg;
+ }
+
+ static KotlinValueParameterInfo fromKmValueParameter(KmValueParameter kmValueParameter) {
+ return new KotlinValueParameterInfo(
+ kmValueParameter.getName(),
+ kmValueParameter.getFlags(),
+ kmValueParameter.getVarargElementType() != null);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
index 45c59a8..e891f95 100644
--- a/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
+++ b/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
@@ -54,28 +54,28 @@
// ClassNameMinifier.
for (DexProgramClass clazz : classes) {
genericSignatureCollector.setCurrentClassContext(clazz);
- clazz.annotations =
+ clazz.setAnnotations(
rewriteGenericSignatures(
- clazz.annotations,
+ clazz.annotations(),
genericSignatureParser::parseClassSignature,
genericSignatureCollector::getRenamedSignature,
- (signature, e) -> parseError(clazz, clazz.getOrigin(), signature, e));
+ (signature, e) -> parseError(clazz, clazz.getOrigin(), signature, e)));
clazz.forEachField(
field ->
- field.annotations =
+ field.setAnnotations(
rewriteGenericSignatures(
- field.annotations,
+ field.annotations(),
genericSignatureParser::parseFieldSignature,
genericSignatureCollector::getRenamedSignature,
- (signature, e) -> parseError(field, clazz.getOrigin(), signature, e)));
+ (signature, e) -> parseError(field, clazz.getOrigin(), signature, e))));
clazz.forEachMethod(
method ->
- method.annotations =
+ method.setAnnotations(
rewriteGenericSignatures(
- method.annotations,
+ method.annotations(),
genericSignatureParser::parseMethodSignature,
genericSignatureCollector::getRenamedSignature,
- (signature, e) -> parseError(method, clazz.getOrigin(), signature, e)));
+ (signature, e) -> parseError(method, clazz.getOrigin(), signature, e))));
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/Retrace.java b/src/main/java/com/android/tools/r8/retrace/Retrace.java
index 057875d..0edcea8 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.utils.OptionsParsing.ParseContext;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -118,10 +119,14 @@
*/
public static void run(RetraceCommand command) {
try {
+ Timing timing = Timing.create("R8 retrace", command.printMemory());
+ timing.begin("Read proguard map");
ClassNameMapper classNameMapper =
ClassNameMapper.mapperFromString(command.proguardMapProducer.get());
+ timing.end();
RetraceBase retraceBase = RetraceBaseImpl.create(classNameMapper);
RetraceCommandLineResult result;
+ timing.begin("Parse and Retrace");
if (command.regularExpression != null) {
result =
new RetraceRegularExpression(
@@ -136,7 +141,13 @@
retraceBase, command.stackTrace, command.diagnosticsHandler, command.isVerbose)
.retrace();
}
+ timing.end();
+ timing.begin("Report result");
command.retracedStackTraceConsumer.accept(result.getNodes());
+ timing.end();
+ if (command.printTimes()) {
+ timing.report();
+ }
} catch (IOException ex) {
command.diagnosticsHandler.error(
new StringDiagnostic("Could not open mapping input stream: " + ex.getMessage()));
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java b/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
index 93addc4..64cf59a 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceCommand.java
@@ -40,6 +40,14 @@
assert this.retracedStackTraceConsumer != null;
}
+ public boolean printTimes() {
+ return System.getProperty("com.android.tools.r8.printtimes") != null;
+ }
+
+ public boolean printMemory() {
+ return System.getProperty("com.android.tools.r8.printmemory") != null;
+ }
+
/**
* Utility method for obtaining a RetraceCommand builder.
*
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationFixer.java b/src/main/java/com/android/tools/r8/shaking/AnnotationFixer.java
index 356f609..0fe561c 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationFixer.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationFixer.java
@@ -27,21 +27,21 @@
public void run(Iterable<DexProgramClass> classes) {
for (DexProgramClass clazz : classes) {
- clazz.annotations = clazz.annotations.rewrite(this::rewriteAnnotation);
+ clazz.setAnnotations(clazz.annotations().rewrite(this::rewriteAnnotation));
clazz.forEachMethod(this::processMethod);
clazz.forEachField(this::processField);
}
}
private void processMethod(DexEncodedMethod method) {
- method.annotations = method.annotations.rewrite(this::rewriteAnnotation);
+ method.setAnnotations(method.annotations().rewrite(this::rewriteAnnotation));
method.parameterAnnotationsList =
method.parameterAnnotationsList.rewrite(
dexAnnotationSet -> dexAnnotationSet.rewrite(this::rewriteAnnotation));
}
private void processField(DexEncodedField field) {
- field.annotations = field.annotations.rewrite(this::rewriteAnnotation);
+ field.setAnnotations(field.annotations().rewrite(this::rewriteAnnotation));
}
private DexAnnotation rewriteAnnotation(DexAnnotation original) {
diff --git a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
index fd3e7f5..6cfa6d8 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationElement;
-import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexEncodedAnnotation;
@@ -157,7 +156,7 @@
}
private static boolean hasSignatureAnnotation(DexProgramClass clazz, DexItemFactory itemFactory) {
- for (DexAnnotation annotation : clazz.annotations.annotations) {
+ for (DexAnnotation annotation : clazz.annotations().annotations) {
if (DexAnnotation.isSignatureAnnotation(annotation, itemFactory)) {
return true;
}
@@ -230,23 +229,23 @@
public void run() {
for (DexProgramClass clazz : appView.appInfo().classes()) {
stripAttributes(clazz);
- clazz.annotations =
- clazz.annotations.rewrite(annotation -> rewriteAnnotation(clazz, annotation));
+ clazz.setAnnotations(
+ clazz.annotations().rewrite(annotation -> rewriteAnnotation(clazz, annotation)));
clazz.forEachMethod(this::processMethod);
clazz.forEachField(this::processField);
}
}
private void processMethod(DexEncodedMethod method) {
- method.annotations =
- method.annotations.rewrite(annotation -> rewriteAnnotation(method, annotation));
+ method.setAnnotations(
+ method.annotations().rewrite(annotation -> rewriteAnnotation(method, annotation)));
method.parameterAnnotationsList =
method.parameterAnnotationsList.keepIf(this::filterParameterAnnotations);
}
private void processField(DexEncodedField field) {
- field.annotations =
- field.annotations.rewrite(annotation -> rewriteAnnotation(field, annotation));
+ field.setAnnotations(
+ field.annotations().rewrite(annotation -> rewriteAnnotation(field, annotation)));
}
private DexAnnotation rewriteAnnotation(DexDefinition holder, DexAnnotation original) {
@@ -359,13 +358,8 @@
public static void clearAnnotations(AppView<?> appView) {
for (DexProgramClass clazz : appView.appInfo().classes()) {
- clazz.annotations = DexAnnotationSet.empty();
- for (DexEncodedMethod method : clazz.methods()) {
- method.annotations = DexAnnotationSet.empty();
- }
- for (DexEncodedField field : clazz.fields()) {
- field.annotations = DexAnnotationSet.empty();
- }
+ clazz.clearAnnotations();
+ clazz.members().forEach(DexDefinition::clearAnnotations);
}
}
}
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 dcc6877..69ed3b0 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -26,6 +26,8 @@
import com.android.tools.r8.graph.FieldAccessInfoImpl;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.GraphLense.NestedGraphLense;
+import com.android.tools.r8.graph.ObjectAllocationInfoCollection;
+import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
import com.android.tools.r8.graph.PresortedComparable;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
@@ -62,20 +64,18 @@
/** Encapsulates liveness and reachability information for an application. */
public class AppInfoWithLiveness extends AppInfoWithSubtyping {
+ /** Set of types that are mentioned in the program, but for which no definition exists. */
+ private final Set<DexType> missingTypes;
/**
* Set of types that are mentioned in the program. We at least need an empty abstract classitem
* for these.
*/
private final Set<DexType> liveTypes;
- /** Set of annotation types that are instantiated. */
- private final Set<DexType> instantiatedAnnotationTypes;
/**
* Set of service types (from META-INF/services/) that may have been instantiated reflectively via
* ServiceLoader.load() or ServiceLoader.loadInstalled().
*/
public final Set<DexType> instantiatedAppServices;
- /** Set of types that are actually instantiated. These cannot be abstract. */
- final Set<DexType> instantiatedTypes;
/** Cache for {@link #isInstantiatedDirectlyOrIndirectly(DexProgramClass)}. */
private final IdentityHashMap<DexType, Boolean> indirectlyInstantiatedTypes =
new IdentityHashMap<>();
@@ -109,6 +109,8 @@
* each field. The latter is used, for example, during member rebinding.
*/
private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection;
+ /** Information about instantiated classes and their allocation sites. */
+ private final ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection;
/** Set of all methods referenced in virtual invokes, along with calling context. */
public final SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes;
/** Set of all methods referenced in interface invokes, along with calling context. */
@@ -190,10 +192,9 @@
// TODO(zerny): Clean up the constructors so we have just one.
AppInfoWithLiveness(
DirectMappedDexApplication application,
+ Set<DexType> missingTypes,
Set<DexType> liveTypes,
- Set<DexType> instantiatedAnnotationTypes,
Set<DexType> instantiatedAppServices,
- Set<DexType> instantiatedTypes,
SortedSet<DexMethod> targetedMethods,
Set<DexMethod> failedResolutionTargets,
SortedSet<DexMethod> bootstrapMethods,
@@ -201,6 +202,7 @@
SortedSet<DexMethod> virtualMethodsTargetedByInvokeDirect,
SortedSet<DexMethod> liveMethods,
FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
+ ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection,
SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes,
SortedMap<DexMethod, Set<DexEncodedMethod>> interfaceInvokes,
SortedMap<DexMethod, Set<DexEncodedMethod>> superInvokes,
@@ -230,10 +232,9 @@
Set<DexType> instantiatedLambdas,
Set<DexType> constClassReferences) {
super(application);
+ this.missingTypes = missingTypes;
this.liveTypes = liveTypes;
- this.instantiatedAnnotationTypes = instantiatedAnnotationTypes;
this.instantiatedAppServices = instantiatedAppServices;
- this.instantiatedTypes = instantiatedTypes;
this.targetedMethods = targetedMethods;
this.failedResolutionTargets = failedResolutionTargets;
this.bootstrapMethods = bootstrapMethods;
@@ -241,6 +242,7 @@
this.virtualMethodsTargetedByInvokeDirect = virtualMethodsTargetedByInvokeDirect;
this.liveMethods = liveMethods;
this.fieldAccessInfoCollection = fieldAccessInfoCollection;
+ this.objectAllocationInfoCollection = objectAllocationInfoCollection;
this.pinnedItems = pinnedItems;
this.mayHaveSideEffects = mayHaveSideEffects;
this.noSideEffects = noSideEffects;
@@ -273,10 +275,9 @@
public AppInfoWithLiveness(
AppInfoWithSubtyping appInfoWithSubtyping,
+ Set<DexType> missingTypes,
Set<DexType> liveTypes,
- Set<DexType> instantiatedAnnotationTypes,
Set<DexType> instantiatedAppServices,
- Set<DexType> instantiatedTypes,
SortedSet<DexMethod> targetedMethods,
Set<DexMethod> failedResolutionTargets,
SortedSet<DexMethod> bootstrapMethods,
@@ -284,6 +285,7 @@
SortedSet<DexMethod> virtualMethodsTargetedByInvokeDirect,
SortedSet<DexMethod> liveMethods,
FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
+ ObjectAllocationInfoCollectionImpl objectAllocationInfoCollection,
SortedMap<DexMethod, Set<DexEncodedMethod>> virtualInvokes,
SortedMap<DexMethod, Set<DexEncodedMethod>> interfaceInvokes,
SortedMap<DexMethod, Set<DexEncodedMethod>> superInvokes,
@@ -313,10 +315,9 @@
Set<DexType> instantiatedLambdas,
Set<DexType> constClassReferences) {
super(appInfoWithSubtyping);
+ this.missingTypes = missingTypes;
this.liveTypes = liveTypes;
- this.instantiatedAnnotationTypes = instantiatedAnnotationTypes;
this.instantiatedAppServices = instantiatedAppServices;
- this.instantiatedTypes = instantiatedTypes;
this.targetedMethods = targetedMethods;
this.failedResolutionTargets = failedResolutionTargets;
this.bootstrapMethods = bootstrapMethods;
@@ -324,6 +325,7 @@
this.virtualMethodsTargetedByInvokeDirect = virtualMethodsTargetedByInvokeDirect;
this.liveMethods = liveMethods;
this.fieldAccessInfoCollection = fieldAccessInfoCollection;
+ this.objectAllocationInfoCollection = objectAllocationInfoCollection;
this.pinnedItems = pinnedItems;
this.mayHaveSideEffects = mayHaveSideEffects;
this.noSideEffects = noSideEffects;
@@ -357,10 +359,9 @@
private AppInfoWithLiveness(AppInfoWithLiveness previous) {
this(
previous,
+ previous.missingTypes,
previous.liveTypes,
- previous.instantiatedAnnotationTypes,
previous.instantiatedAppServices,
- previous.instantiatedTypes,
previous.targetedMethods,
previous.failedResolutionTargets,
previous.bootstrapMethods,
@@ -368,6 +369,7 @@
previous.virtualMethodsTargetedByInvokeDirect,
previous.liveMethods,
previous.fieldAccessInfoCollection,
+ previous.objectAllocationInfoCollection,
previous.virtualInvokes,
previous.interfaceInvokes,
previous.superInvokes,
@@ -406,10 +408,9 @@
Collection<DexReference> additionalPinnedItems) {
this(
application,
+ previous.missingTypes,
previous.liveTypes,
- previous.instantiatedAnnotationTypes,
previous.instantiatedAppServices,
- previous.instantiatedTypes,
previous.targetedMethods,
previous.failedResolutionTargets,
previous.bootstrapMethods,
@@ -417,6 +418,7 @@
previous.virtualMethodsTargetedByInvokeDirect,
previous.liveMethods,
previous.fieldAccessInfoCollection,
+ previous.objectAllocationInfoCollection,
previous.virtualInvokes,
previous.interfaceInvokes,
previous.superInvokes,
@@ -458,10 +460,9 @@
Map<DexField, Int2ReferenceMap<DexField>> switchMaps,
Map<DexType, Map<DexField, EnumValueInfo>> enumValueInfoMaps) {
super(previous);
+ this.missingTypes = previous.missingTypes;
this.liveTypes = previous.liveTypes;
- this.instantiatedAnnotationTypes = previous.instantiatedAnnotationTypes;
this.instantiatedAppServices = previous.instantiatedAppServices;
- this.instantiatedTypes = previous.instantiatedTypes;
this.instantiatedLambdas = previous.instantiatedLambdas;
this.targetedMethods = previous.targetedMethods;
this.failedResolutionTargets = previous.failedResolutionTargets;
@@ -470,6 +471,7 @@
this.virtualMethodsTargetedByInvokeDirect = previous.virtualMethodsTargetedByInvokeDirect;
this.liveMethods = previous.liveMethods;
this.fieldAccessInfoCollection = previous.fieldAccessInfoCollection;
+ this.objectAllocationInfoCollection = previous.objectAllocationInfoCollection;
this.pinnedItems = previous.pinnedItems;
this.mayHaveSideEffects = previous.mayHaveSideEffects;
this.noSideEffects = previous.noSideEffects;
@@ -500,6 +502,30 @@
previous.markObsolete();
}
+ private boolean dontAssertDefinitionFor = true;
+
+ @Override
+ public void enableDefinitionForAssert() {
+ dontAssertDefinitionFor = false;
+ }
+
+ @Override
+ public void disableDefinitionForAssert() {
+ dontAssertDefinitionFor = true;
+ }
+
+ @Override
+ public DexClass definitionFor(DexType type) {
+ DexClass definition = super.definitionFor(type);
+ assert dontAssertDefinitionFor
+ || definition != null
+ || missingTypes.contains(type)
+ // TODO(b/149363884): Remove this exception once fixed.
+ || type.toDescriptorString().endsWith("$Builder;")
+ : "Failed lookup of non-missing type: " + type;
+ return definition;
+ }
+
public boolean isLiveProgramClass(DexProgramClass clazz) {
return liveTypes.contains(clazz.type);
}
@@ -689,6 +715,11 @@
return fieldAccessInfoCollection;
}
+ /** This method provides immutable access to `objectAllocationInfoCollection`. */
+ public ObjectAllocationInfoCollection getObjectAllocationInfoCollection() {
+ return objectAllocationInfoCollection;
+ }
+
private boolean assertNoItemRemoved(Collection<DexReference> items, Collection<DexType> types) {
Set<DexType> typeSet = ImmutableSet.copyOf(types);
for (DexReference item : items) {
@@ -710,8 +741,8 @@
assert checkIfObsolete();
DexType type = clazz.type;
return type.isD8R8SynthesizedClassType()
- || instantiatedTypes.contains(type)
- || instantiatedAnnotationTypes.contains(type);
+ || objectAllocationInfoCollection.isInstantiatedDirectly(clazz)
+ || (clazz.isAnnotation() && liveTypes.contains(type));
}
public boolean isInstantiatedIndirectly(DexProgramClass clazz) {
@@ -966,10 +997,9 @@
return new AppInfoWithLiveness(
application,
+ missingTypes,
rewriteItems(liveTypes, lens::lookupType),
- rewriteItems(instantiatedAnnotationTypes, lens::lookupType),
rewriteItems(instantiatedAppServices, lens::lookupType),
- rewriteItems(instantiatedTypes, lens::lookupType),
lens.rewriteMethodsConservatively(targetedMethods),
lens.rewriteMethodsConservatively(failedResolutionTargets),
lens.rewriteMethodsConservatively(bootstrapMethods),
@@ -977,6 +1007,7 @@
lens.rewriteMethodsConservatively(virtualMethodsTargetedByInvokeDirect),
lens.rewriteMethodsConservatively(liveMethods),
fieldAccessInfoCollection.rewrittenWithLens(application, lens),
+ objectAllocationInfoCollection.rewrittenWithLens(application, lens),
rewriteKeysConservativelyWhileMergingValues(
virtualInvokes, lens::lookupMethodInAllContexts),
rewriteKeysConservativelyWhileMergingValues(
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 ba1bdb5..d0e971e 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;
+import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.graph.FieldAccessInfoImpl.MISSING_FIELD_ACCESS_INFO;
import static com.android.tools.r8.naming.IdentifierNameStringUtils.identifyIdentifier;
import static com.android.tools.r8.naming.IdentifierNameStringUtils.isReflectionMethod;
@@ -28,11 +29,13 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.Descriptor;
import com.android.tools.r8.graph.DexAnnotation;
+import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItem;
@@ -46,9 +49,12 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.DirectMappedDexApplication.Builder;
import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
import com.android.tools.r8.graph.FieldAccessInfoImpl;
-import com.android.tools.r8.graph.KeyedDexItem;
+import com.android.tools.r8.graph.InnerClassAttribute;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ObjectAllocationInfoCollectionImpl;
import com.android.tools.r8.graph.PresortedComparable;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
@@ -172,6 +178,7 @@
private final Map<DexMethod, Set<DexEncodedMethod>> staticInvokes = new IdentityHashMap<>();
private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection =
new FieldAccessInfoCollectionImpl();
+ private final ObjectAllocationInfoCollectionImpl.Builder objectAllocationInfoCollection;
private final Set<DexCallSite> callSites = Sets.newIdentityHashSet();
private final Set<DexReference> identifierNameStrings = Sets.newIdentityHashSet();
@@ -203,19 +210,20 @@
/** Set of types whose class initializer may execute. */
private final SetWithReportedReason<DexProgramClass> initializedTypes;
- /** Set of live types defined in the library and classpath. Used to avoid duplicate tracing. */
+ /**
+ * Set of live types defined in the library and classpath.
+ *
+ * <p>Used to build a new app of just referenced types and avoid duplicate tracing.
+ */
private final Set<DexClass> liveNonProgramTypes = Sets.newIdentityHashSet();
+ /** Set of missing types. */
+ private final Set<DexType> missingTypes = Sets.newIdentityHashSet();
+
/** Mapping from each unused interface to the set of live types that implements the interface. */
private final Map<DexProgramClass, Set<DexProgramClass>> unusedInterfaceTypes =
new IdentityHashMap<>();
- /** Set of annotation types that are instantiated. */
- private final SetWithReason<DexAnnotation> liveAnnotations;
-
- /** Set of types that are actually instantiated. These cannot be abstract. */
- private final SetWithReason<DexProgramClass> instantiatedTypes;
-
/** Set of all types that are instantiated, directly or indirectly, thus may be abstract. */
private final Set<DexProgramClass> directAndIndirectlyInstantiatedTypes =
Sets.newIdentityHashSet();
@@ -299,8 +307,8 @@
private final Set<DexType> constClassReferences = Sets.newIdentityHashSet();
/**
- * A map from classes to annotations that need to be processed should the classes ever become
- * live.
+ * A map from annotation classes to annotations that need to be processed should the classes ever
+ * become live.
*/
private final Map<DexType, Set<DexAnnotation>> deferredAnnotations = new IdentityHashMap<>();
@@ -345,9 +353,7 @@
}
liveTypes = new SetWithReportedReason<>();
- liveAnnotations = new SetWithReason<>(graphReporter::registerAnnotation);
initializedTypes = new SetWithReportedReason<>();
- instantiatedTypes = new SetWithReason<>(graphReporter::registerClass);
targetedMethods = new SetWithReason<>(graphReporter::registerMethod);
// This set is only populated in edge cases due to multiple default interface methods.
// The set is generally expected to be empty and in the unlikely chance it is not, it will
@@ -359,6 +365,10 @@
instantiatedInterfaceTypes = Sets.newIdentityHashSet();
lambdaRewriter = options.desugarState == DesugarState.ON ? new LambdaRewriter(appView) : null;
+ // TODO(b/147799448): Enable allocation site tracking during the initial round of tree shaking.
+ objectAllocationInfoCollection =
+ ObjectAllocationInfoCollectionImpl.builder(false, graphReporter);
+
if (appView.rewritePrefix.isRewriting() && mode.isInitialTreeShaking()) {
desugaredLibraryWrapperAnalysis = new DesugaredLibraryConversionWrapperAnalysis(appView);
registerAnalysis(desugaredLibraryWrapperAnalysis);
@@ -409,11 +419,14 @@
return clazz.asProgramClass();
}
if (liveNonProgramTypes.add(clazz) && clazz.isLibraryClass()) {
+ // TODO(b/149201735): This likely needs to apply to classpath too.
ensureMethodsContinueToWidenAccess(clazz);
+ // TODO(b/149201158): This should apply to classpath too (likely even hard fail).
warnIfLibraryTypeInheritsFromProgramType(clazz.asLibraryClass());
}
+ } else {
+ reportMissingClass(type);
}
- reportMissingClass(type);
return null;
}
@@ -453,10 +466,12 @@
if (item.isDexClass()) {
DexProgramClass clazz = item.asDexClass().asProgramClass();
KeepReasonWitness witness = graphReporter.reportKeepClass(precondition, rules, clazz);
- if (clazz.isInterface() && !clazz.accessFlags.isAnnotation()) {
- markInterfaceAsInstantiated(clazz, witness);
+ if (clazz.isAnnotation()) {
+ workList.enqueueMarkAnnotationInstantiatedAction(clazz, witness);
+ } else if (clazz.isInterface()) {
+ workList.enqueueMarkInterfaceInstantiatedAction(clazz, witness);
} else {
- workList.enqueueMarkInstantiatedAction(clazz, null, witness);
+ workList.enqueueMarkInstantiatedAction(clazz, null, InstantiationReason.KEEP_RULE, witness);
if (clazz.hasDefaultInitializer()) {
DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
if (forceProguardCompatibility) {
@@ -494,9 +509,9 @@
pinnedItems.add(item.toReference());
}
- private void markInterfaceAsInstantiated(DexProgramClass clazz, KeepReasonWitness witness) {
- assert clazz.isInterface() && !clazz.accessFlags.isAnnotation();
-
+ void markInterfaceAsInstantiated(DexProgramClass clazz, KeepReasonWitness witness) {
+ assert !clazz.isAnnotation();
+ assert clazz.isInterface();
unknownInstantiatedInterfaceTypes.add(clazz, witness);
if (!instantiatedInterfaceTypes.add(clazz)) {
return;
@@ -582,7 +597,7 @@
DexField field, DexEncodedMethod context, boolean isRead, boolean isReflective) {
FieldAccessInfoImpl info = fieldAccessInfoCollection.get(field);
if (info == null) {
- DexEncodedField encodedField = appInfo.resolveField(field);
+ DexEncodedField encodedField = resolveField(field);
// If the field does not exist, then record this in the mapping, such that we don't have to
// resolve the field the next time.
@@ -761,10 +776,13 @@
DexProgramClass clazz = getProgramClassOrNull(type);
if (clazz != null) {
KeepReason reason = KeepReason.methodHandleReferencedIn(currentMethod);
- if (clazz.isInterface() && !clazz.accessFlags.isAnnotation()) {
+ if (clazz.isAnnotation()) {
+ markTypeAsLive(clazz, graphReporter.registerClass(clazz, reason));
+ } else if (clazz.isInterface()) {
markInterfaceAsInstantiated(clazz, graphReporter.registerInterface(clazz, reason));
} else {
- markInstantiated(clazz, null, reason);
+ workList.enqueueMarkInstantiatedAction(
+ clazz, null, InstantiationReason.REFERENCED_IN_METHOD_HANDLE, reason);
}
}
}
@@ -951,21 +969,34 @@
return false;
}
- return traceNewInstance(type, context, KeepReason.instantiatedIn(currentMethod));
+ return traceNewInstance(
+ type,
+ context,
+ InstantiationReason.NEW_INSTANCE_INSTRUCTION,
+ KeepReason.instantiatedIn(currentMethod));
}
boolean traceNewInstanceFromLambda(DexType type, ProgramMethod context) {
- return traceNewInstance(type, context, KeepReason.invokedFromLambdaCreatedIn(context.method));
+ return traceNewInstance(
+ type,
+ context,
+ InstantiationReason.LAMBDA,
+ KeepReason.invokedFromLambdaCreatedIn(context.method));
}
- private boolean traceNewInstance(DexType type, ProgramMethod context, KeepReason keepReason) {
+ private boolean traceNewInstance(
+ DexType type,
+ ProgramMethod context,
+ InstantiationReason instantiationReason,
+ KeepReason keepReason) {
DexEncodedMethod currentMethod = context.method;
DexProgramClass clazz = getProgramClassOrNull(type);
if (clazz != null) {
- if (clazz.isInterface()) {
+ if (clazz.isAnnotation() || clazz.isInterface()) {
markTypeAsLive(clazz, graphReporter.registerClass(clazz, keepReason));
} else {
- markInstantiated(clazz, currentMethod, keepReason);
+ workList.enqueueMarkInstantiatedAction(
+ clazz, currentMethod, instantiationReason, keepReason);
}
}
return true;
@@ -979,9 +1010,8 @@
// Must mark the field as targeted even if it does not exist.
markFieldAsTargeted(field, currentMethod);
- DexEncodedField encodedField = appInfo.resolveField(field);
+ DexEncodedField encodedField = resolveField(field);
if (encodedField == null) {
- reportMissingField(field);
return false;
}
@@ -1016,9 +1046,8 @@
// Must mark the field as targeted even if it does not exist.
markFieldAsTargeted(field, currentMethod);
- DexEncodedField encodedField = appInfo.resolveField(field);
+ DexEncodedField encodedField = resolveField(field);
if (encodedField == null) {
- reportMissingField(field);
return false;
}
@@ -1050,11 +1079,10 @@
return false;
}
- DexEncodedField encodedField = appInfo.resolveField(field);
+ DexEncodedField encodedField = resolveField(field);
if (encodedField == null) {
// Must mark the field as targeted even if it does not exist.
markFieldAsTargeted(field, currentMethod);
- reportMissingField(field);
return false;
}
@@ -1095,11 +1123,10 @@
return false;
}
- DexEncodedField encodedField = appInfo.resolveField(field);
+ DexEncodedField encodedField = resolveField(field);
if (encodedField == null) {
// Must mark the field as targeted even if it does not exist.
markFieldAsTargeted(field, currentMethod);
- reportMissingField(field);
return false;
}
@@ -1214,7 +1241,7 @@
reason.apply(holder));
}
- private void markTypeAsLive(DexProgramClass clazz, KeepReasonWitness witness) {
+ void markTypeAsLive(DexProgramClass clazz, KeepReasonWitness witness) {
markTypeAsLive(
clazz,
scopedMethodsForLiveTypes.computeIfAbsent(clazz.type, ignore -> new ScopedDexMethodSet()),
@@ -1227,6 +1254,13 @@
return;
}
+ // Mark types in inner-class attributes referenced.
+ InnerClassAttribute innerClassAttributes = holder.getInnerClassAttributeForThisClass();
+ if (innerClassAttributes != null) {
+ recordTypeReference(innerClassAttributes.getInner());
+ recordTypeReference(innerClassAttributes.getOuter());
+ }
+
if (Log.ENABLED) {
Log.verbose(getClass(), "Type `%s` has become live.", holder.type);
}
@@ -1270,15 +1304,15 @@
enqueueFirstNonSerializableClassInitializer(holder, reason);
}
- if (!holder.annotations.isEmpty()) {
- processAnnotations(holder, holder.annotations.annotations);
- }
+ processAnnotations(holder, holder);
+
// If this type has deferred annotations, we have to process those now, too.
- Set<DexAnnotation> annotations = deferredAnnotations.remove(holder.type);
- if (annotations != null && !annotations.isEmpty()) {
- assert holder.accessFlags.isAnnotation();
- assert annotations.stream().allMatch(a -> a.annotation.type == holder.type);
- annotations.forEach(annotation -> handleAnnotation(holder, annotation));
+ if (holder.isAnnotation()) {
+ Set<DexAnnotation> annotations = deferredAnnotations.remove(holder.type);
+ if (annotations != null && !annotations.isEmpty()) {
+ assert annotations.stream().allMatch(a -> a.annotation.type == holder.type);
+ annotations.forEach(annotation -> processAnnotation(holder, holder, annotation));
+ }
}
rootSet.forEachDependentStaticMember(holder, appView, this::enqueueDependentItem);
@@ -1335,37 +1369,68 @@
internalEnqueueRootItem(consequent, reasons, precondition);
}
- private void processAnnotations(DexDefinition holder, DexAnnotation[] annotations) {
+ private void processAnnotations(DexProgramClass holder, DexDefinition annotatedItem) {
+ processAnnotations(holder, annotatedItem, annotatedItem.annotations());
+ }
+
+ private void processAnnotations(
+ DexProgramClass holder, DexDefinition annotatedItem, DexAnnotationSet annotations) {
+ processAnnotations(holder, annotatedItem, annotations.annotations);
+ }
+
+ private void processAnnotations(
+ DexProgramClass holder, DexDefinition annotatedItem, DexAnnotation[] annotations) {
for (DexAnnotation annotation : annotations) {
- processAnnotation(holder, annotation);
+ processAnnotation(holder, annotatedItem, annotation);
}
}
- private void processAnnotation(DexDefinition holder, DexAnnotation annotation) {
- handleAnnotation(holder, annotation);
- }
-
- private void handleAnnotation(DexDefinition holder, DexAnnotation annotation) {
+ private void processAnnotation(
+ DexProgramClass holder, DexDefinition annotatedItem, DexAnnotation annotation) {
+ assert annotatedItem == holder
+ || (annotatedItem.isDexEncodedField()
+ && annotatedItem.asDexEncodedField().field.holder == holder.type)
+ || (annotatedItem.isDexEncodedMethod()
+ && annotatedItem.asDexEncodedMethod().method.holder == holder.type);
assert !holder.isDexClass() || holder.asDexClass().isProgramClass();
DexType type = annotation.annotation.type;
+ recordTypeReference(type);
DexClass clazz = appView.definitionFor(type);
boolean annotationTypeIsLibraryClass = clazz == null || clazz.isNotProgramClass();
boolean isLive = annotationTypeIsLibraryClass || liveTypes.contains(clazz.asProgramClass());
- if (!shouldKeepAnnotation(holder, annotation, isLive, appView)) {
+ if (!shouldKeepAnnotation(annotatedItem, annotation, isLive, appView)) {
// Remember this annotation for later.
if (!annotationTypeIsLibraryClass) {
deferredAnnotations.computeIfAbsent(type, ignore -> new HashSet<>()).add(annotation);
}
return;
}
- KeepReason reason = KeepReason.annotatedOn(holder);
- liveAnnotations.add(annotation, reason);
+ KeepReason reason = KeepReason.annotatedOn(annotatedItem);
+ graphReporter.registerAnnotation(annotation, reason);
AnnotationReferenceMarker referenceMarker =
new AnnotationReferenceMarker(annotation.annotation.type, appView.dexItemFactory(), reason);
annotation.annotation.collectIndexedItems(referenceMarker);
}
+ private DexEncodedField resolveField(DexField field) {
+ // Record the references in case they are not program types.
+ recordTypeReference(field.holder);
+ recordTypeReference(field.type);
+ DexEncodedField encodedField = appInfo.resolveField(field);
+ if (encodedField == null) {
+ reportMissingField(field);
+ return null;
+ }
+ return encodedField;
+ }
+
private ResolutionResult resolveMethod(DexMethod method, KeepReason reason) {
+ // Record the references in case they are not program types.
+ recordTypeReference(method.holder);
+ recordTypeReference(method.proto.returnType);
+ for (DexType param : method.proto.parameters.values) {
+ recordTypeReference(param);
+ }
ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
if (resolutionResult.isFailedResolution()) {
reportMissingMethod(method);
@@ -1436,6 +1501,10 @@
DexType holder = method.holder;
DexProgramClass clazz = getProgramClassOrNull(holder);
if (clazz == null) {
+ recordTypeReference(method.proto.returnType);
+ for (DexType param : method.proto.parameters.values) {
+ recordTypeReference(param);
+ }
return;
}
// TODO(zerny): Is it ok that we lookup in both the direct and virtual pool here?
@@ -1496,7 +1565,8 @@
}
private void reportMissingClass(DexType clazz) {
- if (Log.ENABLED && reportedMissing.add(clazz)) {
+ boolean newReport = missingTypes.add(clazz);
+ if (Log.ENABLED && newReport) {
Log.verbose(Enqueuer.class, "Class `%s` is missing.", clazz);
}
}
@@ -1521,9 +1591,9 @@
return;
}
markReferencedTypesAsLive(method);
- processAnnotations(method, method.annotations.annotations);
+ processAnnotations(clazz, method);
method.parameterAnnotationsList.forEachAnnotation(
- annotation -> processAnnotation(method, annotation));
+ annotation -> processAnnotation(clazz, method, annotation));
if (Log.ENABLED) {
Log.verbose(getClass(), "Method `%s` is targeted.", method.method);
@@ -1543,15 +1613,21 @@
*/
// Package protected due to entry point from worklist.
void processNewlyInstantiatedClass(
- DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
- assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
+ DexProgramClass clazz,
+ DexEncodedMethod context,
+ InstantiationReason instantiationReason,
+ KeepReason keepReason) {
+ assert !clazz.isAnnotation();
+ assert !clazz.isInterface();
+
// Notify analyses. This is done even if `clazz` has already been marked as instantiated,
// because each analysis may depend on seeing all the (clazz, reason) pairs. Thus, not doing so
// could lead to nondeterminism.
analyses.forEach(
analysis -> analysis.processNewlyInstantiatedClass(clazz.asProgramClass(), context));
- if (!instantiatedTypes.add(clazz, reason)) {
+ if (!objectAllocationInfoCollection.recordDirectAllocationSite(
+ clazz, context, instantiationReason, keepReason)) {
return;
}
@@ -1561,7 +1637,7 @@
Log.verbose(getClass(), "Class `%s` is instantiated, processing...", clazz);
}
// This class becomes live, so it and all its supertypes become live types.
- markTypeAsLive(clazz, graphReporter.registerClass(clazz, reason));
+ markTypeAsLive(clazz, graphReporter.registerClass(clazz, keepReason));
// Instantiation triggers class initialization.
markDirectAndIndirectClassInitializersAsLive(clazz);
// For all methods of the class, if we have seen a call, mark the method live.
@@ -1617,7 +1693,7 @@
transitionReachableVirtualMethods(current, seen);
Collections.addAll(interfaces, current.interfaces.values);
current = getProgramClassOrNull(current.superType);
- } while (current != null && !instantiatedTypes.contains(current));
+ } while (current != null && !objectAllocationInfoCollection.isInstantiatedDirectly(current));
// The set now contains all virtual methods on the type and its supertype that are reachable.
// In a second step, we now look at interfaces. We have to do this in this order due to JVM
@@ -1673,7 +1749,7 @@
private void markLibraryAndClasspathMethodOverridesAsLive(
DexClass libraryClass, DexProgramClass instantiatedClass) {
assert libraryClass.isNotProgramClass();
- assert !instantiatedClass.isInterface() || instantiatedClass.accessFlags.isAnnotation();
+ assert !instantiatedClass.isInterface() || instantiatedClass.isAnnotation();
for (DexEncodedMethod method : libraryClass.virtualMethods()) {
// Note: it may be worthwhile to add a resolution cache here. If so, it must still ensure
// that all library override edges are reported to the kept-graph consumer.
@@ -1775,24 +1851,26 @@
if (reachableFields != null) {
for (DexEncodedField field : reachableFields.getItems()) {
// TODO(b/120959039): Should the reason this field is reachable come from the set?
- markInstanceFieldAsLive(field, KeepReason.reachableFromLiveType(clazz.type));
+ markInstanceFieldAsLive(clazz, field, KeepReason.reachableFromLiveType(clazz.type));
}
}
clazz = getProgramClassOrNull(clazz.superType);
- } while (clazz != null && !instantiatedTypes.contains(clazz));
+ } while (clazz != null && !objectAllocationInfoCollection.isInstantiatedDirectly(clazz));
}
- private void transitionDependentItemsForInstantiatedClass(DexClass clazz) {
- DexClass current = clazz;
+ private void transitionDependentItemsForInstantiatedClass(DexProgramClass clazz) {
+ assert !clazz.isAnnotation();
+ assert !clazz.isInterface();
do {
// Handle keep rules that are dependent on the class being instantiated.
- rootSet.forEachDependentNonStaticMember(current, appView, this::enqueueDependentItem);
+ rootSet.forEachDependentNonStaticMember(clazz, appView, this::enqueueDependentItem);
// Visit the super type.
- current = current.superType != null ? appView.definitionFor(current.superType) : null;
- } while (current != null
- && current.isProgramClass()
- && !instantiatedTypes.contains(current.asProgramClass()));
+ clazz =
+ clazz.superType != null
+ ? asProgramClassOrNull(appView.definitionFor(clazz.superType))
+ : null;
+ } while (clazz != null && !objectAllocationInfoCollection.isInstantiatedDirectly(clazz));
}
private void transitionUnusedInterfaceToLive(DexProgramClass clazz) {
@@ -1841,7 +1919,7 @@
encodedField.field);
}
}
- processAnnotations(encodedField, encodedField.annotations.annotations);
+ processAnnotations(clazz, encodedField);
liveFields.add(encodedField, reason);
// Add all dependent members to the workqueue.
@@ -1851,7 +1929,8 @@
analyses.forEach(analysis -> analysis.processNewlyLiveField(encodedField));
}
- private void markInstanceFieldAsLive(DexEncodedField field, KeepReason reason) {
+ private void markInstanceFieldAsLive(
+ DexProgramClass holder, DexEncodedField field, KeepReason reason) {
assert field != null;
assert field.isProgramField(appView);
markTypeAsLive(field.field.holder, reason);
@@ -1859,7 +1938,7 @@
if (Log.ENABLED) {
Log.verbose(getClass(), "Adding instance field `%s` to live set.", field.field);
}
- processAnnotations(field, field.annotations.annotations);
+ processAnnotations(holder, field);
liveFields.add(field, reason);
// Add all dependent members to the workqueue.
@@ -1869,14 +1948,6 @@
analyses.forEach(analysis -> analysis.processNewlyLiveField(field));
}
- private void markInstantiated(
- DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
- if (Log.ENABLED) {
- Log.verbose(getClass(), "Register new instantiation of `%s`.", clazz);
- }
- workList.enqueueMarkInstantiatedAction(clazz, context, reason);
- }
-
private void markLambdaInstantiated(DexType itf, DexEncodedMethod method) {
DexClass clazz = appView.definitionFor(itf);
if (clazz == null) {
@@ -1998,7 +2069,7 @@
markStaticFieldAsLive(encodedField, reason);
} else {
if (isInstantiatedOrHasInstantiatedSubtype(clazz)) {
- markInstanceFieldAsLive(encodedField, reason);
+ markInstanceFieldAsLive(clazz, encodedField, reason);
} else {
// Add the field to the reachable set if the type later becomes instantiated.
reachableInstanceFields
@@ -2008,6 +2079,19 @@
}
}
+ private void recordTypeReference(DexType type) {
+ if (type == null) {
+ return;
+ }
+ if (type.isArrayType()) {
+ type = type.toBaseType(appView.dexItemFactory());
+ }
+ if (!type.isClassType()) {
+ return;
+ }
+ getProgramClassOrNull(type);
+ }
+
private void markVirtualMethodAsReachable(
DexMethod method, boolean interfaceInvoke, ProgramMethod contextOrNull, KeepReason reason) {
if (method.holder.isArrayType()) {
@@ -2024,6 +2108,12 @@
// TODO(b/70160030): Revise this to support tree shaking library methods on non-escaping types.
DexProgramClass holder = getProgramClassOrNull(method.holder);
if (holder == null) {
+ // TODO(b/139464956): clean this.
+ // Ensure that the full proto of the targeted method is referenced.
+ recordTypeReference(method.proto.returnType);
+ for (DexType type : method.proto.parameters.values) {
+ recordTypeReference(type);
+ }
return;
}
@@ -2065,14 +2155,15 @@
assert resolution.holder.isProgramClass();
assert interfaceInvoke == holder.isInterface();
- Set<DexEncodedMethod> possibleTargets =
+ LookupResult lookupResult =
// TODO(b/140214802): Call on the resolution once proper resolution and lookup is resolved.
new SingleResolutionResult(holder, resolution.holder, resolution.method)
- .lookupVirtualDispatchTargets(appInfo);
- if (possibleTargets == null || possibleTargets.isEmpty()) {
+ .lookupVirtualDispatchTargets(appView, appInfo);
+ if (!lookupResult.isLookupResultSuccess()) {
return;
}
- for (DexEncodedMethod encodedPossibleTarget : possibleTargets) {
+ for (DexEncodedMethod encodedPossibleTarget :
+ lookupResult.asLookupResultSuccess().getMethodTargets()) {
if (encodedPossibleTarget.isAbstract()) {
continue;
}
@@ -2104,7 +2195,8 @@
return;
}
- if (instantiatedTypes.contains(clazz) || instantiatedInterfaceTypes.contains(clazz)) {
+ if (objectAllocationInfoCollection.isInstantiatedDirectly(clazz)
+ || instantiatedInterfaceTypes.contains(clazz)) {
markVirtualMethodAsLive(
clazz,
encodedPossibleTarget,
@@ -2120,7 +2212,7 @@
if (currentClass == null || currentClass.lookupVirtualMethod(possibleTarget) != null) {
continue;
}
- if (instantiatedTypes.contains(currentClass)
+ if (objectAllocationInfoCollection.isInstantiatedDirectly(currentClass)
|| instantiatedInterfaceTypes.contains(currentClass)) {
markVirtualMethodAsLive(
clazz,
@@ -2313,10 +2405,6 @@
}
private AppInfoWithLiveness createAppInfo(AppInfoWithSubtyping appInfo) {
- ImmutableSortedSet.Builder<DexType> builder =
- ImmutableSortedSet.orderedBy(PresortedComparable::slowCompareTo);
- liveAnnotations.items.forEach(annotation -> builder.add(annotation.annotation.type));
-
// Remove the temporary mappings that have been inserted into the field access info collection
// and verify that the mapping is then one-to-one.
fieldAccessInfoCollection.removeIf(
@@ -2330,9 +2418,39 @@
liveMethods.add(bridge.holder, bridge.method, graphReporter.fakeReportShouldNotBeUsed());
}
- // A direct appInfo is required to add classpath classes in wrapper post processing.
- assert appInfo.app().isDirect() : "Expected a direct appInfo after enqueuing.";
- DirectMappedDexApplication.Builder appBuilder = appInfo.app().asDirect().builder();
+ // Ensure references from various root set collections.
+ rootSet
+ .noSideEffects
+ .keySet()
+ .forEach(
+ r -> {
+ if (r.isDexType()) {
+ recordTypeReference(r.asDexType());
+ } else if (r.isDexField()) {
+ recordTypeReference(r.asDexField().holder);
+ recordTypeReference(r.asDexField().type);
+ } else {
+ assert r.isDexMethod();
+ recordTypeReference(r.asDexMethod().holder);
+ recordTypeReference(r.asDexMethod().proto.returnType);
+ for (DexType param : r.asDexMethod().proto.parameters.values) {
+ recordTypeReference(param);
+ }
+ }
+ });
+
+ // Rebuild a new app only containing referenced types.
+ appView.dexItemFactory().forEachPossiblyCompilerSynthesizedType(this::recordTypeReference);
+ Set<DexLibraryClass> libraryClasses = Sets.newIdentityHashSet();
+ Set<DexClasspathClass> classpathClasses = Sets.newIdentityHashSet();
+ for (DexClass clazz : liveNonProgramTypes) {
+ traverseHierarchy(clazz, libraryClasses, classpathClasses);
+ }
+ Builder appBuilder = appInfo.app().asDirect().builder();
+ appBuilder.replaceLibraryClasses(libraryClasses);
+ appBuilder.replaceClasspathClasses(classpathClasses);
+ // Can't replace the program classes at this point as they are needed in tree pruning.
+ // Post process the app to add synthetic content.
postProcessLambdaDesugaring(appBuilder);
postProcessLibraryConversionWrappers(appBuilder);
DirectMappedDexApplication app = appBuilder.build();
@@ -2340,11 +2458,9 @@
AppInfoWithLiveness appInfoWithLiveness =
new AppInfoWithLiveness(
app,
+ missingTypes,
SetUtils.mapIdentityHashSet(liveTypes.getItems(), DexProgramClass::getType),
- SetUtils.mapIdentityHashSet(
- liveAnnotations.getItems(), DexAnnotation::getAnnotationType),
Collections.unmodifiableSet(instantiatedAppServices),
- SetUtils.mapIdentityHashSet(instantiatedTypes.getItems(), DexProgramClass::getType),
Enqueuer.toSortedDescriptorSet(targetedMethods.getItems()),
Collections.unmodifiableSet(failedResolutionTargets),
ImmutableSortedSet.copyOf(DexMethod::slowCompareTo, bootstrapMethods),
@@ -2354,6 +2470,7 @@
toSortedDescriptorSet(liveMethods.getItems()),
// Filter out library fields and pinned fields, because these are read by default.
fieldAccessInfoCollection,
+ objectAllocationInfoCollection.build(),
// TODO(b/132593519): Do we require these sets to be sorted for determinism?
toImmutableSortedMap(virtualInvokes, PresortedComparable::slowCompare),
toImmutableSortedMap(interfaceInvokes, PresortedComparable::slowCompare),
@@ -2388,6 +2505,46 @@
return appInfoWithLiveness;
}
+ private void traverseHierarchy(
+ DexClass clazz,
+ Set<DexLibraryClass> libraryClasses,
+ Set<DexClasspathClass> classpathClasses) {
+ if (clazz.isLibraryClass()) {
+ libraryClasses.add(clazz.asLibraryClass());
+ } else if (clazz.isClasspathClass()) {
+ classpathClasses.add(clazz.asClasspathClass());
+ }
+ Deque<DexType> worklist = new ArrayDeque<>();
+ if (clazz.superType != null) {
+ worklist.add(clazz.superType);
+ }
+ Collections.addAll(worklist, clazz.interfaces.values);
+ while (!worklist.isEmpty()) {
+ DexType type = worklist.pop();
+ DexClass definition = appView.definitionFor(type);
+ if (definition == null) {
+ continue;
+ }
+ if (definition.isProgramClass()) {
+ // TODO(b/120884788): This should assert not possible once fixed.
+ continue;
+ }
+ if (definition.isLibraryClass()) {
+ if (!libraryClasses.add(definition.asLibraryClass())) {
+ continue;
+ }
+ } else if (definition.isClasspathClass()) {
+ if (!classpathClasses.add(definition.asClasspathClass())) {
+ continue;
+ }
+ }
+ if (definition.superType != null) {
+ worklist.add(definition.superType);
+ }
+ Collections.addAll(worklist, definition.interfaces.values);
+ }
+ }
+
private void postProcessLibraryConversionWrappers(DirectMappedDexApplication.Builder appBuilder) {
if (desugaredLibraryWrapperAnalysis == null) {
return;
@@ -2406,7 +2563,11 @@
for (DexProgramClass wrapper : wrappers) {
appBuilder.addProgramClass(wrapper);
liveTypes.add(wrapper, graphReporter.fakeReportShouldNotBeUsed());
- instantiatedTypes.add(wrapper, graphReporter.fakeReportShouldNotBeUsed());
+ objectAllocationInfoCollection.recordDirectAllocationSite(
+ wrapper,
+ null,
+ InstantiationReason.SYNTHESIZED_CLASS,
+ graphReporter.fakeReportShouldNotBeUsed());
// Mark all methods on the wrapper as live and targeted.
for (DexEncodedMethod method : wrapper.methods()) {
targetedMethods.add(method, graphReporter.fakeReportShouldNotBeUsed());
@@ -2441,7 +2602,11 @@
appBuilder.addToMainDexList(Collections.singletonList(programClass.type));
}
liveTypes.add(programClass, graphReporter.fakeReportShouldNotBeUsed());
- instantiatedTypes.add(programClass, graphReporter.fakeReportShouldNotBeUsed());
+ objectAllocationInfoCollection.recordDirectAllocationSite(
+ programClass,
+ null,
+ InstantiationReason.SYNTHESIZED_CLASS,
+ graphReporter.fakeReportShouldNotBeUsed());
// Register all of the field writes in the lambda constructors.
// This is needed to ensure that the initializers can be optimized.
@@ -2529,10 +2694,10 @@
}
private static <T extends PresortedComparable<T>> SortedSet<T> toSortedDescriptorSet(
- Set<? extends KeyedDexItem<T>> set) {
+ Set<? extends DexEncodedMember<T>> set) {
ImmutableSortedSet.Builder<T> builder =
new ImmutableSortedSet.Builder<>(PresortedComparable::slowCompareTo);
- for (KeyedDexItem<T> item : set) {
+ for (DexEncodedMember<T> item : set) {
builder.add(item.getKey());
}
return builder.build();
@@ -2554,19 +2719,15 @@
timing.begin("Grow the tree.");
try {
while (true) {
- long numOfLiveItems = (long) liveTypes.items.size();
- numOfLiveItems += (long) liveMethods.items.size();
- numOfLiveItems += (long) liveFields.items.size();
+ long numberOfLiveItems = getNumberOfLiveItems();
while (!workList.isEmpty()) {
EnqueuerAction action = workList.poll();
action.run(this);
}
// Continue fix-point processing if -if rules are enabled by items that newly became live.
- long numOfLiveItemsAfterProcessing = (long) liveTypes.items.size();
- numOfLiveItemsAfterProcessing += (long) liveMethods.items.size();
- numOfLiveItemsAfterProcessing += (long) liveFields.items.size();
- if (numOfLiveItemsAfterProcessing > numOfLiveItems) {
+ long numberOfLiveItemsAfterProcessing = getNumberOfLiveItems();
+ if (numberOfLiveItemsAfterProcessing > numberOfLiveItems) {
// Build the mapping of active if rules. We use a single collection of if-rules to allow
// removing if rules that have a constant sequent keep rule when they materialize.
if (activeIfRules == null) {
@@ -2590,6 +2751,7 @@
consequentSetBuilder,
targetedMethods.getItems());
addConsequentRootSet(ifRuleEvaluator.run(), false);
+ assert getNumberOfLiveItems() == numberOfLiveItemsAfterProcessing;
if (!workList.isEmpty()) {
continue;
}
@@ -2631,11 +2793,6 @@
Set<DexEncodedMethod> reachableNotLive = Sets.difference(allLive, liveMethods.getItems());
Log.debug(getClass(), "%s methods are reachable but not live", reachableNotLive.size());
Log.info(getClass(), "Only reachable: %s", reachableNotLive);
- Set<DexProgramClass> liveButNotInstantiated =
- Sets.difference(liveTypes.getItems(), instantiatedTypes.getItems());
- Log.debug(getClass(), "%s classes are live but not instantiated",
- liveButNotInstantiated.size());
- Log.info(getClass(), "Live but not instantiated: %s", liveButNotInstantiated);
SetView<DexEncodedMethod> targetedButNotLive = Sets
.difference(targetedMethods.getItems(), liveMethods.getItems());
Log.debug(getClass(), "%s methods are targeted but not live", targetedButNotLive.size());
@@ -2647,6 +2804,13 @@
unpinLambdaMethods();
}
+ private long getNumberOfLiveItems() {
+ long result = liveTypes.items.size();
+ result += liveMethods.items.size();
+ result += liveFields.items.size();
+ return result;
+ }
+
private void addConsequentRootSet(ConsequentRootSet consequentRootSet, boolean addNoShrinking) {
// TODO(b/132600955): This modifies the root set. Should the consequent be persistent?
rootSet.addConsequentRootSet(consequentRootSet, addNoShrinking);
@@ -2835,9 +2999,9 @@
}
}
markParameterAndReturnTypesAsLive(method);
- processAnnotations(method, method.annotations.annotations);
+ processAnnotations(clazz, method);
method.parameterAnnotationsList.forEachAnnotation(
- annotation -> processAnnotation(method, annotation));
+ annotation -> processAnnotation(clazz, method, annotation));
method.registerCodeReferences(useRegistryFactory.create(appView, clazz, method, this));
// Add all dependent members to the workqueue.
@@ -2865,7 +3029,7 @@
}
private void markClassAsInstantiatedWithReason(DexProgramClass clazz, KeepReason reason) {
- workList.enqueueMarkInstantiatedAction(clazz, null, reason);
+ workList.enqueueMarkInstantiatedAction(clazz, null, InstantiationReason.REFLECTION, reason);
if (clazz.hasDefaultInitializer()) {
workList.enqueueMarkReachableDirectAction(clazz.getDefaultInitializer().method, reason);
}
@@ -2873,16 +3037,18 @@
private void markClassAsInstantiatedWithCompatRule(
DexProgramClass clazz, KeepReasonWitness witness) {
- if (clazz.isInterface() && !clazz.accessFlags.isAnnotation()) {
+ if (clazz.isAnnotation()) {
+ markTypeAsLive(clazz, witness);
+ } else if (clazz.isInterface()) {
markInterfaceAsInstantiated(clazz, witness);
- return;
- }
- workList.enqueueMarkInstantiatedAction(clazz, null, witness);
- if (clazz.hasDefaultInitializer()) {
- DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
- workList.enqueueMarkReachableDirectAction(
- defaultInitializer.method,
- graphReporter.reportCompatKeepDefaultInitializer(clazz, defaultInitializer));
+ } else {
+ workList.enqueueMarkInstantiatedAction(clazz, null, InstantiationReason.KEEP_RULE, witness);
+ if (clazz.hasDefaultInitializer()) {
+ DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
+ workList.enqueueMarkReachableDirectAction(
+ defaultInitializer.method,
+ graphReporter.reportCompatKeepDefaultInitializer(clazz, defaultInitializer));
+ }
}
}
@@ -2940,10 +3106,11 @@
if (clazz == null) {
return;
}
- if (clazz.isInterface()) {
+ if (clazz.isAnnotation() || clazz.isInterface()) {
markTypeAsLive(clazz.type, KeepReason.reflectiveUseIn(method));
} else {
- markInstantiated(clazz, null, KeepReason.reflectiveUseIn(method));
+ workList.enqueueMarkInstantiatedAction(
+ clazz, null, InstantiationReason.REFLECTION, KeepReason.reflectiveUseIn(method));
if (clazz.hasDefaultInitializer()) {
DexEncodedMethod initializer = clazz.getDefaultInitializer();
KeepReason reason = KeepReason.reflectiveUseIn(method);
@@ -2970,7 +3137,8 @@
!encodedField.accessFlags.isStatic()
&& dexItemFactory.atomicFieldUpdaterMethods.isFieldUpdater(invokedMethod);
if (keepClass) {
- markInstantiated(clazz, null, KeepReason.reflectiveUseIn(method));
+ workList.enqueueMarkInstantiatedAction(
+ clazz, null, InstantiationReason.REFLECTION, KeepReason.reflectiveUseIn(method));
}
if (pinnedItems.add(encodedField.field)) {
markFieldAsKept(clazz, encodedField, KeepReason.reflectiveUseIn(method));
@@ -3428,6 +3596,8 @@
@Override
public boolean addField(DexField field) {
+ recordTypeReference(field.holder);
+ recordTypeReference(field.type);
DexClass holder = appView.definitionFor(field.holder);
if (holder == null) {
return false;
@@ -3462,6 +3632,11 @@
@Override
public boolean addMethod(DexMethod method) {
+ // Record the references in case they are not program types.
+ recordTypeReference(method.proto.returnType);
+ for (DexType param : method.proto.parameters.values) {
+ recordTypeReference(param);
+ }
DexProgramClass holder = getProgramClassOrNull(method.holder);
if (holder == null) {
return false;
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
index d98d7c9..45e61a4 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
@@ -68,20 +68,56 @@
}
static class MarkInstantiatedAction extends EnqueuerAction {
+
final DexProgramClass target;
final DexEncodedMethod context;
- final KeepReason reason;
+ final InstantiationReason instantiationReason;
+ final KeepReason keepReason;
public MarkInstantiatedAction(
- DexProgramClass target, DexEncodedMethod context, KeepReason reason) {
+ DexProgramClass target,
+ DexEncodedMethod context,
+ InstantiationReason instantiationReason,
+ KeepReason keepReason) {
this.target = target;
this.context = context;
+ this.instantiationReason = instantiationReason;
+ this.keepReason = keepReason;
+ }
+
+ @Override
+ public void run(Enqueuer enqueuer) {
+ enqueuer.processNewlyInstantiatedClass(target, context, instantiationReason, keepReason);
+ }
+ }
+
+ static class MarkAnnotationInstantiatedAction extends EnqueuerAction {
+ final DexProgramClass target;
+ final KeepReasonWitness reason;
+
+ public MarkAnnotationInstantiatedAction(DexProgramClass target, KeepReasonWitness reason) {
+ this.target = target;
this.reason = reason;
}
@Override
public void run(Enqueuer enqueuer) {
- enqueuer.processNewlyInstantiatedClass(target, context, reason);
+ enqueuer.markTypeAsLive(target, reason);
+ }
+ }
+
+ static class MarkInterfaceInstantiatedAction extends EnqueuerAction {
+ final DexProgramClass target;
+ final KeepReasonWitness reason;
+
+ public MarkInterfaceInstantiatedAction(DexProgramClass target, KeepReasonWitness reason) {
+ this.target = target;
+ this.reason = reason;
+ }
+
+ @Override
+ public void run(Enqueuer enqueuer) {
+ enqueuer.markInterfaceAsInstantiated(target, reason);
}
}
@@ -235,9 +271,25 @@
// TODO(b/142378367): Context is the containing method that is cause of the instantiation.
// Consider updating call sites with the context information to increase precision where possible.
void enqueueMarkInstantiatedAction(
- DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
- assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
- queue.add(new MarkInstantiatedAction(clazz, context, reason));
+ DexProgramClass clazz,
+ DexEncodedMethod context,
+ InstantiationReason instantiationReason,
+ KeepReason keepReason) {
+ assert !clazz.isAnnotation();
+ assert !clazz.isInterface();
+ queue.add(new MarkInstantiatedAction(clazz, context, instantiationReason, keepReason));
+ }
+
+ void enqueueMarkAnnotationInstantiatedAction(DexProgramClass clazz, KeepReasonWitness reason) {
+ assert clazz.isAnnotation();
+ assert clazz.isInterface();
+ queue.add(new MarkAnnotationInstantiatedAction(clazz, reason));
+ }
+
+ void enqueueMarkInterfaceInstantiatedAction(DexProgramClass clazz, KeepReasonWitness reason) {
+ assert !clazz.isAnnotation();
+ assert clazz.isInterface();
+ queue.add(new MarkInterfaceInstantiatedAction(clazz, reason));
}
void enqueueMarkMethodLiveAction(
diff --git a/src/main/java/com/android/tools/r8/shaking/InstantiationReason.java b/src/main/java/com/android/tools/r8/shaking/InstantiationReason.java
new file mode 100644
index 0000000..c6af09d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/InstantiationReason.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.shaking;
+
+public enum InstantiationReason {
+ KEEP_RULE,
+ LAMBDA,
+ NEW_INSTANCE_INSTRUCTION,
+ REFERENCED_IN_METHOD_HANDLE,
+ REFLECTION,
+ SYNTHESIZED_CLASS
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java b/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
index 47cc590..3a6fcae 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
@@ -43,7 +43,7 @@
assert clazz != null;
consumer.accept(type);
// Super and interfaces are live, no need to add them.
- traceAnnotationsDirectDependencies(clazz.annotations);
+ traceAnnotationsDirectDependencies(clazz.annotations());
clazz.forEachField(field -> consumer.accept(field.field.type));
clazz.forEachMethod(method -> {
traceMethodDirectDependencies(method.method, consumer);
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
index 718b9a9..b92f82e 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexListBuilder.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.shaking;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexClass;
@@ -13,7 +14,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.utils.SetUtils;
-import com.google.common.collect.Maps;
+import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
@@ -32,16 +33,7 @@
private final DirectMappedDexApplication dexApplication;
private final MainDexClasses.Builder mainDexClassesBuilder;
- /**
- * @param roots Classes which code may be executed before secondary dex files loading.
- * @param application the dex appplication.
- */
- public MainDexListBuilder(Set<DexProgramClass> roots, DirectMappedDexApplication application) {
- this.dexApplication = application;
- this.appInfo = new AppInfoWithSubtyping(dexApplication);
- // Only consider program classes for the root set.
- this.roots = SetUtils.mapIdentityHashSet(roots, DexProgramClass::getType);
- mainDexClassesBuilder = MainDexClasses.builder(appInfo).addRoots(this.roots);
+ public static void checkForAssumedLibraryTypes(AppInfo appInfo) {
DexClass enumType = appInfo.definitionFor(appInfo.dexItemFactory().enumType);
if (enumType == null) {
throw new CompilationError("Tracing for legacy multi dex is not possible without all"
@@ -52,9 +44,19 @@
throw new CompilationError("Tracing for legacy multi dex is not possible without all"
+ " classpath libraries (java.lang.annotation.Annotation is missing)");
}
- annotationTypeContainEnum =
- Maps.newHashMapWithExpectedSize(
- appInfo.subtypes(appInfo.dexItemFactory().annotationType).size());
+ }
+
+ /**
+ * @param roots Classes which code may be executed before secondary dex files loading.
+ * @param application the dex appplication.
+ */
+ public MainDexListBuilder(Set<DexProgramClass> roots, DirectMappedDexApplication application) {
+ this.dexApplication = application;
+ this.appInfo = new AppInfoWithSubtyping(dexApplication);
+ // Only consider program classes for the root set.
+ this.roots = SetUtils.mapIdentityHashSet(roots, DexProgramClass::getType);
+ mainDexClassesBuilder = MainDexClasses.builder(appInfo).addRoots(this.roots);
+ annotationTypeContainEnum = new IdentityHashMap<>();
}
public MainDexClasses run() {
@@ -126,11 +128,6 @@
return appInfo.isSubtype(valueType, appInfo.dexItemFactory().annotationType);
}
- private boolean isProgramClass(DexType dexType) {
- DexClass clazz = appInfo.definitionFor(dexType);
- return clazz != null && clazz.isProgramClass();
- }
-
private void traceMainDexDirectDependencies() {
new MainDexDirectReferenceTracer(appInfo, this::addDirectDependency)
.run(roots);
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
index c5dcb0c..f75a307 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfigurationUtils.java
@@ -105,7 +105,7 @@
.setClassType(ProguardClassType.CLASS)
.setClassNames(
ProguardClassNameList.singletonList(
- ProguardTypeMatcher.create(factory.createType("Landroid/os/Build$VERSION;"))))
+ ProguardTypeMatcher.create(factory.androidOsBuildVersionType)))
.setMemberRules(
ImmutableList.of(
ProguardMemberRule.builder()
@@ -138,7 +138,7 @@
&& !rule.getInheritanceClassName().matches(factory.objectType)) {
continue;
}
- if (!rule.getClassNames().matches(factory.createType("Landroid/os/Build$VERSION;"))) {
+ if (!rule.getClassNames().matches(factory.androidOsBuildVersionType)) {
continue;
}
for (ProguardMemberRule memberRule : rule.getMemberRules()) {
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
index 4186091..7495c6b 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetBuilder.java
@@ -871,11 +871,11 @@
}
static boolean containsAnnotation(ProguardTypeMatcher classAnnotation, DexClass clazz) {
- return containsAnnotation(classAnnotation, clazz.annotations);
+ return containsAnnotation(classAnnotation, clazz.annotations());
}
static boolean containsAnnotation(ProguardTypeMatcher classAnnotation, DexEncodedMethod method) {
- if (containsAnnotation(classAnnotation, method.annotations)) {
+ if (containsAnnotation(classAnnotation, method.annotations())) {
return true;
}
for (int i = 0; i < method.parameterAnnotationsList.size(); i++) {
@@ -887,7 +887,7 @@
}
static boolean containsAnnotation(ProguardTypeMatcher classAnnotation, DexEncodedField field) {
- return containsAnnotation(classAnnotation, field.annotations);
+ return containsAnnotation(classAnnotation, field.annotations());
}
private static boolean containsAnnotation(
diff --git a/src/main/java/com/android/tools/r8/shaking/TreePruner.java b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
index dc66249..3ded35c 100644
--- a/src/main/java/com/android/tools/r8/shaking/TreePruner.java
+++ b/src/main/java/com/android/tools/r8/shaking/TreePruner.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
@@ -15,7 +16,6 @@
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.EnclosingMethodAttribute;
import com.android.tools.r8.graph.InnerClassAttribute;
-import com.android.tools.r8.graph.KeyedDexItem;
import com.android.tools.r8.graph.NestMemberClassAttribute;
import com.android.tools.r8.graph.PresortedComparable;
import com.android.tools.r8.logging.Log;
@@ -85,7 +85,7 @@
}
if (appInfo.isLiveProgramClass(clazz)) {
newClasses.add(clazz);
- if (!appInfo.instantiatedTypes.contains(clazz.type)
+ if (!appInfo.getObjectAllocationInfoCollection().isInstantiatedDirectly(clazz)
&& !options.forceProguardCompatibility) {
// The class is only needed as a type but never instantiated. Make it abstract to reflect
// this.
@@ -243,8 +243,8 @@
return context == null || !isTypeLive(context);
}
- private <S extends PresortedComparable<S>, T extends KeyedDexItem<S>> int firstUnreachableIndex(
- List<T> items, Predicate<T> live) {
+ private <S extends PresortedComparable<S>, T extends DexEncodedMember<S>>
+ int firstUnreachableIndex(List<T> items, Predicate<T> live) {
for (int i = 0; i < items.size(); i++) {
if (!live.test(items.get(i))) {
return i;
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 8217920..76db9fe 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.graph.DexClass.FieldSetter;
import com.android.tools.r8.graph.DexClass.MethodSetter;
import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
@@ -26,7 +27,7 @@
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.GraphLense.GraphLenseLookupResult;
-import com.android.tools.r8.graph.KeyedDexItem;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.PresortedComparable;
@@ -325,7 +326,7 @@
// Returns true if [clazz] is a merge candidate. Note that the result of the checks in this
// method do not change in response to any class merges.
private boolean isMergeCandidate(DexProgramClass clazz, Set<DexType> pinnedTypes) {
- if (appInfo.instantiatedTypes.contains(clazz.type)
+ if (appInfo.getObjectAllocationInfoCollection().isInstantiatedDirectly(clazz)
|| appInfo.instantiatedLambdas.contains(clazz.type)
|| appInfo.isPinned(clazz.type)
|| pinnedTypes.contains(clazz.type)
@@ -334,7 +335,7 @@
}
assert Streams.stream(Iterables.concat(clazz.fields(), clazz.methods()))
- .map(KeyedDexItem::getKey)
+ .map(DexEncodedMember::getKey)
.noneMatch(appInfo::isPinned);
if (appView.options().featureSplitConfiguration != null &&
@@ -734,11 +735,17 @@
// }
for (DexEncodedMethod method : defaultMethods) {
// Conservatively find all possible targets for this method.
- Set<DexEncodedMethod> interfaceTargets =
+ LookupResult lookupResult =
appInfo
.resolveMethodOnInterface(method.method.holder, method.method)
- .lookupVirtualDispatchTargets(appInfo);
-
+ .lookupVirtualDispatchTargets(appView, appInfo);
+ assert lookupResult.isLookupResultSuccess();
+ if (lookupResult.isLookupResultFailure()) {
+ return true;
+ }
+ assert lookupResult.isLookupResultSuccess();
+ Set<DexEncodedMethod> interfaceTargets =
+ lookupResult.asLookupResultSuccess().getMethodTargets();
// If [method] is not even an interface-target, then we can safely merge it. Otherwise we
// need to check for a conflict.
if (interfaceTargets.remove(method)) {
@@ -1262,12 +1269,12 @@
return null;
}
- private <T extends KeyedDexItem<S>, S extends PresortedComparable<S>> void add(
+ private <T extends DexEncodedMember<S>, S extends PresortedComparable<S>> void add(
Map<Wrapper<S>, T> map, T item, Equivalence<S> equivalence) {
map.put(equivalence.wrap(item.getKey()), item);
}
- private <T extends KeyedDexItem<S>, S extends PresortedComparable<S>> void addAll(
+ private <T extends DexEncodedMember<S>, S extends PresortedComparable<S>> void addAll(
Collection<Wrapper<S>> collection, Iterable<T> items, Equivalence<S> equivalence) {
for (T item : items) {
collection.add(equivalence.wrap(item.getKey()));
diff --git a/src/main/java/com/android/tools/r8/utils/LensUtils.java b/src/main/java/com/android/tools/r8/utils/LensUtils.java
new file mode 100644
index 0000000..325d6fa
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/LensUtils.java
@@ -0,0 +1,23 @@
+// 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.utils;
+
+import com.android.tools.r8.graph.DexDefinitionSupplier;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.GraphLense;
+import com.google.common.collect.Sets;
+import java.util.Set;
+
+public class LensUtils {
+
+ public static Set<DexEncodedMethod> rewrittenWithRenamedSignature(
+ Set<DexEncodedMethod> methods, DexDefinitionSupplier definitions, GraphLense lens) {
+ Set<DexEncodedMethod> result = Sets.newIdentityHashSet();
+ for (DexEncodedMethod method : methods) {
+ result.add(lens.mapDexEncodedMethod(method, definitions));
+ }
+ return result;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 7bcf1c9..78edccb 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -35,6 +35,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.kotlin.KotlinSourceDebugExtensionParser;
import com.android.tools.r8.kotlin.KotlinSourceDebugExtensionParser.Result;
@@ -46,6 +47,7 @@
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.naming.Range;
+import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.utils.InternalOptions.LineNumberOptimization;
import com.google.common.base.Suppliers;
import java.util.ArrayList;
@@ -306,6 +308,7 @@
// methods, we either did not rename them, we renamed them according to a supplied map or
// they may be bridges for interface methods with covariant return types.
sortMethods(methods);
+ assert verifyMethodsAreKeptDirectlyOrIndirectly(appView, methods);
}
boolean identityMapping =
@@ -431,6 +434,43 @@
return classNameMapperBuilder.build();
}
+ private static boolean verifyMethodsAreKeptDirectlyOrIndirectly(
+ AppView<AppInfoWithSubtyping> appView, List<DexEncodedMethod> methods) {
+ if (appView.options().isGeneratingClassFiles()) {
+ return true;
+ }
+ RootSet rootSet = appView.rootSet();
+ DexString originalName = null;
+ for (DexEncodedMethod method : methods) {
+ // We cannot rename instance initializers.
+ if (method.isInstanceInitializer()) {
+ continue;
+ }
+ // If the method is pinned, we cannot minify it.
+ if (rootSet.mayNotBeMinified(method.method, appView)) {
+ continue;
+ }
+ // With desugared library, call-backs names are reserved here.
+ if (method.isLibraryMethodOverride().isTrue()) {
+ continue;
+ }
+ // We use the same name for interface names even if it has different types.
+ DexProgramClass clazz = appView.definitionForProgramType(method.method.holder);
+ ResolutionResult resolutionResult =
+ appView.appInfo().resolveMaximallySpecificMethods(clazz, method.method);
+ if (resolutionResult.isFailedResolution()) {
+ // We cannot rename methods we cannot look up.
+ continue;
+ }
+ String errorString = method.method.qualifiedName() + " is not kept but is overloaded";
+ assert resolutionResult.isSingleResolution() : errorString;
+ assert resolutionResult.asSingleResolution().getResolvedHolder().isInterface() : errorString;
+ assert originalName == null || originalName.equals(method.method.name) : errorString;
+ originalName = method.method.name;
+ }
+ return true;
+ }
+
private static int getMethodStartLine(DexEncodedMethod method) {
Code code = method.getCode();
if (code == null) {
@@ -653,7 +693,7 @@
assert !identityMapping
|| inlinedOriginalPosition.get()
- || checkIdentityMapping(debugInfo, optimizedDebugInfo);
+ || verifyIdentityMapping(debugInfo, optimizedDebugInfo);
dexCode.setDebugInfo(optimizedDebugInfo);
}
@@ -709,7 +749,7 @@
dexCode.setDebugInfo(null);
}
- private static boolean checkIdentityMapping(
+ private static boolean verifyIdentityMapping(
DexDebugInfo originalDebugInfo, DexDebugInfo optimizedDebugInfo) {
assert optimizedDebugInfo.startLine == originalDebugInfo.startLine;
assert optimizedDebugInfo.events.length == originalDebugInfo.events.length;
diff --git a/src/main/java/com/android/tools/r8/utils/OrderedMergingIterator.java b/src/main/java/com/android/tools/r8/utils/OrderedMergingIterator.java
index 33f9d7c..40fa54f 100644
--- a/src/main/java/com/android/tools/r8/utils/OrderedMergingIterator.java
+++ b/src/main/java/com/android/tools/r8/utils/OrderedMergingIterator.java
@@ -4,13 +4,13 @@
package com.android.tools.r8.utils;
import com.android.tools.r8.errors.InternalCompilerError;
-import com.android.tools.r8.graph.KeyedDexItem;
+import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.PresortedComparable;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
-public class OrderedMergingIterator<T extends KeyedDexItem<S>, S extends PresortedComparable<S>>
+public class OrderedMergingIterator<T extends DexEncodedMember<S>, S extends PresortedComparable<S>>
implements Iterator<T> {
private final List<T> one;
diff --git a/src/main/java/com/android/tools/r8/utils/Timing.java b/src/main/java/com/android/tools/r8/utils/Timing.java
index 78c1b44..5652476 100644
--- a/src/main/java/com/android/tools/r8/utils/Timing.java
+++ b/src/main/java/com/android/tools/r8/utils/Timing.java
@@ -75,6 +75,10 @@
: Timing.empty();
}
+ public static Timing create(String title, boolean printMemory) {
+ return new Timing(title, printMemory);
+ }
+
private final Node top;
private final Stack<Node> stack;
private final boolean trackMemory;
diff --git a/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java b/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
new file mode 100644
index 0000000..294a210
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/TraversalContinuation.java
@@ -0,0 +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.utils;
+
+/** Two value continuation value to indicate the continuation of a loop/traversal. */
+public enum TraversalContinuation {
+ CONTINUE,
+ BREAK;
+
+ public final boolean shouldBreak() {
+ return this == BREAK;
+ }
+
+ public final boolean shouldContinue() {
+ return this == CONTINUE;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/JvmTestBuilder.java b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
index 0e510a9..8bc4820 100644
--- a/src/test/java/com/android/tools/r8/JvmTestBuilder.java
+++ b/src/test/java/com/android/tools/r8/JvmTestBuilder.java
@@ -30,6 +30,16 @@
super(state);
}
+ private Path writeClassesToJar(Collection<Class<?>> classes) {
+ try {
+ Path archive = getState().getNewTempFolder().resolve("out.jar");
+ TestBase.writeClassesToJar(archive, classes);
+ return archive;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
public static JvmTestBuilder create(TestState state) {
return new JvmTestBuilder(state);
}
@@ -77,14 +87,7 @@
@Override
public JvmTestBuilder addProgramClasses(Collection<Class<?>> classes) {
- try {
- Path out = getState().getNewTempFolder().resolve("out.jar");
- TestBase.writeClassesToJar(out, classes);
- addProgramFiles(out);
- return self();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ return addProgramFiles(writeClassesToJar(classes));
}
@Override
diff --git a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
index 2b6cd3c..4a94ac1 100644
--- a/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
+++ b/src/test/java/com/android/tools/r8/KotlinCompilerTool.java
@@ -86,6 +86,30 @@
return this;
}
+ public KotlinCompilerTool addSourceFilesWithNonKtExtension(TemporaryFolder temp, Path... files) {
+ return addSourceFilesWithNonKtExtension(temp, Arrays.asList(files));
+ }
+
+ public KotlinCompilerTool addSourceFilesWithNonKtExtension(
+ TemporaryFolder temp, Collection<Path> files) {
+ return addSourceFiles(
+ files.stream()
+ .map(
+ fileNotNamedKt -> {
+ try {
+ // The Kotlin compiler does not require particular naming of files except for
+ // the extension,
+ // so just create a file called source.kt in a new directory.
+ Path fileNamedKt = temp.newFolder().toPath().resolve("source.kt");
+ Files.copy(fileNotNamedKt, fileNamedKt);
+ return fileNamedKt;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ })
+ .collect(Collectors.toList()));
+ }
+
public KotlinCompilerTool addClasspathFiles(Path... files) {
return addClasspathFiles(Arrays.asList(files));
}
diff --git a/src/test/java/com/android/tools/r8/KotlinTestBase.java b/src/test/java/com/android/tools/r8/KotlinTestBase.java
index c3ce381..1a6a428 100644
--- a/src/test/java/com/android/tools/r8/KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/KotlinTestBase.java
@@ -39,6 +39,12 @@
.collect(Collectors.toList());
}
+ protected static Path getKotlinFileInTestPackage(Package pkg, String fileName)
+ throws IOException {
+ String folder = DescriptorUtils.getBinaryNameFromJavaType(pkg.getName());
+ return getKotlinFileInTest(folder, fileName);
+ }
+
protected static Path getKotlinFileInTest(String folder, String fileName) {
return Paths.get(ToolHelper.TESTS_DIR, "java", folder, fileName + FileUtils.KT_EXTENSION);
}
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index 5094ec5..d3bc8da 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -716,6 +716,10 @@
return dataResources;
}
+ protected static Path getFileInTest(String folder, String fileName) {
+ return Paths.get(ToolHelper.TESTS_DIR, "java", folder, fileName);
+ }
+
/**
* Create a temporary JAR file containing all test classes in a package.
*/
@@ -1189,8 +1193,11 @@
consumer.finished(null);
}
- protected static void writeClassFileDataToJar(Path output, Collection<byte[]> classes)
- throws IOException {
+ protected static void writeClassesToJar(Path output, Class<?>... classes) throws IOException {
+ writeClassesToJar(output, Arrays.asList(classes));
+ }
+
+ protected static void writeClassFileDataToJar(Path output, Collection<byte[]> classes) {
ClassFileConsumer consumer = new ArchiveConsumer(output);
for (byte[] clazz : classes) {
consumer.accept(ByteDataView.of(clazz), extractClassDescriptor(clazz), null);
diff --git a/src/test/java/com/android/tools/r8/classlookup/ClasspathClassExtendsProgramClassTest.java b/src/test/java/com/android/tools/r8/classlookup/ClasspathClassExtendsProgramClassTest.java
new file mode 100644
index 0000000..b409e5a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/classlookup/ClasspathClassExtendsProgramClassTest.java
@@ -0,0 +1,105 @@
+// 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.classlookup;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.references.Reference;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.util.Collection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+// This test runs an R8 setup where a classpath class extends a program class and the program in
+// turn uses the classpath class. Having such a cyclic compilation setup is very odd, but with
+// sufficient keep rules it can work.
+@RunWith(Parameterized.class)
+public class ClasspathClassExtendsProgramClassTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public ClasspathClassExtendsProgramClassTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ public static class ProgramClass {
+
+ public void foo() {
+ System.out.println("ProgramClass::foo");
+ }
+ }
+
+ static class Main {
+ public static void main(String[] args) {
+ ProgramClass object = args.length == 42 ? new ProgramClass() : new ClasspathClass();
+ object.foo();
+ }
+ }
+
+ public static class ClasspathIndirection extends ProgramClass {
+ // Intentionally empty.
+ }
+
+ public static class ClasspathClass extends ClasspathIndirection {
+
+ @Override
+ public void foo() {
+ System.out.println("ClasspathClass::foo");
+ }
+ }
+
+ @Test
+ public void testReference() throws Exception {
+ testForRuntime(parameters)
+ .addProgramClasses(Main.class, ProgramClass.class)
+ .addRunClasspathFiles(compileClasspath())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("ClasspathClass::foo");
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters.getApiLevel())
+ .addProgramClasses(Main.class, ProgramClass.class)
+ .addClasspathClasses(ClasspathClass.class, ClasspathIndirection.class)
+ .addKeepMainRule(Main.class)
+ // Keep the method that is overridden by the classpath class.
+ .addKeepMethodRules(Reference.methodFromMethod(ProgramClass.class.getDeclaredMethod("foo")))
+ .addRunClasspathFiles(compileClasspath())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("ClasspathClass::foo");
+ }
+
+ private Path compileClasspath() throws java.io.IOException, CompilationFailedException {
+ return compile(
+ ImmutableList.of(ClasspathClass.class, ClasspathIndirection.class),
+ ImmutableList.of(ProgramClass.class));
+ }
+
+ private Path compile(Collection<Class<?>> compilationUnit, Collection<Class<?>> classpath)
+ throws java.io.IOException, CompilationFailedException {
+ if (parameters.isCfRuntime()) {
+ Path out = temp.newFolder().toPath().resolve("out.jar");
+ writeClassesToJar(out, compilationUnit);
+ return out;
+ }
+ return testForD8()
+ .setMinApi(parameters.getApiLevel())
+ .addProgramClasses(compilationUnit)
+ .addClasspathClasses(classpath)
+ .compile()
+ .writeToZip();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/TestBackportedNotPresentInAndroidJar.java b/src/test/java/com/android/tools/r8/desugar/backports/TestBackportedNotPresentInAndroidJar.java
index 83682b2..8096c47 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/TestBackportedNotPresentInAndroidJar.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/TestBackportedNotPresentInAndroidJar.java
@@ -8,11 +8,13 @@
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -23,7 +25,7 @@
import java.util.stream.Collectors;
import org.junit.Test;
-public class TestBackportedNotPresentInAndroidJar {
+public class TestBackportedNotPresentInAndroidJar extends TestBase {
@Test
public void testBackportedMethodsPerAPILevel() throws Exception {
@@ -40,7 +42,7 @@
options.minApiLevel = apiLevel.getLevel();
List<DexMethod> backportedMethods =
BackportedMethodRewriter.generateListOfBackportedMethods(
- null, options, ThreadUtils.getExecutorService(options));
+ AndroidApp.builder().build(), options, ThreadUtils.getExecutorService(options));
for (DexMethod method : backportedMethods) {
// Two different DexItemFactories are in play, but as toSourceString is used for lookup
// that is not an issue.
diff --git a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
index 53bb117..666cb87 100644
--- a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
+++ b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.code.IfNez;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.code.ReturnVoid;
+import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexCode.Try;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -160,7 +161,8 @@
null);
MethodAccessFlags flags = MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false);
DexEncodedMethod method =
- new DexEncodedMethod(null, flags, null, ParameterAnnotationsList.empty(), code);
+ new DexEncodedMethod(
+ null, flags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), code);
return new JumboStringRewriter(method, string, factory).rewrite();
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
index 0924546..4484311 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreLookupTest.java
@@ -7,36 +7,39 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.StringResource;
+import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DirectMappedDexApplication;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
-import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.junit.Before;
import org.junit.Test;
-public class R8GMSCoreLookupTest {
+public class R8GMSCoreLookupTest extends TestBase {
static final String APP_DIR = "third_party/gmscore/v5/";
private AndroidApp app;
private DirectMappedDexApplication program;
private AppInfoWithSubtyping appInfo;
+ private AppView<?> appView;
@Before
- public void readGMSCore() throws IOException, ExecutionException {
+ public void readGMSCore() throws Exception {
Path directory = Paths.get(APP_DIR);
app = ToolHelper.builderFromProgramDirectory(directory).build();
Path mapFile = directory.resolve(ToolHelper.DEFAULT_PROGUARD_MAP_FILE);
@@ -51,6 +54,7 @@
.read(proguardMap, executorService)
.toDirect();
appInfo = new AppInfoWithSubtyping(program);
+ appView = computeAppViewWithSubtyping(app);
}
private void testVirtualLookup(DexProgramClass clazz, DexEncodedMethod method) {
@@ -59,16 +63,20 @@
assertEquals(appInfo.resolveMethod(id.holder, method.method).getSingleTarget(), method);
// Check lookup targets with include method.
- Set<DexEncodedMethod> targets =
- appInfo.resolveMethodOnClass(clazz, method.method).lookupVirtualDispatchTargets(appInfo);
+ ResolutionResult resolutionResult = appInfo.resolveMethodOnClass(clazz, method.method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView, appInfo);
+ assertTrue(lookupResult.isLookupResultSuccess());
+ Set<DexEncodedMethod> targets = lookupResult.asLookupResultSuccess().getMethodTargets();
assertTrue(targets.contains(method));
}
private void testInterfaceLookup(DexProgramClass clazz, DexEncodedMethod method) {
- Set<DexEncodedMethod> targets =
+ LookupResult lookupResult =
appInfo
.resolveMethodOnInterface(clazz, method.method)
- .lookupVirtualDispatchTargets(appInfo);
+ .lookupVirtualDispatchTargets(appView, appInfo);
+ assertTrue(lookupResult.isLookupResultSuccess());
+ Set<DexEncodedMethod> targets = lookupResult.asLookupResultSuccess().getMethodTargets();
if (appInfo.subtypes(method.method.holder).stream()
.allMatch(t -> appInfo.definitionFor(t).isInterface())) {
assertEquals(
@@ -81,8 +89,6 @@
}
}
-
-
private void testLookup(DexProgramClass clazz) {
if (clazz.isInterface()) {
for (DexEncodedMethod method : clazz.virtualMethods()) {
diff --git a/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java b/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
index b567014..7b7036f 100644
--- a/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
+++ b/src/test/java/com/android/tools/r8/ir/conversion/CallGraphTestBase.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.conversion;
import com.android.tools.r8.TestBase;
+import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
@@ -20,7 +21,8 @@
dexItemFactory.createProto(dexItemFactory.voidType),
methodName);
return new Node(
- new DexEncodedMethod(signature, null, null, ParameterAnnotationsList.empty(), null));
+ new DexEncodedMethod(
+ signature, null, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(), null));
}
Node createForceInlinedNode(String methodName) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentForwardingConstructorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentForwardingConstructorTest.java
new file mode 100644
index 0000000..a118c85
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentForwardingConstructorTest.java
@@ -0,0 +1,107 @@
+// 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+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.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantArgumentForwardingConstructorTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public FieldInitializedByConstantArgumentForwardingConstructorTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(FieldInitializedByConstantArgumentForwardingConstructorTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Live!", "Live!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+ assertThat(testClassSubject, isPresent());
+ assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+ // TODO(b/147652121): Should be absent.
+ assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ if (allocationSite1().x == 42) {
+ live();
+ } else {
+ dead();
+ }
+
+ if (allocationSite2().x == 42) {
+ live();
+ } else {
+ dead();
+ }
+ }
+
+ @NeverInline
+ static A allocationSite1() {
+ return new A();
+ }
+
+ @NeverInline
+ static A allocationSite2() {
+ return new A(42);
+ }
+
+ @NeverInline
+ static void live() {
+ System.out.println("Live!");
+ }
+
+ @NeverInline
+ static void dead() {
+ System.out.println("Dead!");
+ }
+ }
+
+ @NeverClassInline
+ static class A {
+
+ int x;
+
+ A() {
+ this(42);
+ }
+
+ A(int x) {
+ this.x = x;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentMultipleConstructorsTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentMultipleConstructorsTest.java
new file mode 100644
index 0000000..6663b91
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentMultipleConstructorsTest.java
@@ -0,0 +1,107 @@
+// 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+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.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantArgumentMultipleConstructorsTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public FieldInitializedByConstantArgumentMultipleConstructorsTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(FieldInitializedByConstantArgumentMultipleConstructorsTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Live!", "Live!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+ assertThat(testClassSubject, isPresent());
+ assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+ // TODO(b/147652121): Should be absent.
+ assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ if (allocationSite1().x == 42) {
+ live();
+ } else {
+ dead();
+ }
+
+ if (allocationSite2().x == 42) {
+ live();
+ } else {
+ dead();
+ }
+ }
+
+ @NeverInline
+ static A allocationSite1() {
+ return new A(42);
+ }
+
+ @NeverInline
+ static A allocationSite2() {
+ return new A(42, null);
+ }
+
+ @NeverInline
+ static void live() {
+ System.out.println("Live!");
+ }
+
+ @NeverInline
+ static void dead() {
+ System.out.println("Dead!");
+ }
+ }
+
+ @NeverClassInline
+ static class A {
+
+ int x;
+
+ A(int x) {
+ this.x = x;
+ }
+
+ A(int x, Object unused) {
+ this.x = x;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentSubtypeTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentSubtypeTest.java
new file mode 100644
index 0000000..c460e16
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentSubtypeTest.java
@@ -0,0 +1,111 @@
+// 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+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.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantArgumentSubtypeTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public FieldInitializedByConstantArgumentSubtypeTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(FieldInitializedByConstantArgumentSubtypeTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Live!", "Live!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+ assertThat(testClassSubject, isPresent());
+ assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+ // TODO(b/147652121): Should be absent.
+ assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ if (allocationSite1().x == 42) {
+ live();
+ } else {
+ dead();
+ }
+
+ if (allocationSite2().x == 42) {
+ live();
+ } else {
+ dead();
+ }
+ }
+
+ @NeverInline
+ static A allocationSite1() {
+ return new A(42);
+ }
+
+ @NeverInline
+ static A allocationSite2() {
+ return new B(42);
+ }
+
+ @NeverInline
+ static void live() {
+ System.out.println("Live!");
+ }
+
+ @NeverInline
+ static void dead() {
+ System.out.println("Dead!");
+ }
+ }
+
+ @NeverClassInline
+ static class A {
+
+ int x;
+
+ A(int x) {
+ this.x = x;
+ }
+ }
+
+ @NeverClassInline
+ static class B extends A {
+
+ B(int x) {
+ super(x);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentTest.java
new file mode 100644
index 0000000..beecf65
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantArgumentTest.java
@@ -0,0 +1,103 @@
+// 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+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.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantArgumentTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public FieldInitializedByConstantArgumentTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(FieldInitializedByConstantArgumentTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Live!", "Live!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+ assertThat(testClassSubject, isPresent());
+ assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+ // TODO(b/147652121): Should be absent.
+ assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ if (allocationSite1().x == 42) {
+ live();
+ } else {
+ dead();
+ }
+
+ if (allocationSite2().x == 42) {
+ live();
+ } else {
+ dead();
+ }
+ }
+
+ @NeverInline
+ static A allocationSite1() {
+ return new A(42);
+ }
+
+ @NeverInline
+ static A allocationSite2() {
+ return new A(42);
+ }
+
+ @NeverInline
+ static void live() {
+ System.out.println("Live!");
+ }
+
+ @NeverInline
+ static void dead() {
+ System.out.println("Dead!");
+ }
+ }
+
+ @NeverClassInline
+ static class A {
+
+ int x;
+
+ A(int x) {
+ this.x = x;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantInOneConstructorTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantInOneConstructorTest.java
new file mode 100644
index 0000000..71ef038
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByConstantInOneConstructorTest.java
@@ -0,0 +1,95 @@
+// 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+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.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByConstantInOneConstructorTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public FieldInitializedByConstantInOneConstructorTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(FieldInitializedByConstantInOneConstructorTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Live!", "true");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+ assertThat(testClassSubject, isPresent());
+ assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+ // TODO(b/147652121): Should be absent.
+ assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ A obj1 = new A();
+ if (obj1.x == 42) {
+ live();
+ } else {
+ dead();
+ }
+
+ A obj2 = new A((int) System.currentTimeMillis());
+ System.out.println(obj2.x != 42);
+ }
+
+ @NeverInline
+ static void live() {
+ System.out.println("Live!");
+ }
+
+ @NeverInline
+ static void dead() {
+ System.out.println("Dead!");
+ }
+ }
+
+ @NeverClassInline
+ static class A {
+
+ int x;
+
+ A() {
+ this.x = 42;
+ }
+
+ A(int x) {
+ this.x = x;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByNonConstantArgumentTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByNonConstantArgumentTest.java
new file mode 100644
index 0000000..c0c12e2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/fields/FieldInitializedByNonConstantArgumentTest.java
@@ -0,0 +1,95 @@
+// 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.ir.optimize.membervaluepropagation.fields;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+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.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldInitializedByNonConstantArgumentTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public FieldInitializedByNonConstantArgumentTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ testForR8(parameters.getBackend())
+ .addInnerClasses(FieldInitializedByNonConstantArgumentTest.class)
+ .addKeepMainRule(TestClass.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::inspect)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Live!", "Live!");
+ }
+
+ private void inspect(CodeInspector inspector) {
+ ClassSubject testClassSubject = inspector.clazz(TestClass.class);
+ assertThat(testClassSubject, isPresent());
+ assertThat(testClassSubject.uniqueMethodWithName("live"), isPresent());
+ // TODO(b/147652121): Should be absent.
+ assertThat(testClassSubject.uniqueMethodWithName("dead"), isPresent());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ A obj1 = new A(42);
+ if (obj1.x == 42) {
+ live();
+ } else {
+ dead();
+ }
+
+ A obj2 = new A(43);
+ if (obj2.x == 43) {
+ live();
+ } else {
+ dead();
+ }
+ }
+
+ @NeverInline
+ static void live() {
+ System.out.println("Live!");
+ }
+
+ @NeverInline
+ static void dead() {
+ System.out.println("Dead!");
+ }
+ }
+
+ @NeverClassInline
+ static class A {
+
+ int x;
+
+ A(int x) {
+ this.x = x;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/B148525512.java b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/B148525512.java
new file mode 100644
index 0000000..a06dcf8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/B148525512.java
@@ -0,0 +1,155 @@
+// 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.kotlin.lambda.b148525512;
+
+import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.DexIndexedConsumer.ArchiveConsumer;
+import com.android.tools.r8.KotlinTestBase;
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
+import com.android.tools.r8.utils.ArchiveResourceProvider;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
+import com.android.tools.r8.utils.codeinspector.InstructionSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class B148525512 extends KotlinTestBase {
+
+ private static final Package pkg = B148525512.class.getPackage();
+ private static final String kotlinTestClassesPackage = pkg.getName();
+ private static final String baseKtClassName = kotlinTestClassesPackage + ".BaseKt";
+ private static final String featureKtClassNamet = kotlinTestClassesPackage + ".FeatureKt";
+ private static final String baseClassName = kotlinTestClassesPackage + ".Base";
+
+ private static final Map<KotlinTargetVersion, Path> kotlinBaseClasses = new HashMap<>();
+ private static final Map<KotlinTargetVersion, Path> kotlinFeatureClasses = new HashMap<>();
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0},{1}")
+ public static Collection<Object[]> data() {
+ return buildParameters(
+ getTestParameters().withDexRuntimes().withAllApiLevels().build(),
+ KotlinTargetVersion.values());
+ }
+
+ public B148525512(TestParameters parameters, KotlinTargetVersion targetVersion) {
+ super(targetVersion);
+ this.parameters = parameters;
+ }
+
+ @ClassRule public static TemporaryFolder classTemp = new TemporaryFolder();
+
+ @BeforeClass
+ public static void compileKotlin() throws Exception {
+ // Compile the base Kotlin with the FeatureAPI Java class on classpath.
+ Path featureApiJar = classTemp.newFile("feature_api.jar").toPath();
+ writeClassesToJar(featureApiJar, FeatureAPI.class);
+ for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
+ Path ktBaseClasses =
+ kotlinc(KOTLINC, targetVersion)
+ .addClasspathFiles(featureApiJar)
+ .addSourceFiles(getKotlinFileInTestPackage(pkg, "base"))
+ .compile();
+ kotlinBaseClasses.put(targetVersion, ktBaseClasses);
+ // Compile the feature Kotlin code with the base classes on classpath.
+ Path ktFeatureClasses =
+ kotlinc(KOTLINC, targetVersion)
+ .addClasspathFiles(ktBaseClasses)
+ .addSourceFiles(getKotlinFileInTestPackage(pkg, "feature"))
+ .compile();
+ kotlinFeatureClasses.put(targetVersion, ktFeatureClasses);
+ }
+ }
+
+ private void checkLambdaGroups(CodeInspector inspector) {
+ List<FoundClassSubject> lambdaGroups =
+ inspector.allClasses().stream()
+ .filter(clazz -> clazz.getOriginalName().contains("LambdaGroup"))
+ .collect(Collectors.toList());
+ assertEquals(1, lambdaGroups.size());
+ MethodSubject invokeMethod = lambdaGroups.get(0).uniqueMethodWithName("invoke");
+ assertThat(invokeMethod, isPresent());
+ // The lambda group has 2 captures which capture "Base".
+ assertEquals(
+ 2,
+ invokeMethod
+ .streamInstructions()
+ .filter(InstructionSubject::isCheckCast)
+ .filter(
+ instruction ->
+ instruction.asCheckCast().getType().toSourceString().contains("Base"))
+ .count());
+ // The lambda group has no captures which capture "Feature" (lambdas in the feature are not
+ // in this lambda group).
+ assertTrue(
+ invokeMethod
+ .streamInstructions()
+ .filter(InstructionSubject::isCheckCast)
+ .noneMatch(
+ instruction ->
+ instruction.asCheckCast().getType().toSourceString().contains("Feature")));
+ }
+
+ @Test
+ public void test() throws Exception {
+ Path featureCode = temp.newFile("feature.zip").toPath();
+ R8TestCompileResult compileResult =
+ testForR8(parameters.getBackend())
+ .addProgramFiles(ToolHelper.getKotlinStdlibJar())
+ .addProgramFiles(kotlinBaseClasses.get(targetVersion))
+ .addProgramClasses(FeatureAPI.class)
+ .addKeepMainRule(baseKtClassName)
+ .addKeepClassAndMembersRules(baseClassName)
+ .addKeepClassAndMembersRules(featureKtClassNamet)
+ .addKeepClassAndMembersRules(FeatureAPI.class)
+ .setMinApi(parameters.getApiLevel())
+ .noMinification() // The check cast inspection above relies on original names.
+ .addFeatureSplit(
+ builder ->
+ builder
+ .addProgramResourceProvider(
+ ArchiveResourceProvider.fromArchive(
+ kotlinFeatureClasses.get(targetVersion), true))
+ .setProgramConsumer(new ArchiveConsumer(featureCode, false))
+ .build())
+ .allowDiagnosticWarningMessages()
+ .compile()
+ .assertAllWarningMessagesMatch(
+ equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))
+ .inspect(this::checkLambdaGroups);
+
+ // Run the code without the feature code present.
+ compileResult
+ .run(parameters.getRuntime(), baseKtClassName)
+ .assertSuccessWithOutputLines("1", "2");
+
+ // Run the code with the feature code present.
+ compileResult
+ .addRunClasspathFiles(featureCode)
+ .run(parameters.getRuntime(), baseKtClassName)
+ .assertSuccessWithOutputLines("1", "2", "3", "4");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/FeatureAPI.java b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/FeatureAPI.java
new file mode 100644
index 0000000..95bc790
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/FeatureAPI.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.kotlin.lambda.b148525512;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class FeatureAPI {
+ public static boolean hasFeature() {
+ try {
+ Class.forName(FeatureAPI.class.getPackage().getName() + ".FeatureKt");
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ return true;
+ }
+
+ public static void feature(int i)
+ throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
+ IllegalAccessException {
+ Class<?> featureKtClass = Class.forName(FeatureAPI.class.getPackage().getName() + ".FeatureKt");
+ Method featureMethod = featureKtClass.getMethod("feature", int.class);
+ featureMethod.invoke(null, i);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/base.kt b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/base.kt
new file mode 100644
index 0000000..aced216
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/base.kt
@@ -0,0 +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.kotlin.lambda.b148525512
+
+fun printInt(l: () -> Int ) = println(l())
+
+open class Base(@JvmField var x: Int, @JvmField var y: Int)
+
+fun main(args: Array<String>) {
+ val base = Base(args.size + 1, args.size + 2)
+ printInt { base.x }
+ printInt { base.y }
+ if (FeatureAPI.hasFeature()) {
+ FeatureAPI.feature(args.size + 3)
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/feature.kt b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/feature.kt
new file mode 100644
index 0000000..3480225
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/lambda/b148525512/feature.kt
@@ -0,0 +1,13 @@
+// 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.kotlin.lambda.b148525512
+
+class Feature(x: Int, y: Int) : Base(x, y)
+
+fun feature(i: Int) {
+ val f = Feature(i, i + 1)
+ printInt { f.x }
+ printInt { f.y }
+}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java
index 16385b4..f77cdb9 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInCompanionTest.java
@@ -94,6 +94,8 @@
.addProgramFiles(companionLibJarMap.get(targetVersion))
// Keep the B class and its interface (which has the doStuff method).
.addKeepRules("-keep class **.B")
+ // Property in companion with @JvmField is defined in the host class, without accessors.
+ .addKeepRules("-keepclassmembers class **.B { *** elt2; }")
.addKeepRules("-keep class **.I { <methods>; }")
// Keep getters for B$Companion.(eltN|foo) which will be referenced at the app.
.addKeepRules("-keepclassmembers class **.B$* { *** get*(...); }")
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java
index ec9cdc7..54675ca 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithDefaultValueTest.java
@@ -10,7 +10,9 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
@@ -21,10 +23,12 @@
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.KmFunctionSubject;
import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
+import com.android.tools.r8.utils.codeinspector.KmValueParameterSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -91,7 +95,7 @@
assertThat(
kotlinTestCompileResult.stderr, containsString("but java.util.Map<K, V> was expected"));
assertThat(
- kotlinTestCompileResult.stderr, containsString("no value passed for parameter 'p2'"));
+ kotlinTestCompileResult.stderr, not(containsString("no value passed for parameter 'p2'")));
}
private void inspect(CodeInspector inspector) {
@@ -114,7 +118,11 @@
KmFunctionSubject kmFunction = kmPackage.kmFunctionExtensionWithUniqueName("applyMap");
assertThat(kmFunction, isExtensionFunction());
- // TODO(b/70169921): inspect 2nd arg has flag that says it has a default value.
- // https://github.com/JetBrains/kotlin/blob/master/libraries/kotlinx-metadata/src/kotlinx/metadata/Flag.kt#L455
+ List<KmValueParameterSubject> valueParameters = kmFunction.valueParameters();
+ assertEquals(2, valueParameters.size());
+ // TODO(b/70169921): inspect 1st arg is Map with correct type parameter.
+ KmValueParameterSubject valueParameter = valueParameters.get(1);
+ assertTrue(valueParameter.declaresDefaultValue());
+ assertEquals("Lkotlin/String;", valueParameter.type().descriptor());
}
}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java
index f4e79f3..1bf7552 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInFunctionWithVarargTest.java
@@ -10,7 +10,9 @@
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
@@ -20,10 +22,12 @@
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.KmFunctionSubject;
import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
+import com.android.tools.r8.utils.codeinspector.KmValueParameterSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -66,7 +70,7 @@
Path libJar =
testForR8(parameters.getBackend())
.addProgramFiles(varargLibJarMap.get(targetVersion))
- // keep SomClass#foo, since there is a method reference in the app.
+ // keep SomeClass#foo, since there is a method reference in the app.
.addKeepRules("-keep class **.SomeClass { *** foo(...); }")
// Keep LibKt, along with bar function.
.addKeepRules("-keep class **.LibKt { *** bar(...); }")
@@ -87,7 +91,8 @@
assertNotEquals(0, kotlinTestCompileResult.exitCode);
assertThat(
kotlinTestCompileResult.stderr,
- containsString("type mismatch: inferred type is String but Array<T> was expected"));
+ not(containsString("type mismatch: inferred type is String but Array<T> was expected")));
+ assertThat(kotlinTestCompileResult.stderr, containsString("unresolved reference: foo"));
}
private void inspect(CodeInspector inspector) {
@@ -115,6 +120,11 @@
KmFunctionSubject kmFunction = kmPackage.kmFunctionWithUniqueName("bar");
assertThat(kmFunction, not(isExtensionFunction()));
- // TODO(b/70169921): inspect 1st arg is `vararg`.
+ List<KmValueParameterSubject> valueParameters = kmFunction.valueParameters();
+ assertEquals(2, valueParameters.size());
+ KmValueParameterSubject valueParameter = valueParameters.get(0);
+ assertTrue(valueParameter.isVararg());
+ assertEquals("Lkotlin/String;", valueParameter.varargElementType().descriptor());
+ // TODO(b/70169921): inspect 2nd arg is lambda with correct type parameter.
}
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java
index d8b230d..34abe12 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInPropertyTest.java
@@ -9,6 +9,8 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -18,8 +20,10 @@
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import com.android.tools.r8.utils.codeinspector.FieldSubject;
import com.android.tools.r8.utils.codeinspector.KmClassSubject;
import com.android.tools.r8.utils.codeinspector.KmPropertySubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
@@ -85,7 +89,7 @@
.addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
.addClasspath(output)
.run(parameters.getRuntime(), PKG + ".fragile_property_only_getter.Getter_userKt")
- .assertSuccessWithOutputLines("true", "false", "Hey");
+ .assertSuccessWithOutputLines("true", "false", "Hey Jude");
}
private void inspectGetterOnly(CodeInspector inspector) {
@@ -94,6 +98,14 @@
assertThat(person, isPresent());
assertThat(person, not(isRenamed()));
+ FieldSubject backingField = person.uniqueFieldWithName("name");
+ assertThat(backingField, isRenamed());
+ MethodSubject getterForName = person.uniqueMethodWithName("getName");
+ assertThat(getterForName, isPresent());
+ assertThat(getterForName, not(isRenamed()));
+ MethodSubject setterForName = person.uniqueMethodWithName("setName");
+ assertThat(setterForName, not(isPresent()));
+
// API entry is kept, hence the presence of Metadata.
KmClassSubject kmClass = person.getKmClass();
assertThat(kmClass, isPresent());
@@ -101,8 +113,12 @@
KmPropertySubject name = kmClass.kmPropertyWithUniqueName("name");
assertThat(name, isPresent());
assertThat(name, not(isExtensionProperty()));
+ // Property name is not renamed, due to the kept getter.
+ assertEquals("name", name.name());
assertNotNull(name.fieldSignature());
+ assertEquals(backingField.getJvmFieldSignatureAsString(), name.fieldSignature().asString());
assertNotNull(name.getterSignature());
+ assertEquals(getterForName.getJvmMethodSignatureAsString(), name.getterSignature().asString());
assertNull(name.setterSignature());
KmPropertySubject familyName = kmClass.kmPropertyWithUniqueName("familyName");
@@ -159,6 +175,7 @@
ClassSubject person = inspector.clazz(personClassName);
assertThat(person, isPresent());
assertThat(person, not(isRenamed()));
+
// API entry is kept, hence the presence of Metadata.
KmClassSubject kmClass = person.getKmClass();
assertThat(kmClass, isPresent());
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java
index b643c4b..57cd84c 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/MetadataRewriteInSealedClassTest.java
@@ -148,7 +148,8 @@
ProcessResult kotlinTestCompileResult =
kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
.addClasspathFiles(libJar)
- .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/sealed_app", "invalid"))
+ .addSourceFilesWithNonKtExtension(
+ temp, getFileInTest(PKG_PREFIX + "/sealed_app", "invalid.kt_txt"))
.setOutputPath(temp.newFolder().toPath())
.compileRaw();
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/fragile_property_only_getter/getter_user.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/fragile_property_only_getter/getter_user.kt
index b85bd2e..b3aba2e 100644
--- a/src/test/java/com/android/tools/r8/kotlin/metadata/fragile_property_only_getter/getter_user.kt
+++ b/src/test/java/com/android/tools/r8/kotlin/metadata/fragile_property_only_getter/getter_user.kt
@@ -11,5 +11,5 @@
println(x.canDrink)
println(x.married)
- println(y.firstName)
+ println(y.name)
}
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/kotlin/metadata/sealed_app/invalid.kt b/src/test/java/com/android/tools/r8/kotlin/metadata/sealed_app/invalid.kt_txt
similarity index 100%
rename from src/test/java/com/android/tools/r8/kotlin/metadata/sealed_app/invalid.kt
rename to src/test/java/com/android/tools/r8/kotlin/metadata/sealed_app/invalid.kt_txt
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 3f8c11f..03ab057 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -830,7 +830,7 @@
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
code);
- AppView<?> appView = AppView.createForR8(null, options);
+ AppView<?> appView = AppView.createForR8(appInfo, options);
IRCode ir = code.buildIR(method, appView, Origin.unknown());
RegisterAllocator allocator = new LinearScanRegisterAllocator(appView, ir);
method.setCode(ir, allocator, appView);
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLibraryMemberRenamingTests.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLibraryMemberRenamingTests.java
index 0e5e1c6..26873f4 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLibraryMemberRenamingTests.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLibraryMemberRenamingTests.java
@@ -63,7 +63,7 @@
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().build();
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
public ApplyMappingLibraryMemberRenamingTests(TestParameters parameters) {
@@ -78,7 +78,7 @@
.addProgramClasses(Dto.class, Interface.class, Main.class)
.addKeepClassAndMembersRules(Main.class)
.addKeepClassAndMembersRulesWithAllowObfuscation(Interface.class, Dto.class)
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.compile()
.inspect(
codeInspector -> {
@@ -93,7 +93,7 @@
.addClasspathClasses(Dto.class, Interface.class, Main.class)
.addKeepAllClassesRule()
.addApplyMapping(libraryCompileResult.getProguardMap())
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.compile()
.addRunClasspathFiles(libraryCompileResult.writeToZip())
.run(parameters.getRuntime(), ClientTest.class)
diff --git a/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
index 8034ad7..079a8f5 100644
--- a/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/ArrayTargetLookupTest.java
@@ -44,7 +44,7 @@
factory.createType(DescriptorUtils.javaTypeToDescriptor(Foo.class.getTypeName()));
DexType[] arrayTypes =
new DexType[] {
- factory.createType("[I"),
+ factory.intArrayType,
factory.stringArrayType,
factory.objectArrayType,
factory.createArrayType(2, fooType)
diff --git a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
index 45a9a20..ba27c33 100644
--- a/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/SingleTargetLookupTest.java
@@ -7,9 +7,11 @@
import com.android.tools.r8.AsmTestBase;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.resolution.singletarget.Main;
import com.android.tools.r8.resolution.singletarget.one.AbstractSubClass;
@@ -43,9 +45,9 @@
@RunWith(Parameterized.class)
public class SingleTargetLookupTest extends AsmTestBase {
- /**
- * Initialized in @Before rule.
- */
+ /** Initialized in @Before rule. */
+ public static AppView<AppInfoWithLiveness> appView;
+
public static AppInfoWithLiveness appInfo;
public static List<Class<?>> CLASSES =
@@ -83,9 +85,8 @@
@BeforeClass
public static void computeAppInfo() throws Exception {
- appInfo =
- computeAppViewWithLiveness(readClassesAndAsmDump(CLASSES, ASM_CLASSES), Main.class)
- .appInfo();
+ appView = computeAppViewWithLiveness(readClassesAndAsmDump(CLASSES, ASM_CLASSES), Main.class);
+ appInfo = appView.appInfo();
}
private static Object[] singleTarget(String name, Class<?> receiverAndTarget) {
@@ -222,7 +223,9 @@
appInfo.resolveMethod(toType(invokeReceiver, appInfo), method).getSingleTarget());
ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
if (resolutionResult.isVirtualTarget()) {
- Set<DexEncodedMethod> targets = resolutionResult.lookupVirtualDispatchTargets(appInfo);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView, appInfo);
+ assertTrue(lookupResult.isLookupResultSuccess());
+ Set<DexEncodedMethod> targets = lookupResult.asLookupResultSuccess().getMethodTargets();
Set<DexType> targetHolders =
targets.stream().map(m -> m.method.holder).collect(Collectors.toSet());
Assert.assertEquals(allTargetHolders.size(), targetHolders.size());
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodAsOverrideWithLambdaTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodAsOverrideWithLambdaTest.java
index b119874..3fcc33d 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodAsOverrideWithLambdaTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodAsOverrideWithLambdaTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.interfacetargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -48,18 +51,23 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "bar", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
- ImmutableSet.of(A.class.getTypeName() + ".bar", J.class.getTypeName() + ".bar");
+ ImmutableSet.of(
+ I.class.getTypeName() + ".bar",
+ A.class.getTypeName() + ".bar",
+ J.class.getTypeName() + ".bar");
assertEquals(expected, targets);
}
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodLambdaTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodLambdaTest.java
index f926d4b..bdd5dd3 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodLambdaTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultMethodLambdaTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.interfacetargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -47,13 +50,15 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
- computeAppViewWithLiveness(buildClasses(I.class, A.class, Main.class).build(), Main.class)
- .appInfo();
+ AppView<AppInfoWithLiveness> appView =
+ computeAppViewWithLiveness(buildClasses(I.class, A.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "bar", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
index 61e872e..266cb48 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/DefaultWithoutTopTest.java
@@ -6,6 +6,7 @@
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.CompilationFailedException;
@@ -15,8 +16,11 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
@@ -47,16 +51,19 @@
@Test
public void testDynamicLookupTargets() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, J.class, Main.class)
- .addClassProgramData(setAImplementsIAndJ())
- .build(),
- Main.class)
- .appInfo();
+ buildClasses(I.class, J.class, Main.class)
+ .addClassProgramData(setAImplementsIAndJ())
+ .build(),
+ Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
@@ -84,18 +91,21 @@
}
@Test
- public void testtestDynamicLookupTargetsWithIndirectDefault() throws Exception {
+ public void testDynamicLookupTargetsWithIndirectDefault() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, J.class, K.class, Main.class)
- .addClassProgramData(setAimplementsIandK())
- .build(),
- Main.class)
- .appInfo();
+ buildClasses(I.class, J.class, K.class, Main.class)
+ .addClassProgramData(setAimplementsIandK())
+ .build(),
+ Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
index a69a18b..2614319 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceClInitTest.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.TestRuntime.DexRuntime;
import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.transformers.ClassTransformer;
@@ -49,19 +50,17 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(A.class, B.class)
- .addClassProgramData(transformI(), transformMain())
- .build(),
- Main.class)
- .appInfo();
+ buildClasses(A.class, B.class)
+ .addClassProgramData(transformI(), transformMain())
+ .build(),
+ Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "<clinit>", appInfo.dexItemFactory());
Assert.assertThrows(
AssertionError.class,
- () -> {
- appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo);
- });
+ () -> appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appView));
}
private Matcher<String> getExpected() {
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
index 3b6022b..1ca966b 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/InvokeInterfaceWithStaticTargetTest.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -42,15 +43,15 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.getRuntime().equals(TestRuntime.getDefaultJavaRuntime()));
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(A.class, I.class).addClassProgramData(transformMain()).build(),
- Main.class)
- .appInfo();
+ buildClasses(A.class, I.class).addClassProgramData(transformMain()).build(),
+ Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "bar", appInfo.dexItemFactory());
Assert.assertThrows(
AssertionError.class,
- () -> appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo));
+ () -> appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appView));
}
@Test
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/LambdaMultipleInterfacesTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/LambdaMultipleInterfacesTest.java
index 88fd988..251fa37 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/LambdaMultipleInterfacesTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/LambdaMultipleInterfacesTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.interfacetargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -47,14 +50,16 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(J.class, "bar", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/MultipleImplementsTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/MultipleImplementsTest.java
index 23c2215..eff0088 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/MultipleImplementsTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/MultipleImplementsTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.interfacetargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -47,14 +50,16 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SimpleInterfaceInvokeTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SimpleInterfaceInvokeTest.java
index 03a6141..9552212 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SimpleInterfaceInvokeTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SimpleInterfaceInvokeTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.interfacetargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -48,14 +51,16 @@
public void testResolution() throws Exception {
// The resolution is runtime independent, so just run it on the default CF VM.
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, A.class, B.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, A.class, B.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubInterfaceOverridesTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubInterfaceOverridesTest.java
index e73a10e..41d4879 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubInterfaceOverridesTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubInterfaceOverridesTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.interfacetargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -13,8 +14,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -46,15 +49,17 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, J.class, A.class, B.class, C.class, Main.class).build(),
- Main.class)
- .appInfo();
+ buildClasses(I.class, J.class, A.class, B.class, C.class, Main.class).build(),
+ Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeMissingOverridesTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeMissingOverridesTest.java
index 24916b0..84236e5 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeMissingOverridesTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeMissingOverridesTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.interfacetargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -13,8 +14,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -46,14 +49,16 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeOverridesTest.java b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeOverridesTest.java
index a9b34f2..a952bb3 100644
--- a/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeOverridesTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/interfacetargets/SubTypeOverridesTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.interfacetargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -13,8 +14,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -46,14 +49,16 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, A.class, B.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, A.class, B.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethodOnInterface(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java
new file mode 100644
index 0000000..f465727
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryTest.java
@@ -0,0 +1,114 @@
+// 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.resolution.packageprivate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.resolution.packageprivate.a.A;
+import com.android.tools.r8.resolution.packageprivate.a.A.B;
+import com.android.tools.r8.resolution.packageprivate.a.D;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+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 PackagePrivateReentryTest extends TestBase {
+
+ private final TestParameters parameters;
+ private static final String[] EXPECTED = new String[] {"D.foo", "D.bar", "D.foo", "D.bar"};
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public PackagePrivateReentryTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testResolution() throws Exception {
+ assumeTrue(parameters.useRuntimeAsNoneRuntime());
+ AppView<AppInfoWithLiveness> appView =
+ computeAppViewWithLiveness(
+ buildClasses(A.class, B.class, C.class, D.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
+ DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
+ Set<String> targets =
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
+ .map(DexEncodedMethod::qualifiedName)
+ .collect(Collectors.toSet());
+ // TODO(b/149363086): Fix expection, should not include C.bar().
+ ImmutableSet<String> expected =
+ ImmutableSet.of(
+ A.class.getTypeName() + ".bar",
+ B.class.getTypeName() + ".bar",
+ C.class.getTypeName() + ".bar",
+ D.class.getTypeName() + ".bar");
+ assertEquals(expected, targets);
+ }
+
+ @Test
+ public void testRuntime() throws ExecutionException, CompilationFailedException, IOException {
+ TestRunResult<?> runResult =
+ testForRuntime(parameters)
+ .addProgramClasses(A.class, B.class, C.class, D.class, Main.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws ExecutionException, CompilationFailedException, IOException {
+ testForR8(parameters.getBackend())
+ .addProgramClasses(A.class, B.class, C.class, D.class, Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ public static class C extends B {
+ @Override
+ public void foo() {
+ System.out.println("C.foo");
+ }
+
+ public void bar() {
+ System.out.println("C.bar");
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ D d = new D();
+ A.run(d);
+ d.foo();
+ d.bar();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java
new file mode 100644
index 0000000..35791e7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateReentryWithNarrowingTest.java
@@ -0,0 +1,123 @@
+// 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.resolution.packageprivate;
+
+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.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.resolution.packageprivate.PackagePrivateReentryTest.C;
+import com.android.tools.r8.resolution.packageprivate.a.A;
+import com.android.tools.r8.resolution.packageprivate.a.A.B;
+import com.android.tools.r8.resolution.packageprivate.a.D;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+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 PackagePrivateReentryWithNarrowingTest extends TestBase {
+
+ private final TestParameters parameters;
+ private static final String[] EXPECTED = new String[] {"D.foo", "D.bar", "D.foo", "D.bar"};
+ private static final String[] EXPECTED_ART = new String[] {"D.foo", "D.bar", "D.foo", "C.bar"};
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public PackagePrivateReentryWithNarrowingTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testResolution() throws Exception {
+ assumeTrue(parameters.useRuntimeAsNoneRuntime());
+ AppView<AppInfoWithLiveness> appView =
+ computeAppViewWithLiveness(
+ buildClasses(A.class, B.class, C.class, D.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
+ DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
+ Set<String> targets =
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
+ .map(DexEncodedMethod::qualifiedName)
+ .collect(Collectors.toSet());
+ // TODO(b/149363086): Fix expection, should not include C.bar().
+ ImmutableSet<String> expected =
+ ImmutableSet.of(
+ A.class.getTypeName() + ".bar",
+ B.class.getTypeName() + ".bar",
+ C.class.getTypeName() + ".bar",
+ D.class.getTypeName() + ".bar");
+ assertEquals(expected, targets);
+ }
+
+ @Test
+ public void testRuntime()
+ throws ExecutionException, CompilationFailedException, IOException, NoSuchMethodException {
+ TestRunResult<?> runResult =
+ testForRuntime(parameters)
+ .addProgramClasses(A.class, B.class, C.class, Main.class)
+ .addProgramClassFileData(getDWithPackagePrivateFoo())
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.isCfRuntime()
+ || parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_TARGET)) {
+ runResult.assertSuccessWithOutputLines(EXPECTED);
+ } else {
+ runResult.assertSuccessWithOutputLines(EXPECTED_ART);
+ }
+ }
+
+ @Test
+ public void testR8()
+ throws ExecutionException, CompilationFailedException, IOException, NoSuchMethodException {
+ // TODO(b/149363086): Fix test.
+ testForR8(parameters.getBackend())
+ .addProgramClasses(A.class, B.class, C.class, Main.class)
+ .addProgramClassFileData(getDWithPackagePrivateFoo())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertFailureWithErrorThatMatches(containsString("IllegalAccessError"));
+ }
+
+ private byte[] getDWithPackagePrivateFoo() throws NoSuchMethodException, IOException {
+ return transformer(D.class)
+ .setAccessFlags(D.class.getDeclaredMethod("bar", null), m -> m.unsetPublic())
+ .transform();
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ C d = (C) ((Object) new D());
+ A.run(d);
+ d.foo();
+ d.bar();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java
new file mode 100644
index 0000000..c2d041c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/PackagePrivateWithDefaultMethodTest.java
@@ -0,0 +1,149 @@
+// 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.resolution.packageprivate;
+
+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.CompilationFailedException;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.resolution.packageprivate.a.Abstract;
+import com.android.tools.r8.resolution.packageprivate.a.I;
+import com.android.tools.r8.resolution.packageprivate.a.J;
+import com.android.tools.r8.resolution.packageprivate.a.NonAbstract;
+import com.android.tools.r8.resolution.packageprivate.a.NonAbstractExtendingA;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.transformers.ClassTransformer;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.objectweb.asm.MethodVisitor;
+
+@RunWith(Parameterized.class)
+public class PackagePrivateWithDefaultMethodTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public PackagePrivateWithDefaultMethodTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testResolution() throws Exception {
+ assumeTrue(parameters.useRuntimeAsNoneRuntime());
+ AppView<AppInfoWithLiveness> appView =
+ computeAppViewWithLiveness(
+ buildClasses(
+ Abstract.class,
+ I.class,
+ A.class,
+ NonAbstractExtendingA.class,
+ J.class,
+ Main.class)
+ .addClassProgramData(getNonAbstractWithoutDeclaredMethods())
+ .build(),
+ Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
+ DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
+ Set<String> targets =
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
+ .map(DexEncodedMethod::qualifiedName)
+ .collect(Collectors.toSet());
+ // TODO(b/148591377): The set should be empty.
+ ImmutableSet<String> expected = ImmutableSet.of(Abstract.class.getTypeName() + ".foo");
+ assertEquals(expected, targets);
+ }
+
+ @Test
+ public void testRuntime() throws ExecutionException, CompilationFailedException, IOException {
+ TestRunResult<?> runResult =
+ testForRuntime(parameters)
+ .addProgramClasses(
+ Abstract.class, I.class, A.class, NonAbstractExtendingA.class, J.class, Main.class)
+ .addProgramClassFileData(getNonAbstractWithoutDeclaredMethods())
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.isDexRuntime()
+ && parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_TARGET)) {
+ runResult.assertFailure();
+ } else {
+ runResult.assertFailureWithErrorThatMatches(containsString("AbstractMethodError"));
+ }
+ }
+
+ @Test
+ public void testR8() throws ExecutionException, CompilationFailedException, IOException {
+ R8TestRunResult runResult =
+ testForR8(parameters.getBackend())
+ .addProgramClasses(
+ Abstract.class, I.class, A.class, NonAbstractExtendingA.class, J.class, Main.class)
+ .addProgramClassFileData(getNonAbstractWithoutDeclaredMethods())
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.isDexRuntime()
+ && parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_TARGET)) {
+ runResult.assertFailure();
+ } else {
+ runResult.assertFailureWithErrorThatMatches(containsString("AbstractMethodError"));
+ }
+ }
+
+ private byte[] getNonAbstractWithoutDeclaredMethods() throws IOException {
+ return transformer(NonAbstract.class)
+ .addClassTransformer(
+ new ClassTransformer() {
+ @Override
+ public MethodVisitor visitMethod(
+ int access,
+ String name,
+ String descriptor,
+ String signature,
+ String[] exceptions) {
+ if (!name.equals("foo")) {
+ return super.visitMethod(access, name, descriptor, signature, exceptions);
+ }
+ return null;
+ }
+ })
+ .transform();
+ }
+
+ public static class A extends NonAbstract {}
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ NonAbstractExtendingA d = new NonAbstractExtendingA();
+ Abstract.run(d);
+ d.foo();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java
new file mode 100644
index 0000000..28c8c2f
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/WidenAccessOutsidePackageTest.java
@@ -0,0 +1,120 @@
+// 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.resolution.packageprivate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.TestRunResult;
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
+import com.android.tools.r8.resolution.packageprivate.a.A;
+import com.android.tools.r8.resolution.packageprivate.a.A.B;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+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 WidenAccessOutsidePackageTest extends TestBase {
+
+ private final TestParameters parameters;
+ private static final String[] EXPECTED = new String[] {"C.foo", "B.bar", "C.foo", "C.bar"};
+ private static final String[] EXPECTED_DALVIK = new String[] {"C.foo", "C.bar", "C.foo", "C.bar"};
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public WidenAccessOutsidePackageTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testResolution() throws Exception {
+ assumeTrue(parameters.useRuntimeAsNoneRuntime());
+ AppView<AppInfoWithLiveness> appView =
+ computeAppViewWithLiveness(
+ buildClasses(A.class, B.class, C.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
+ DexMethod method = buildNullaryVoidMethod(A.class, "bar", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
+ Set<String> targets =
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
+ .map(DexEncodedMethod::qualifiedName)
+ .collect(Collectors.toSet());
+ // TODO(b/149363086): Fix expectation.
+ ImmutableSet<String> expected =
+ ImmutableSet.of(
+ A.class.getTypeName() + ".bar",
+ B.class.getTypeName() + ".bar",
+ C.class.getTypeName() + ".bar");
+ assertEquals(expected, targets);
+ }
+
+ @Test
+ public void testRuntime() throws ExecutionException, CompilationFailedException, IOException {
+ TestRunResult<?> runResult =
+ testForRuntime(parameters)
+ .addProgramClasses(A.class, B.class, C.class, Main.class)
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.isDexRuntime()
+ && parameters.getRuntime().asDex().getVm().isOlderThanOrEqual(DexVm.ART_4_4_4_TARGET)) {
+ runResult.assertSuccessWithOutputLines(EXPECTED_DALVIK);
+ } else {
+ runResult.assertSuccessWithOutputLines(EXPECTED);
+ }
+ }
+
+ @Test
+ public void testR8() throws ExecutionException, CompilationFailedException, IOException {
+ // TODO(b/149363086): Fix expectation.
+ testForR8(parameters.getBackend())
+ .addProgramClasses(A.class, B.class, C.class, Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .addKeepMainRule(Main.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED_DALVIK);
+ }
+
+ public static class C extends B {
+ @Override
+ public void foo() {
+ System.out.println("C.foo");
+ }
+
+ public void bar() {
+ System.out.println("C.bar");
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ C c = new C();
+ A.run(c);
+ c.foo();
+ c.bar();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/A.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/A.java
new file mode 100644
index 0000000..8154e21
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/A.java
@@ -0,0 +1,34 @@
+// 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.resolution.packageprivate.a;
+
+public class A {
+
+ protected void foo() {
+ System.out.println("A.foo");
+ }
+
+ void bar() {
+ System.out.println("A.bar");
+ }
+
+ public static class B extends A {
+
+ @Override
+ protected void foo() {
+ System.out.println("B.foo");
+ }
+
+ @Override
+ void bar() {
+ System.out.println("B.bar");
+ }
+ }
+
+ public static void run(A a) {
+ a.foo();
+ a.bar();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/Abstract.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/Abstract.java
new file mode 100644
index 0000000..bd4f5b2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/Abstract.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.resolution.packageprivate.a;
+
+public abstract class Abstract {
+
+ abstract void foo();
+
+ public static void run(Abstract a) {
+ a.foo();
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/D.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/D.java
new file mode 100644
index 0000000..1d7c54e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/D.java
@@ -0,0 +1,19 @@
+// 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.resolution.packageprivate.a;
+
+import com.android.tools.r8.resolution.packageprivate.PackagePrivateReentryTest.C;
+
+public class D extends C {
+ @Override
+ public void foo() {
+ System.out.println("D.foo");
+ }
+
+ @Override
+ public void bar() {
+ System.out.println("D.bar");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/I.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/I.java
new file mode 100644
index 0000000..a510f12
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/I.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.resolution.packageprivate.a;
+
+public interface I {
+
+ default void foo() {
+ System.out.println("I.foo");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/J.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/J.java
new file mode 100644
index 0000000..6f3d327
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/J.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.resolution.packageprivate.a;
+
+public interface J {
+
+ default void foo() {
+ System.out.println("J.foo");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstract.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstract.java
new file mode 100644
index 0000000..75e25a5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstract.java
@@ -0,0 +1,13 @@
+// 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.resolution.packageprivate.a;
+
+public class NonAbstract extends Abstract implements I {
+
+ @Override
+ public void foo() {
+ System.out.println("Method declaration will be removed");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstractExtendingA.java b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstractExtendingA.java
new file mode 100644
index 0000000..4478062
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/resolution/packageprivate/a/NonAbstractExtendingA.java
@@ -0,0 +1,9 @@
+// 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.resolution.packageprivate.a;
+
+import com.android.tools.r8.resolution.packageprivate.PackagePrivateWithDefaultMethodTest;
+
+public class NonAbstractExtendingA extends PackagePrivateWithDefaultMethodTest.A implements J {}
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
index 8a52035..9538dec 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/AbstractInMiddleTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.virtualtargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
@@ -46,13 +50,16 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(A.class, B.class, C.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(A.class, B.class, C.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
// TODO(b/148591377): Should we report B.foo()?
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
index 34b536b..4133fbe 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceSubTypeTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.virtualtargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
@@ -46,13 +50,16 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, J.class, A.class, B.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, J.class, A.class, B.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
// TODO(b/148591377): I.foo() should ideally not be included in the set.
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
index 399ad7d..264ddb0 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultInterfaceMethodInSubInterfaceTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.virtualtargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
@@ -46,13 +50,16 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, J.class, A.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
index 4759dc3..ff58047 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/DefaultWithoutTopTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.virtualtargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
@@ -46,16 +50,19 @@
@Test
public void testDynamicLookupTargets() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, J.class, Main.class)
- .addClassProgramData(setAImplementsIAndJ())
- .build(),
- Main.class)
- .appInfo();
+ buildClasses(I.class, J.class, Main.class)
+ .addClassProgramData(setAImplementsIAndJ())
+ .build(),
+ Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected = ImmutableSet.of(J.class.getTypeName() + ".foo");
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
index ebbfcef..055c113 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/InvokeVirtualToInterfaceDefinitionTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.virtualtargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,11 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
+import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
@@ -46,12 +50,15 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
- computeAppViewWithLiveness(buildClasses(A.class, I.class, Main.class).build(), Main.class)
- .appInfo();
+ AppView<AppInfoWithLiveness> appView =
+ computeAppViewWithLiveness(buildClasses(A.class, I.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(A.class, "foo", appInfo.dexItemFactory());
+ ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- appInfo.resolveMethod(method.holder, method).lookupVirtualDispatchTargets(appInfo).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected = ImmutableSet.of(I.class.getTypeName() + ".foo");
diff --git a/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java b/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
index e4d1f55..570527c 100644
--- a/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
+++ b/src/test/java/com/android/tools/r8/resolution/virtualtargets/TargetInDefaultMethodTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.resolution.virtualtargets;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import com.android.tools.r8.CompilationFailedException;
@@ -14,8 +15,10 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.LookupResult;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.ImmutableSet;
@@ -47,14 +50,16 @@
@Test
public void testResolution() throws Exception {
assumeTrue(parameters.useRuntimeAsNoneRuntime());
- AppInfoWithLiveness appInfo =
+ AppView<AppInfoWithLiveness> appView =
computeAppViewWithLiveness(
- buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class)
- .appInfo();
+ buildClasses(I.class, A.class, B.class, C.class, Main.class).build(), Main.class);
+ AppInfoWithLiveness appInfo = appView.appInfo();
DexMethod method = buildNullaryVoidMethod(I.class, "foo", appInfo.dexItemFactory());
ResolutionResult resolutionResult = appInfo.resolveMethod(method.holder, method);
+ LookupResult lookupResult = resolutionResult.lookupVirtualDispatchTargets(appView);
+ assertTrue(lookupResult.isLookupResultSuccess());
Set<String> targets =
- resolutionResult.lookupVirtualDispatchTargets(appInfo.withSubtyping()).stream()
+ lookupResult.asLookupResultSuccess().getMethodTargets().stream()
.map(DexEncodedMethod::qualifiedName)
.collect(Collectors.toSet());
ImmutableSet<String> expected =
diff --git a/src/test/java/com/android/tools/r8/shaking/addconfigurationdebugging/B133167042.java b/src/test/java/com/android/tools/r8/shaking/addconfigurationdebugging/B133167042.java
index 725fe66..3971997 100644
--- a/src/test/java/com/android/tools/r8/shaking/addconfigurationdebugging/B133167042.java
+++ b/src/test/java/com/android/tools/r8/shaking/addconfigurationdebugging/B133167042.java
@@ -31,7 +31,7 @@
@Parameters(name = "{0}")
public static TestParametersCollection data() {
- return getTestParameters().withAllRuntimes().build();
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
}
private final TestParameters parameters;
@@ -46,7 +46,7 @@
.addProgramClasses(TestClass.class)
.addKeepMainRule(TestClass.class)
.addKeepRules("-addconfigurationdebugging")
- .setMinApi(parameters.getRuntime())
+ .setMinApi(parameters.getApiLevel())
.run(parameters.getRuntime(), TestClass.class)
.assertSuccessWithOutput(StringUtils.lines("false"));
}
diff --git a/src/test/java/com/android/tools/r8/shaking/annotations/ProgramAnnotationRemovalTest.java b/src/test/java/com/android/tools/r8/shaking/annotations/ProgramAnnotationRemovalTest.java
index 0cf779d..3396686 100644
--- a/src/test/java/com/android/tools/r8/shaking/annotations/ProgramAnnotationRemovalTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/annotations/ProgramAnnotationRemovalTest.java
@@ -67,12 +67,12 @@
MethodSubject methodWithLiveProgramAnnotationSubject =
testClassSubject.uniqueMethodWithName("methodWithLiveProgramAnnotation");
assertThat(methodWithLiveProgramAnnotationSubject, isPresent());
- assertEquals(1, methodWithLiveProgramAnnotationSubject.getMethod().annotations.size());
+ assertEquals(1, methodWithLiveProgramAnnotationSubject.getMethod().annotations().size());
MethodSubject methodWithDeadProgramAnnotationSubject =
testClassSubject.uniqueMethodWithName("methodWithDeadProgramAnnotation");
assertThat(methodWithDeadProgramAnnotationSubject, isPresent());
- assertEquals(0, methodWithDeadProgramAnnotationSubject.getMethod().annotations.size());
+ assertEquals(0, methodWithDeadProgramAnnotationSubject.getMethod().annotations().size());
result.assertSuccessWithOutputLines("@" + liveAnnotationClassSubject.getFinalName() + "()");
}
diff --git a/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesDotsTest.java b/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesDotsTest.java
index 58671ab..5a978c6 100644
--- a/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesDotsTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/attributes/KeepAttributesDotsTest.java
@@ -69,11 +69,11 @@
private void inspect(CodeInspector inspector) {
ClassSubject clazz = inspector.clazz(Main.class);
- assertTrue(clazz.getDexClass().annotations.isEmpty());
+ assertTrue(clazz.getDexClass().annotations().isEmpty());
MethodSubject main = clazz.uniqueMethodWithName("main");
- assertTrue(main.getMethod().annotations.isEmpty());
+ assertTrue(main.getMethod().annotations().isEmpty());
FieldSubject field = clazz.uniqueFieldWithName("field");
- assertTrue(field.getField().annotations.isEmpty());
+ assertTrue(field.getField().annotations().isEmpty());
assertTrue(clazz.getDexClass().sourceFile == null || clazz.getDexClass().sourceFile.size == 0);
assertNull(main.getLineNumberTable());
assertTrue(main.getLocalVariableTable().isEmpty());
diff --git a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
index 0c2358a..eb3929c 100644
--- a/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
+++ b/src/test/java/com/android/tools/r8/transformers/ClassFileTransformer.java
@@ -166,7 +166,7 @@
}
});
}
-
+
/** Unconditionally replace the descriptor (ie, qualified name) of a class. */
public ClassFileTransformer setClassDescriptor(String descriptor) {
assert DescriptorUtils.isClassDescriptor(descriptor);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentFieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentFieldSubject.java
index 20da5d0..f41135f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentFieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentFieldSubject.java
@@ -95,4 +95,9 @@
public AnnotationSubject annotation(String name) {
return new AbsentAnnotationSubject();
}
+
+ @Override
+ public String getJvmFieldSignatureAsString() {
+ return null;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java
index c72d305..5efcf6e 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmFunctionSubject.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils.codeinspector;
+import java.util.List;
import kotlinx.metadata.jvm.JvmMethodSignature;
public class AbsentKmFunctionSubject extends KmFunctionSubject {
@@ -38,6 +39,11 @@
}
@Override
+ public List<KmValueParameterSubject> valueParameters() {
+ return null;
+ }
+
+ @Override
public KmTypeSubject returnType() {
return null;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPropertySubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPropertySubject.java
index 70f6e52..d9c7d55 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPropertySubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentKmPropertySubject.java
@@ -29,6 +29,11 @@
}
@Override
+ public String name() {
+ return null;
+ }
+
+ @Override
public JvmFieldSignature fieldSignature() {
return null;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
index b3e5eec..e08c9b7 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/AbsentMethodSubject.java
@@ -132,4 +132,9 @@
public AnnotationSubject annotation(String name) {
return new AbsentAnnotationSubject();
}
+
+ @Override
+ public String getJvmMethodSignatureAsString() {
+ return null;
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastCfInstructionSubject.java
new file mode 100644
index 0000000..0f5c42c
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastCfInstructionSubject.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.utils.codeinspector;
+
+import com.android.tools.r8.cf.code.CfCheckCast;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.graph.DexType;
+
+public class CheckCastCfInstructionSubject extends CfInstructionSubject
+ implements CheckCastInstructionSubject {
+ public CheckCastCfInstructionSubject(CfInstruction instruction, MethodSubject method) {
+ super(instruction, method);
+ assert isCheckCast();
+ }
+
+ @Override
+ public DexType getType() {
+ return ((CfCheckCast) instruction).getType();
+ }
+
+ @Override
+ public CheckCastInstructionSubject asCheckCast() {
+ return this;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastDexInstructionSubject.java
new file mode 100644
index 0000000..ea10ad4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastDexInstructionSubject.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.utils.codeinspector;
+
+import com.android.tools.r8.code.CheckCast;
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.graph.DexType;
+
+public class CheckCastDexInstructionSubject extends DexInstructionSubject
+ implements CheckCastInstructionSubject {
+ public CheckCastDexInstructionSubject(Instruction instruction, MethodSubject method) {
+ super(instruction, method);
+ assert isCheckCast();
+ }
+
+ @Override
+ public DexType getType() {
+ return ((CheckCast) instruction).getType();
+ }
+
+ @Override
+ public CheckCastInstructionSubject asCheckCast() {
+ return this;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastInstructionSubject.java
new file mode 100644
index 0000000..e7fa916
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CheckCastInstructionSubject.java
@@ -0,0 +1,11 @@
+// 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.utils.codeinspector;
+
+import com.android.tools.r8.graph.DexType;
+
+public interface CheckCastInstructionSubject extends InstructionSubject {
+ DexType getType();
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 5e1e668..63c85d5 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -354,6 +354,8 @@
return new NewInstanceDexInstructionSubject(instruction, method);
} else if (dexInst.isConstString(JumboStringMode.ALLOW)) {
return new ConstStringDexInstructionSubject(instruction, method);
+ } else if (dexInst.isCheckCast()) {
+ return new CheckCastDexInstructionSubject(instruction, method);
} else {
return dexInst;
}
@@ -369,6 +371,8 @@
return new NewInstanceCfInstructionSubject(instruction, method);
} else if (cfInst.isConstString(JumboStringMode.ALLOW)) {
return new ConstStringCfInstructionSubject(instruction, method);
+ } else if (cfInst.isCheckCast()) {
+ return new CheckCastCfInstructionSubject(instruction, method);
} else {
return cfInst;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
index dc9940f..957e78a 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldSubject.java
@@ -34,4 +34,6 @@
public boolean isFieldSubject() {
return true;
}
+
+ public abstract String getJvmFieldSignatureAsString();
}
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 3e83c5d..c0dba89 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
@@ -230,7 +230,7 @@
assert !name.endsWith("EnclosingClass")
&& !name.endsWith("EnclosingMethod")
&& !name.endsWith("InnerClass");
- DexAnnotation annotation = codeInspector.findAnnotation(name, dexClass.annotations);
+ DexAnnotation annotation = codeInspector.findAnnotation(name, dexClass.annotations());
return annotation == null
? new AbsentAnnotationSubject()
: new FoundAnnotationSubject(annotation);
@@ -296,12 +296,12 @@
@Override
public String getOriginalSignatureAttribute() {
return codeInspector.getOriginalSignatureAttribute(
- dexClass.annotations, GenericSignatureParser::parseClassSignature);
+ dexClass.annotations(), GenericSignatureParser::parseClassSignature);
}
@Override
public String getFinalSignatureAttribute() {
- return codeInspector.getFinalSignatureAttribute(dexClass.annotations);
+ return codeInspector.getFinalSignatureAttribute(dexClass.annotations());
}
@Override
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
index 7c40d1e..411dad2 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
@@ -134,17 +134,17 @@
@Override
public String getOriginalSignatureAttribute() {
return codeInspector.getOriginalSignatureAttribute(
- dexField.annotations, GenericSignatureParser::parseFieldSignature);
+ dexField.annotations(), GenericSignatureParser::parseFieldSignature);
}
@Override
public String getFinalSignatureAttribute() {
- return codeInspector.getFinalSignatureAttribute(dexField.annotations);
+ return codeInspector.getFinalSignatureAttribute(dexField.annotations());
}
@Override
public AnnotationSubject annotation(String name) {
- DexAnnotation annotation = codeInspector.findAnnotation(name, dexField.annotations);
+ DexAnnotation annotation = codeInspector.findAnnotation(name, dexField.annotations());
return annotation == null
? new AbsentAnnotationSubject()
: new FoundAnnotationSubject(annotation);
@@ -154,4 +154,9 @@
public String toString() {
return dexField.toSourceString();
}
+
+ @Override
+ public String getJvmFieldSignatureAsString() {
+ return dexField.field.name.toString() + ":" + dexField.field.type.toDescriptorString();
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java
index 3bbf235..28eff88 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmFunctionSubject.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.utils.codeinspector;
import com.android.tools.r8.utils.codeinspector.FoundKmDeclarationContainerSubject.KmFunctionProcessor;
+import java.util.List;
+import java.util.stream.Collectors;
import kotlinx.metadata.KmFunction;
import kotlinx.metadata.KmType;
import kotlinx.metadata.jvm.JvmMethodSignature;
@@ -56,6 +58,13 @@
}
@Override
+ public List<KmValueParameterSubject> valueParameters() {
+ return kmFunction.getValueParameters().stream()
+ .map(KmValueParameterSubject::new)
+ .collect(Collectors.toList());
+ }
+
+ @Override
public KmTypeSubject returnType() {
return new KmTypeSubject(kmFunction.getReturnType());
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPropertySubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPropertySubject.java
index 4f9cc94..3cfe20d 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPropertySubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundKmPropertySubject.java
@@ -49,6 +49,11 @@
}
@Override
+ public String name() {
+ return kmProperty.getName();
+ }
+
+ @Override
public JvmFieldSignature fieldSignature() {
return fieldSignature;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 1051e28..fe574e4 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -24,6 +24,7 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
+import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
@@ -32,6 +33,7 @@
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.LocalVariableTable.LocalVariableTableEntry;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
@@ -177,7 +179,7 @@
@Override
public String getOriginalSignatureAttribute() {
return codeInspector.getOriginalSignatureAttribute(
- dexMethod.annotations, GenericSignatureParser::parseMethodSignature);
+ dexMethod.annotations(), GenericSignatureParser::parseMethodSignature);
}
public DexMethod getOriginalDexMethod(DexItemFactory dexItemFactory) {
@@ -191,7 +193,7 @@
@Override
public String getFinalSignatureAttribute() {
- return codeInspector.getFinalSignatureAttribute(dexMethod.annotations);
+ return codeInspector.getFinalSignatureAttribute(dexMethod.annotations());
}
public Iterable<InstructionSubject> instructions() {
@@ -335,7 +337,7 @@
@Override
public AnnotationSubject annotation(String name) {
- DexAnnotation annotation = codeInspector.findAnnotation(name, dexMethod.annotations);
+ DexAnnotation annotation = codeInspector.findAnnotation(name, dexMethod.annotations());
return annotation == null
? new AbsentAnnotationSubject()
: new FoundAnnotationSubject(annotation);
@@ -356,4 +358,15 @@
.collect(Collectors.toList()),
Reference.returnTypeFromDescriptor(method.proto.returnType.toDescriptorString()));
}
+
+ @Override
+ public String getJvmMethodSignatureAsString() {
+ return dexMethod.method.name.toString()
+ + "("
+ + StringUtils.join(
+ Arrays.stream(dexMethod.method.proto.parameters.values)
+ .map(DexType::toDescriptorString).collect(Collectors.toList()), "")
+ + ")"
+ + dexMethod.method.proto.returnType.toDescriptorString();
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
index 9a48dfa..6eba32b 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
@@ -84,6 +84,10 @@
boolean isCheckCast(String type);
+ default CheckCastInstructionSubject asCheckCast() {
+ return null;
+ }
+
boolean isInstanceOf();
boolean isInstanceOf(String type);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java
index d0e0a37..161aa3f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmFunctionSubject.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils.codeinspector;
+import java.util.List;
import kotlinx.metadata.KmFunction;
import kotlinx.metadata.jvm.JvmMethodSignature;
@@ -18,5 +19,7 @@
public abstract KmTypeSubject receiverParameterType();
+ public abstract List<KmValueParameterSubject> valueParameters();
+
public abstract KmTypeSubject returnType();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmPropertySubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmPropertySubject.java
index 9fb5a0a..826c1f1 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/KmPropertySubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmPropertySubject.java
@@ -15,6 +15,8 @@
public abstract boolean isExtension();
+ public abstract String name();
+
public abstract JvmFieldSignature fieldSignature();
public abstract JvmMethodSignature getterSignature();
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/KmValueParameterSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/KmValueParameterSubject.java
new file mode 100644
index 0000000..1f96b7d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/KmValueParameterSubject.java
@@ -0,0 +1,51 @@
+// 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.utils.codeinspector;
+
+import static kotlinx.metadata.Flag.ValueParameter.DECLARES_DEFAULT_VALUE;
+
+import com.android.tools.r8.errors.Unreachable;
+import kotlinx.metadata.KmValueParameter;
+
+public class KmValueParameterSubject extends Subject {
+ private final KmValueParameter kmValueParameter;
+
+ KmValueParameterSubject(KmValueParameter kmValueParameter) {
+ this.kmValueParameter = kmValueParameter;
+ }
+
+ public KmTypeSubject type() {
+ return new KmTypeSubject(kmValueParameter.getType());
+ }
+
+ public KmTypeSubject varargElementType() {
+ if (!isVararg()) {
+ return null;
+ }
+ return new KmTypeSubject(kmValueParameter.getVarargElementType());
+ }
+
+ public boolean isVararg() {
+ return kmValueParameter.getVarargElementType() != null;
+ }
+
+ public boolean declaresDefaultValue() {
+ return DECLARES_DEFAULT_VALUE.invoke(kmValueParameter.getFlags());
+ }
+
+ @Override
+ public boolean isPresent() {
+ return true;
+ }
+
+ @Override
+ public boolean isRenamed() {
+ throw new Unreachable("Cannot determine if a parameter is renamed");
+ }
+
+ @Override
+ public boolean isSynthetic() {
+ throw new Unreachable("Cannot determine if a parameter is synthetic");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
index af6e1a4..50911f3 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
@@ -104,4 +104,6 @@
public boolean hasCode() {
return getMethod().getCode() != null;
}
+
+ public abstract String getJvmMethodSignatureAsString();
}
diff --git a/tools/test.py b/tools/test.py
index 9359394..a75beb4 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -237,6 +237,7 @@
gradle_args.append('-Pr8lib_no_deps')
if options.worktree:
gradle_args.append('-g=' + os.path.join(utils.REPO_ROOT, ".gradle_user_home"))
+ gradle_args.append('--no-daemon')
# Build an R8 with dependencies for bootstrapping tests before adding test sources.
gradle_args.append('r8WithRelocatedDeps')