Merge "Tests for processing of CovariantReturnType annotation"
diff --git a/build.gradle b/build.gradle
index 86ba02f..0f782b2 100644
--- a/build.gradle
+++ b/build.gradle
@@ -514,7 +514,7 @@
classifier = null
version = null
manifest {
- attributes 'Main-Class': 'com.android.tools.r8.R8'
+ attributes 'Main-Class': 'com.android.tools.r8.SwissArmyKnife'
}
// In order to build without dependencies, pass the exclude_deps property using:
// gradle -Pexclude_deps R8
@@ -527,164 +527,27 @@
}
task D8(type: ShadowJar) {
- from consolidatedLicense.outputs.files
- exclude { path ->
- path.getRelativePath().getPathString().startsWith("META-INF")
- }
+ from R8.outputs.files
baseName 'd8'
- classifier = null
- version = null
manifest {
attributes 'Main-Class': 'com.android.tools.r8.D8'
}
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps D8
- if (!project.hasProperty('exclude_deps')) {
- from repackageSources.outputs.files
- from repackageDeps.outputs.files
- } else {
- from sourceSets.main.output
- }
}
-task CompatDx(type: Jar) {
- from sourceSets.main.output
+task CompatDx(type: ShadowJar) {
+ from R8.outputs.files
baseName 'compatdx'
manifest {
attributes 'Main-Class': 'com.android.tools.r8.compatdx.CompatDx'
}
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps CompatDx
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
}
-task DexFileMerger(type: Jar) {
- from sourceSets.main.output
- baseName 'dexfilemerger'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.dexfilemerger.DexFileMerger'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps CompatDx
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
-task DexSplitter(type: Jar) {
- from sourceSets.main.output
- baseName 'dexsplitter'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.dexsplitter.DexSplitter'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps CompatDx
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
-task CompatProguard(type: Jar) {
- from sourceSets.main.output
+task CompatProguard(type: ShadowJar) {
+ from R8.outputs.files
baseName 'compatproguard'
manifest {
attributes 'Main-Class': 'com.android.tools.r8.compatproguard.CompatProguard'
}
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps CompatProguard
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
-task D8Logger(type: Jar) {
- from sourceSets.main.output
- baseName 'd8logger'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.D8Logger'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps D8Logger
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
-task disasm(type: Jar) {
- from sourceSets.main.output
- baseName 'disasm'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.Disassemble'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps D8
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
-task bisect(type: Jar) {
- from sourceSets.main.output
- baseName 'bisect'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.bisect.Bisect'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps R8
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
-task DexSegments(type: Jar) {
- from sourceSets.main.output
- baseName 'dexsegments'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.DexSegments'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps DexSegments
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
-task maindex(type: Jar) {
- from sourceSets.main.output
- baseName 'maindex'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.GenerateMainDexList'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps maindex
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
-task ExtractMarker(type: Jar) {
- from sourceSets.main.output
- baseName 'extractmarker'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.ExtractMarker'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps ExtractMarker
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
}
task bspatch(type: Jar) {
@@ -694,7 +557,7 @@
attributes 'Main-Class': 'com.android.tools.r8.dex.BSPatch'
}
// In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps maindex
+ // gradle -Pexclude_deps bspatch
if (!project.hasProperty('exclude_deps')) {
// Also include dependencies
from {
@@ -703,20 +566,6 @@
}
}
-task jardiff(type: Jar) {
- from sourceSets.main.output
- baseName 'jardiff'
- manifest {
- attributes 'Main-Class': 'com.android.tools.r8.JarDiff'
- }
- // In order to build without dependencies, pass the exclude_deps property using:
- // gradle -Pexclude_deps jardiff
- if (!project.hasProperty('exclude_deps')) {
- // Also include dependencies
- from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
- }
-}
-
task sourceJar(type: Jar, dependsOn: classes) {
classifier = 'src'
from sourceSets.main.allSource
diff --git a/src/main/java/com/android/tools/r8/SwissArmyKnife.java b/src/main/java/com/android/tools/r8/SwissArmyKnife.java
new file mode 100644
index 0000000..0e35847
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/SwissArmyKnife.java
@@ -0,0 +1,83 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8;
+
+import com.android.tools.r8.bisect.Bisect;
+import com.android.tools.r8.compatdx.CompatDx;
+import com.android.tools.r8.compatproguard.CompatProguard;
+import com.android.tools.r8.dexfilemerger.DexFileMerger;
+import com.android.tools.r8.dexsplitter.DexSplitter;
+import java.util.Arrays;
+
+/**
+ * Common entry point to everything in the R8 project.
+ *
+ * <p>This class is used as the main class in {@code r8.jar}. It checks the first command-line
+ * argument to find the tool to run, or runs {@link R8} if the first argument is not a recognized
+ * tool name.
+ *
+ * <p>The set of tools recognized by this class is defined by a switch statement in {@link
+ * SwissArmyKnife#main(String[])}.
+ */
+public class SwissArmyKnife {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 0) {
+ runDefault(args);
+ return;
+ }
+ switch (args[0]) {
+ case "r8":
+ R8.main(shift(args));
+ break;
+ case "d8":
+ D8.main(shift(args));
+ break;
+ case "compatdx":
+ CompatDx.main(shift(args));
+ break;
+ case "dexfilemerger":
+ DexFileMerger.main(shift(args));
+ break;
+ case "dexsplitter":
+ DexSplitter.main(shift(args));
+ break;
+ case "compatproguard":
+ CompatProguard.main(shift(args));
+ break;
+ case "d8logger":
+ D8Logger.main(shift(args));
+ break;
+ case "disasm":
+ Disassemble.main(shift(args));
+ break;
+ case "bisect":
+ Bisect.main(shift(args));
+ break;
+ case "dexsegments":
+ DexSegments.main(shift(args));
+ break;
+ case "maindex":
+ GenerateMainDexList.main(shift(args));
+ break;
+ case "extractmarker":
+ ExtractMarker.main(shift(args));
+ break;
+ case "jardiff":
+ JarDiff.main(shift(args));
+ break;
+ default:
+ runDefault(args);
+ break;
+ }
+ }
+
+ private static void runDefault(String[] args) {
+ R8.main(args);
+ }
+
+ private static String[] shift(String[] args) {
+ return Arrays.copyOfRange(args, 1, args.length);
+ }
+}
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 df16622..382bc66 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationDirectory;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexDebugInfo;
@@ -30,6 +29,7 @@
import com.android.tools.r8.graph.EnclosingMethodAttribute;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.naming.ProguardMapSupplier;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -106,7 +106,7 @@
}
@Override
- public boolean add(DexAnnotationSetRefList annotationSetRefList) {
+ public boolean add(ParameterAnnotationsList parameterAnnotationsList) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/dex/DexParser.java b/src/main/java/com/android/tools/r8/dex/DexParser.java
index 8042a1a..d762646 100644
--- a/src/main/java/com/android/tools/r8/dex/DexParser.java
+++ b/src/main/java/com/android/tools/r8/dex/DexParser.java
@@ -19,7 +19,6 @@
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.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexCode;
@@ -56,6 +55,7 @@
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.OffsetToObjectMapping;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
@@ -340,11 +340,11 @@
return result;
}
- private DexAnnotationSetRefList annotationSetRefListAt(int offset) {
- return (DexAnnotationSetRefList) cacheAt(offset, this::parseAnnotationSetRefList);
+ private ParameterAnnotationsList annotationSetRefListAt(int offset) {
+ return (ParameterAnnotationsList) cacheAt(offset, this::parseAnnotationSetRefList);
}
- private DexAnnotationSetRefList parseAnnotationSetRefList() {
+ private ParameterAnnotationsList parseAnnotationSetRefList() {
int size = dexReader.getUint();
int[] annotationOffsets = new int[size];
for (int i = 0; i < size; i++) {
@@ -354,7 +354,7 @@
for (int i = 0; i < size; i++) {
values[i] = annotationSetAt(annotationOffsets[i]);
}
- return new DexAnnotationSetRefList(values);
+ return new ParameterAnnotationsList(values);
}
private DexParameterAnnotation[] parseParameterAnnotations(int size) {
@@ -373,7 +373,8 @@
DexMethod method = indexedItems.getMethod(methodIndices[i]);
result[i] = new DexParameterAnnotation(
method,
- annotationSetRefListAt(annotationOffsets[i]));
+ annotationSetRefListAt(annotationOffsets[i])
+ .withParameterCount(method.proto.parameters.size()));
}
dexReader.position(saved);
return result;
@@ -589,8 +590,8 @@
int methodIndex = 0;
MemberAnnotationIterator<DexMethod, DexAnnotationSet> annotationIterator =
new MemberAnnotationIterator<>(annotations, DexAnnotationSet::empty);
- MemberAnnotationIterator<DexMethod, DexAnnotationSetRefList> parameterAnnotationsIterator =
- new MemberAnnotationIterator<>(parameters, DexAnnotationSetRefList::empty);
+ MemberAnnotationIterator<DexMethod, ParameterAnnotationsList> parameterAnnotationsIterator =
+ new MemberAnnotationIterator<>(parameters, ParameterAnnotationsList::empty);
for (int i = 0; i < size; i++) {
methodIndex += dexReader.getUleb128();
MethodAccessFlags accessFlags = MethodAccessFlags.fromDexAccessFlags(dexReader.getUleb128());
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 ced33f6..4767c64 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -13,7 +13,6 @@
import com.android.tools.r8.graph.DexAnnotationDirectory;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
@@ -40,6 +39,7 @@
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;
import com.android.tools.r8.graph.ProgramClassVisitor;
import com.android.tools.r8.logging.Log;
@@ -510,12 +510,17 @@
}
}
- private void writeAnnotationSetRefList(DexAnnotationSetRefList setRefList) {
- assert !setRefList.isEmpty();
- mixedSectionOffsets.setOffsetFor(setRefList, dest.align(4));
- dest.putInt(setRefList.values.length);
- for (DexAnnotationSet set : setRefList.values) {
- dest.putInt(mixedSectionOffsets.getOffsetFor(set));
+ private void writeAnnotationSetRefList(ParameterAnnotationsList parameterAnnotationsList) {
+ assert !parameterAnnotationsList.isEmpty();
+ mixedSectionOffsets.setOffsetFor(parameterAnnotationsList, dest.align(4));
+ dest.putInt(parameterAnnotationsList.countNonMissing());
+ for (int i = 0; i < parameterAnnotationsList.size(); i++) {
+ if (parameterAnnotationsList.isMissing(i)) {
+ // b/62300145: Maintain broken ParameterAnnotations attribute by only outputting the
+ // non-missing annotation lists.
+ continue;
+ }
+ dest.putInt(mixedSectionOffsets.getOffsetFor(parameterAnnotationsList.get(i)));
}
}
@@ -541,7 +546,7 @@
writeMemberAnnotations(methodAnnotations,
item -> mixedSectionOffsets.getOffsetFor(item.annotations));
writeMemberAnnotations(parameterAnnotations,
- item -> mixedSectionOffsets.getOffsetFor(item.parameterAnnotations));
+ item -> mixedSectionOffsets.getOffsetFor(item.parameterAnnotationsList));
}
private void writeEncodedFields(DexEncodedField[] fields) {
@@ -990,7 +995,7 @@
private final Reference2IntMap<DexString> stringData = createReference2IntMap();
private final Object2IntMap<DexAnnotation> annotations = createObject2IntMap();
private final Object2IntMap<DexAnnotationSet> annotationSets = createObject2IntMap();
- private final Object2IntMap<DexAnnotationSetRefList> annotationSetRefLists
+ private final Object2IntMap<ParameterAnnotationsList> annotationSetRefLists
= createObject2IntMap();
private final Object2IntMap<DexAnnotationDirectory> annotationDirectories
= createObject2IntMap();
@@ -1072,7 +1077,7 @@
}
@Override
- public boolean add(DexAnnotationSetRefList annotationSetRefList) {
+ public boolean add(ParameterAnnotationsList annotationSetRefList) {
if (annotationSetRefList.isEmpty()) {
return false;
}
@@ -1120,7 +1125,7 @@
return annotationSets.keySet();
}
- public Collection<DexAnnotationSetRefList> getAnnotationSetRefLists() {
+ public Collection<ParameterAnnotationsList> getAnnotationSetRefLists() {
return annotationSetRefLists.keySet();
}
@@ -1200,7 +1205,7 @@
return lookup(annotationSet, annotationSets);
}
- public int getOffsetFor(DexAnnotationSetRefList annotationSetRefList) {
+ public int getOffsetFor(ParameterAnnotationsList annotationSetRefList) {
if (annotationSetRefList.isEmpty()) {
return 0;
}
@@ -1261,7 +1266,7 @@
setOffsetFor(encodedArray, offset, encodedArrays);
}
- void setOffsetFor(DexAnnotationSetRefList annotationSetRefList, int offset) {
+ void setOffsetFor(ParameterAnnotationsList annotationSetRefList, int offset) {
assert offset != 0 && !annotationSetRefList.isEmpty();
setOffsetFor(annotationSetRefList, offset, annotationSetRefLists);
}
diff --git a/src/main/java/com/android/tools/r8/dex/MixedSectionCollection.java b/src/main/java/com/android/tools/r8/dex/MixedSectionCollection.java
index eb7ae98..dee12fc 100644
--- a/src/main/java/com/android/tools/r8/dex/MixedSectionCollection.java
+++ b/src/main/java/com/android/tools/r8/dex/MixedSectionCollection.java
@@ -6,13 +6,13 @@
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationDirectory;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexDebugInfo;
import com.android.tools.r8.graph.DexEncodedArray;
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexTypeList;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
/**
* Collection of the various components of the mixed section of a dex file.
@@ -86,7 +86,7 @@
*
* @return true if the item was not added before
*/
- public abstract boolean add(DexAnnotationSetRefList annotationSetRefList);
+ public abstract boolean add(ParameterAnnotationsList annotationSetRefList);
/**
* Adds the given annotation to the collection.
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 1ac2246..61595b9 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -5,23 +5,15 @@
import com.android.tools.r8.ApiLevelException;
import com.android.tools.r8.cf.CfPrinter;
-import com.android.tools.r8.cf.code.CfConstNull;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfLabel;
import com.android.tools.r8.cf.code.CfPosition;
import com.android.tools.r8.cf.code.CfReturnVoid;
-import com.android.tools.r8.cf.code.CfThrow;
import com.android.tools.r8.cf.code.CfTryCatch;
import com.android.tools.r8.errors.Unimplemented;
-import com.android.tools.r8.ir.code.BasicBlock;
-import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.ir.code.Throw;
-import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
-import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
@@ -29,7 +21,6 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.InternalOptions;
import java.util.Collections;
-import java.util.LinkedList;
import java.util.List;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
@@ -211,21 +202,6 @@
@Override
public IRCode buildIR(DexEncodedMethod encodedMethod, InternalOptions options, Origin origin)
throws ApiLevelException {
- if (instructions.size() == 2
- && instructions.get(0) instanceof CfConstNull
- && instructions.get(1) instanceof CfThrow) {
- BasicBlock block = new BasicBlock();
- block.setNumber(1);
- Value nullValue = new Value(0, ValueType.OBJECT, null);
- block.add(new ConstNumber(nullValue, 0L));
- block.add(new Throw(nullValue));
- block.close(null);
- for (Instruction insn : block.getInstructions()) {
- insn.setPosition(Position.none());
- }
- LinkedList<BasicBlock> blocks = new LinkedList<>(Collections.singleton(block));
- return new IRCode(options, encodedMethod, blocks, null, false);
- }
return internalBuild(encodedMethod, options, null, null, origin);
}
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 aa5d145..fa5d8a8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
@@ -33,7 +33,7 @@
if (!method.annotations.isEmpty()) {
methodAnnotations.add(method);
}
- if (!method.parameterAnnotations.isEmpty()) {
+ if (!method.parameterAnnotationsList.isEmpty()) {
parameterAnnotations.add(method);
}
}
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 9ee8fba..d093a20 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
@@ -5,7 +5,9 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.function.Predicate;
public class DexAnnotationSet extends CachedHashValueDexItem {
@@ -115,4 +117,30 @@
extendedArray[annotations.length] = newAnnotation;
return new DexAnnotationSet(extendedArray);
}
+
+ public DexAnnotationSet keepIf(Predicate<DexAnnotation> filter) {
+ ArrayList<DexAnnotation> filtered = null;
+ for (int i = 0; i < annotations.length; i++) {
+ DexAnnotation annotation = annotations[i];
+ if (filter.test(annotation)) {
+ if (filtered != null) {
+ filtered.add(annotation);
+ }
+ } else {
+ if (filtered == null) {
+ filtered = new ArrayList<>(annotations.length);
+ for (int j = 0; j < i; j++) {
+ filtered.add(annotations[j]);
+ }
+ }
+ }
+ }
+ if (filtered == null) {
+ return this;
+ } else if (filtered.isEmpty()) {
+ return DexAnnotationSet.empty();
+ } else {
+ return new DexAnnotationSet(filtered.toArray(new DexAnnotation[filtered.size()]));
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationSetRefList.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationSetRefList.java
deleted file mode 100644
index 4bb1314..0000000
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSetRefList.java
+++ /dev/null
@@ -1,72 +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;
-
-import com.android.tools.r8.dex.IndexedItemCollection;
-import com.android.tools.r8.dex.MixedSectionCollection;
-import java.util.Arrays;
-
-public class DexAnnotationSetRefList extends DexItem {
-
- private static final DexAnnotationSetRefList theEmptyTypeList = new DexAnnotationSetRefList();
-
- public final DexAnnotationSet[] values;
- private final int missingParameterAnnotations;
-
- public static DexAnnotationSetRefList empty() {
- return theEmptyTypeList;
- }
-
- private DexAnnotationSetRefList() {
- this.values = new DexAnnotationSet[0];
- this.missingParameterAnnotations = 0;
- }
-
- public DexAnnotationSetRefList(DexAnnotationSet[] values) {
- this(values, 0);
- }
-
- public DexAnnotationSetRefList(DexAnnotationSet[] values, int missingParameterAnnotations) {
- assert values != null && values.length > 0;
- this.values = values;
- this.missingParameterAnnotations = missingParameterAnnotations;
- }
-
- @Override
- public int hashCode() {
- return Arrays.hashCode(values);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- }
- if (other instanceof DexAnnotationSetRefList) {
- return Arrays.equals(values, ((DexAnnotationSetRefList) other).values);
- }
- return false;
- }
-
- @Override
- public void collectIndexedItems(IndexedItemCollection indexedItems,
- DexMethod method, int instructionOffset) {
- collectAll(indexedItems, values);
- }
-
- @Override
- void collectMixedSectionItems(MixedSectionCollection mixedItems) {
- // Collect values first so that the annotation sets have sorted themselves before adding this.
- collectAll(mixedItems, values);
- mixedItems.add(this);
- }
-
- public boolean isEmpty() {
- return values.length == 0;
- }
-
- public int getMissingParameterAnnotations() {
- return missingParameterAnnotations;
- }
-}
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 7b09cab..23139c5 100644
--- a/src/main/java/com/android/tools/r8/graph/DexClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -159,21 +159,13 @@
for (DexAnnotation annotation : method.annotations.annotations) {
consumer.accept(annotation);
}
- for (DexAnnotationSet parameterAnnotations : method.parameterAnnotations.values) {
- for (DexAnnotation annotation : parameterAnnotations.annotations) {
- consumer.accept(annotation);
- }
- }
+ method.parameterAnnotationsList.forEachAnnotation(consumer);
}
for (DexEncodedMethod method : virtualMethods()) {
for (DexAnnotation annotation : method.annotations.annotations) {
consumer.accept(annotation);
}
- for (DexAnnotationSet parameterAnnotations : method.parameterAnnotations.values) {
- for (DexAnnotation annotation : parameterAnnotations.annotations) {
- consumer.accept(annotation);
- }
- }
+ method.parameterAnnotationsList.forEachAnnotation(consumer);
}
for (DexEncodedField field : instanceFields()) {
for (DexAnnotation annotation : field.annotations.annotations) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index d514a9a..0cabaf1 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -93,7 +93,7 @@
public final DexMethod method;
public final MethodAccessFlags accessFlags;
public DexAnnotationSet annotations;
- public DexAnnotationSetRefList parameterAnnotations;
+ public ParameterAnnotationsList parameterAnnotationsList;
private Code code;
private CompilationState compilationState = CompilationState.NOT_PROCESSED;
private OptimizationInfo optimizationInfo = DefaultOptimizationInfo.DEFAULT;
@@ -102,12 +102,12 @@
DexMethod method,
MethodAccessFlags accessFlags,
DexAnnotationSet annotations,
- DexAnnotationSetRefList parameterAnnotations,
+ ParameterAnnotationsList parameterAnnotationsList,
Code code) {
this.method = method;
this.accessFlags = accessFlags;
this.annotations = annotations;
- this.parameterAnnotations = parameterAnnotations;
+ this.parameterAnnotationsList = parameterAnnotationsList;
this.code = code;
assert code == null || !accessFlags.isAbstract();
}
@@ -272,7 +272,7 @@
code.collectIndexedItems(indexedItems, this.method);
}
annotations.collectIndexedItems(indexedItems);
- parameterAnnotations.collectIndexedItems(indexedItems);
+ parameterAnnotationsList.collectIndexedItems(indexedItems);
}
@Override
@@ -281,7 +281,7 @@
code.collectMixedSectionItems(mixedItems);
}
annotations.collectMixedSectionItems(mixedItems);
- parameterAnnotations.collectMixedSectionItems(mixedItems);
+ parameterAnnotationsList.collectMixedSectionItems(mixedItems);
}
public Code getCode() {
@@ -537,7 +537,7 @@
}
public boolean hasAnnotation() {
- return !annotations.isEmpty() || !parameterAnnotations.isEmpty();
+ return !annotations.isEmpty() || !parameterAnnotationsList.isEmpty();
}
public void registerCodeReferences(UseRegistry registry) {
@@ -727,7 +727,7 @@
private DexMethod method;
private final MethodAccessFlags accessFlags;
private final DexAnnotationSet annotations;
- private final DexAnnotationSetRefList parameterAnnotations;
+ private final ParameterAnnotationsList parameterAnnotations;
private Code code;
private CompilationState compilationState = CompilationState.NOT_PROCESSED;
private OptimizationInfo optimizationInfo = DefaultOptimizationInfo.DEFAULT;
@@ -737,7 +737,7 @@
method = from.method;
accessFlags = from.accessFlags.copy();
annotations = from.annotations;
- parameterAnnotations = from.parameterAnnotations;
+ parameterAnnotations = from.parameterAnnotationsList;
code = from.code;
compilationState = from.compilationState;
optimizationInfo = from.optimizationInfo.copy();
diff --git a/src/main/java/com/android/tools/r8/graph/DexMemberAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexMemberAnnotation.java
index f005588..6cc2fb4 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMemberAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMemberAnnotation.java
@@ -60,9 +60,9 @@
}
public static class DexParameterAnnotation extends
- DexMemberAnnotation<DexMethod, DexAnnotationSetRefList> {
+ DexMemberAnnotation<DexMethod, ParameterAnnotationsList> {
- public DexParameterAnnotation(DexMethod item, DexAnnotationSetRefList annotations) {
+ public DexParameterAnnotation(DexMethod item, ParameterAnnotationsList annotations) {
super(item, annotations);
}
}
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 e403c14..02f0801 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -446,7 +446,7 @@
private List<DexAnnotation> annotations = null;
private DexValue defaultAnnotation = null;
private int fakeParameterAnnotations = 0;
- private List<List<DexAnnotation>> parameterAnnotations = null;
+ private List<List<DexAnnotation>> parameterAnnotationsLists = null;
private List<DexValue> parameterNames = null;
private List<DexValue> parameterFlags = null;
final DexMethod method;
@@ -508,21 +508,21 @@
// We can iterate through all the parameters twice. Once for visible and once for
// invisible parameter annotations. We only record the number of fake parameter
// annotations once.
- if (parameterAnnotations == null) {
+ if (parameterAnnotationsLists == null) {
fakeParameterAnnotations++;
}
return null;
}
- if (parameterAnnotations == null) {
+ if (parameterAnnotationsLists == null) {
int adjustedParameterCount = parameterCount - fakeParameterAnnotations;
- parameterAnnotations = new ArrayList<>(adjustedParameterCount);
+ parameterAnnotationsLists = new ArrayList<>(adjustedParameterCount);
for (int i = 0; i < adjustedParameterCount; i++) {
- parameterAnnotations.add(new ArrayList<>());
+ parameterAnnotationsLists.add(new ArrayList<>());
}
}
assert mv == null;
return createAnnotationVisitor(desc, visible,
- parameterAnnotations.get(parameter - fakeParameterAnnotations), parent.application);
+ parameterAnnotationsLists.get(parameter - fakeParameterAnnotations), parent.application);
}
@Override
@@ -573,15 +573,15 @@
public void visitEnd() {
assert flags.isAbstract() || flags.isNative() || parent.classKind != ClassKind.PROGRAM
|| code != null;
- DexAnnotationSetRefList parameterAnnotationSets;
- if (parameterAnnotations == null) {
- parameterAnnotationSets = DexAnnotationSetRefList.empty();
+ ParameterAnnotationsList annotationsList;
+ if (parameterAnnotationsLists == null) {
+ annotationsList = ParameterAnnotationsList.empty();
} else {
- DexAnnotationSet[] sets = new DexAnnotationSet[parameterAnnotations.size()];
- for (int i = 0; i < parameterAnnotations.size(); i++) {
- sets[i] = createAnnotationSet(parameterAnnotations.get(i));
+ DexAnnotationSet[] sets = new DexAnnotationSet[parameterAnnotationsLists.size()];
+ for (int i = 0; i < parameterAnnotationsLists.size(); i++) {
+ sets[i] = createAnnotationSet(parameterAnnotationsLists.get(i));
}
- parameterAnnotationSets = new DexAnnotationSetRefList(sets, fakeParameterAnnotations);
+ annotationsList = new ParameterAnnotationsList(sets, fakeParameterAnnotations);
}
InternalOptions internalOptions = parent.application.options;
if (parameterNames != null && internalOptions.canUseParameterNameAnnotations()) {
@@ -596,7 +596,7 @@
parent.application.getFactory()));
}
DexEncodedMethod dexMethod = new DexEncodedMethod(method, flags,
- createAnnotationSet(annotations), parameterAnnotationSets, code);
+ createAnnotationSet(annotations), annotationsList, code);
if (flags.isStatic() || flags.isConstructor() || flags.isPrivate()) {
parent.directMethods.add(dexMethod);
} else {
diff --git a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
new file mode 100644
index 0000000..23d5a38
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
@@ -0,0 +1,184 @@
+// 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;
+
+import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.dex.MixedSectionCollection;
+import java.util.Arrays;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+/**
+ * List of parameter annotations.
+ *
+ * <p>Due to a javac bug that went unfixed for multiple Java versions, the JVM specification does
+ * not require that the number of entries in the ParameterAnnotations attribute of a method matches
+ * the number of parameters in the method prototype; the number of ParameterAnnotations entries may
+ * be less than the number of prototype parameters for methods on inner classes.
+ *
+ * <p>There are two ways of accessing the parameter annotations:
+ *
+ * <ul>
+ * <li>Using {@link ParameterAnnotationsList#forEachAnnotation(Consumer)}
+ * <li>Using {@link ParameterAnnotationsList#size()}, {@link
+ * ParameterAnnotationsList#isMissing(int)} and {@link ParameterAnnotationsList#get(int)}
+ * </ul>
+ *
+ * <p>The {@link ParameterAnnotationsList#forEachAnnotation(Consumer)} method visits all the {@link
+ * DexAnnotation}s specified in the ParameterAnnotations attribute. In contrast, the {@link
+ * ParameterAnnotationsList#size()} and {@link ParameterAnnotationsList#get(int)} methods may be
+ * used to access the annotations on individual parameters; these methods automatically shift
+ * parameter annotations up to mitigate the javac bug. The {@link
+ * ParameterAnnotationsList#isMissing(int)} accessor is used to determine whether a given parameter
+ * is missing in the ParameterAnnotations attribute.
+ */
+public class ParameterAnnotationsList extends DexItem {
+
+ private static final ParameterAnnotationsList EMPTY_PARAMETER_ANNOTATIONS_LIST =
+ new ParameterAnnotationsList();
+
+ private final DexAnnotationSet[] values;
+ private final int missingParameterAnnotations;
+
+ public static ParameterAnnotationsList empty() {
+ return EMPTY_PARAMETER_ANNOTATIONS_LIST;
+ }
+
+ private ParameterAnnotationsList() {
+ this.values = new DexAnnotationSet[0];
+ this.missingParameterAnnotations = 0;
+ }
+
+ public ParameterAnnotationsList(DexAnnotationSet[] values) {
+ this(values, 0);
+ }
+
+ public ParameterAnnotationsList(DexAnnotationSet[] values, int missingParameterAnnotations) {
+ assert values != null && values.length > 0;
+ this.values = values;
+ this.missingParameterAnnotations = missingParameterAnnotations;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(values);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (other instanceof ParameterAnnotationsList) {
+ return Arrays.equals(values, ((ParameterAnnotationsList) other).values);
+ }
+ return false;
+ }
+
+ @Override
+ public void collectIndexedItems(
+ IndexedItemCollection indexedItems, DexMethod method, int instructionOffset) {
+ collectAll(indexedItems, values);
+ }
+
+ @Override
+ void collectMixedSectionItems(MixedSectionCollection mixedItems) {
+ // Collect values first so that the annotation sets have sorted themselves before adding this.
+ collectAll(mixedItems, values);
+ mixedItems.add(this);
+ }
+
+ public boolean isEmpty() {
+ return values.length == 0;
+ }
+
+ /** Iterate over the {@link DexAnnotation}s of all parameters. */
+ public void forEachAnnotation(Consumer<DexAnnotation> consumer) {
+ for (DexAnnotationSet parameterAnnotations : values) {
+ for (DexAnnotation annotation : parameterAnnotations.annotations) {
+ consumer.accept(annotation);
+ }
+ }
+ }
+
+ /**
+ * Return the number of parameters in the method prototype, or zero if the method's parameters
+ * have no annotations.
+ */
+ public int size() {
+ return missingParameterAnnotations + values.length;
+ }
+
+ /**
+ * Return the number of parameters specified in the ParameterAnnotations attribute, that is, the
+ * number of parameters for which {@link ParameterAnnotationsList#isMissing(int)} returns false.
+ */
+ public int countNonMissing() {
+ return values.length;
+ }
+
+ /**
+ * Return true if the ParameterAnnotations attribute is missing an entry for this parameter. This
+ * is sometimes the case for the first parameter in a method on an inner class.
+ *
+ * @param i Index of the parameter in the method prototype.
+ */
+ public boolean isMissing(int i) {
+ assert i >= 0;
+ return i < missingParameterAnnotations;
+ }
+
+ /**
+ * Return the annotations on the {@code i}th parameter (indexed according to the method
+ * prototype). If the parameter's annotation list is missing, or {@code i} is not less than the
+ * number of parameters (see {@link ParameterAnnotationsList#isMissing(int)}), {@link
+ * DexAnnotationSet#empty()} is returned.
+ *
+ * @param i Index of the parameter in the method prototype.
+ */
+ public DexAnnotationSet get(int i) {
+ assert i >= 0;
+ int adjustedIndex = i - missingParameterAnnotations;
+ return (0 <= adjustedIndex && adjustedIndex < values.length)
+ ? values[adjustedIndex]
+ : DexAnnotationSet.empty();
+ }
+
+ /** Return a ParameterAnnotationsList extended to the given number of parameters. */
+ public ParameterAnnotationsList withParameterCount(int parameterCount) {
+ assert parameterCount >= size();
+ if (this == EMPTY_PARAMETER_ANNOTATIONS_LIST || parameterCount == size()) {
+ return this;
+ }
+ return new ParameterAnnotationsList(values, parameterCount - values.length);
+ }
+
+ /**
+ * Return a new ParameterAnnotationsList that keeps only the annotations matched by {@code
+ * filter}.
+ */
+ public ParameterAnnotationsList keepIf(Predicate<DexAnnotation> filter) {
+ DexAnnotationSet[] filtered = null;
+ boolean allEmpty = true;
+ for (int i = 0; i < values.length; i++) {
+ DexAnnotationSet updated = values[i].keepIf(filter);
+ if (updated != values[i]) {
+ if (filtered == null) {
+ filtered = values.clone();
+ }
+ filtered[i] = updated;
+ }
+ if (!updated.isEmpty()) {
+ allEmpty = false;
+ }
+ }
+ if (filtered == null) {
+ return this;
+ }
+ if (allEmpty) {
+ return ParameterAnnotationsList.empty();
+ }
+ return new ParameterAnnotationsList(filtered, missingParameterAnnotations);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index 7befc69..c75456d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -111,7 +111,7 @@
// Some debuggers (like IntelliJ) automatically skip synthetic methods on single step.
newFlags.setSynthetic();
return new DexEncodedMethod(newMethod, newFlags,
- defaultMethod.annotations, defaultMethod.parameterAnnotations,
+ defaultMethod.annotations, defaultMethod.parameterAnnotationsList,
new SynthesizedCode(new ForwardMethodSourceCode(
clazz.type, method.proto, /* static method */ null,
rewriter.defaultAsMethodOfCompanionClass(method),
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 898a2b2..1e8d57a 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
@@ -70,7 +70,7 @@
|| (companionMethod.getArity() == dexCode.getDebugInfo().parameters.length);
companionMethods.add(new DexEncodedMethod(companionMethod,
- newFlags, virtual.annotations, virtual.parameterAnnotations, code));
+ newFlags, virtual.annotations, virtual.parameterAnnotationsList, code));
// Make the method abstract.
virtual.accessFlags.setAbstract();
@@ -106,7 +106,7 @@
+ "either be public or private in " + iface.origin;
companionMethods.add(new DexEncodedMethod(
rewriter.staticAsMethodOfCompanionClass(direct.method), newFlags,
- direct.annotations, direct.parameterAnnotations, direct.getCode()));
+ direct.annotations, direct.parameterAnnotationsList, direct.getCode()));
} else {
if (originalFlags.isPrivate()) {
@@ -129,7 +129,7 @@
|| (companionMethod.getArity() == dexCode.getDebugInfo().parameters.length);
companionMethods.add(new DexEncodedMethod(companionMethod,
- newFlags, direct.annotations, direct.parameterAnnotations, code));
+ newFlags, direct.annotations, direct.parameterAnnotationsList, code));
} else {
// Since there are no interface constructors at this point,
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 82958da..d9bd4bd 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClass.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexEncodedField;
@@ -27,6 +26,7 @@
import com.android.tools.r8.graph.DexValue.DexValueNull;
import com.android.tools.r8.graph.FieldAccessFlags;
import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.code.Invoke;
import com.android.tools.r8.ir.synthetic.SynthesizedCode;
import com.android.tools.r8.origin.SynthesizedOrigin;
@@ -171,7 +171,7 @@
MethodAccessFlags.fromSharedAccessFlags(
Constants.ACC_PUBLIC | Constants.ACC_FINAL, false),
DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(),
+ ParameterAnnotationsList.empty(),
new SynthesizedCode(new LambdaMainMethodSourceCode(this, mainMethod)));
// Synthesize bridge methods.
@@ -187,7 +187,7 @@
| Constants.ACC_BRIDGE,
false),
DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(),
+ ParameterAnnotationsList.empty(),
new SynthesizedCode(
new LambdaBridgeMethodSourceCode(this, mainMethod, bridgeMethod)));
}
@@ -208,7 +208,7 @@
| Constants.ACC_SYNTHETIC,
true),
DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(),
+ ParameterAnnotationsList.empty(),
new SynthesizedCode(new LambdaConstructorSourceCode(this)));
// Class constructor for stateless lambda classes.
@@ -219,7 +219,7 @@
MethodAccessFlags.fromSharedAccessFlags(
Constants.ACC_SYNTHETIC | Constants.ACC_STATIC, true),
DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(),
+ ParameterAnnotationsList.empty(),
new SynthesizedCode(new LambdaClassConstructorSourceCode(this)));
}
return methods;
@@ -492,7 +492,7 @@
// relax its accessibility without making it virtual.
DexEncodedMethod newMethod = new DexEncodedMethod(
callTarget, encodedMethod.accessFlags, encodedMethod.annotations,
- encodedMethod.parameterAnnotations, encodedMethod.getCode());
+ encodedMethod.parameterAnnotationsList, encodedMethod.getCode());
// TODO(ager): Should we give the new first parameter an actual name? Maybe 'this'?
encodedMethod.accessFlags.setStatic();
encodedMethod.accessFlags.unsetPrivate();
@@ -532,7 +532,7 @@
Constants.ACC_SYNTHETIC | Constants.ACC_STATIC | Constants.ACC_PUBLIC,
false);
DexEncodedMethod accessorEncodedMethod = new DexEncodedMethod(
- callTarget, accessorFlags, DexAnnotationSet.empty(), DexAnnotationSetRefList.empty(),
+ callTarget, accessorFlags, DexAnnotationSet.empty(), ParameterAnnotationsList.empty(),
new SynthesizedCode(new AccessorMethodSourceCode(LambdaClass.this)));
accessorClass.setDirectMethods(appendMethod(
accessorClass.directMethods(), accessorEncodedMethod));
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 5a257df..7af555c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
@@ -22,6 +21,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -1057,7 +1057,7 @@
DexString methodName = dexItemFactory.createString(OutlineOptions.METHOD_PREFIX + count);
DexMethod method = outline.buildMethod(type, methodName);
direct[count] = new DexEncodedMethod(method, methodAccess, DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(), new OutlineCode(outline));
+ ParameterAnnotationsList.empty(), new OutlineCode(outline));
generatedOutlines.put(outline, method);
count++;
}
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 03daf44..466117f 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
@@ -327,12 +327,12 @@
for (DexEncodedMethod method : clazz.directMethods()) {
lambdaInvalidator.accept(method.annotations);
- lambdaInvalidator.accept(method.parameterAnnotations);
+ lambdaInvalidator.accept(method.parameterAnnotationsList);
lambdaInvalidator.accept(method.method, clazz.type);
}
for (DexEncodedMethod method : clazz.virtualMethods()) {
lambdaInvalidator.accept(method.annotations);
- lambdaInvalidator.accept(method.parameterAnnotations);
+ lambdaInvalidator.accept(method.parameterAnnotationsList);
lambdaInvalidator.accept(method.method, clazz.type);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
index 4f56306..05c71e6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/LambdaTypeVisitor.java
@@ -7,7 +7,6 @@
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.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexField;
@@ -24,6 +23,7 @@
import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
import com.android.tools.r8.graph.DexValue.DexValueMethodType;
import com.android.tools.r8.graph.DexValue.DexValueType;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -116,10 +116,8 @@
}
}
- void accept(DexAnnotationSetRefList annotationSetRefList) {
- for (DexAnnotationSet annotationSet : annotationSetRefList.values) {
- accept(annotationSet);
- }
+ void accept(ParameterAnnotationsList parameterAnnotationsList) {
+ parameterAnnotationsList.forEachAnnotation(this::accept);
}
private void accept(DexAnnotation annotation) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
index d441a00..1fe0317 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaGroupClassBuilder.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
@@ -19,6 +18,7 @@
import com.android.tools.r8.graph.EnclosingMethodAttribute;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.optimize.lambda.LambdaGroupClassBuilder;
import com.android.tools.r8.ir.synthetic.SynthesizedCode;
import com.android.tools.r8.ir.synthetic.SyntheticSourceCode;
@@ -113,7 +113,7 @@
factory.createMethod(group.getGroupClassType(), methodProto, methodName),
accessFlags,
isMainMethod ? id.mainMethodAnnotations : DexAnnotationSet.empty(),
- isMainMethod ? id.mainMethodParamAnnotations : DexAnnotationSetRefList.empty(),
+ isMainMethod ? id.mainMethodParamAnnotations : ParameterAnnotationsList.empty(),
new SynthesizedCode(
new KotlinLambdaVirtualMethodSourceCode(factory, group.getGroupClassType(),
methodProto, group.getLambdaIdField(factory), implMethods))));
@@ -159,7 +159,7 @@
factory.createMethod(groupClassType, initializerProto, factory.constructorMethodName),
CONSTRUCTOR_FLAGS_RELAXED, // always create access-relaxed constructor.
DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(),
+ ParameterAnnotationsList.empty(),
new SynthesizedCode(createInstanceInitializerSourceCode(groupClassType, initializerProto)));
// Static class initializer for stateless lambdas.
@@ -170,7 +170,7 @@
factory.classConstructorMethodName),
CLASS_INITIALIZER_FLAGS,
DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(),
+ ParameterAnnotationsList.empty(),
new SynthesizedCode(new ClassInitializerSourceCode(factory, group)));
}
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 0540bef..996099b 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
@@ -5,13 +5,13 @@
package com.android.tools.r8.ir.optimize.lambda.kotlin;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.EnclosingMethodAttribute;
import com.android.tools.r8.graph.InnerClassAttribute;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.optimize.lambda.LambdaGroup;
import com.android.tools.r8.ir.optimize.lambda.LambdaGroupId;
@@ -41,7 +41,7 @@
final DexString mainMethodName;
final DexProto mainMethodProto;
final DexAnnotationSet mainMethodAnnotations;
- final DexAnnotationSetRefList mainMethodParamAnnotations;
+ final ParameterAnnotationsList mainMethodParamAnnotations;
final EnclosingMethodAttribute enclosing;
@@ -61,7 +61,7 @@
this.mainMethodName = mainMethod.method.name;
this.mainMethodProto = mainMethod.method.proto;
this.mainMethodAnnotations = mainMethod.annotations;
- this.mainMethodParamAnnotations = mainMethod.parameterAnnotations;
+ this.mainMethodParamAnnotations = mainMethod.parameterAnnotationsList;
this.innerClassAccess = inner != null ? inner.getAccess() : MISSING_INNER_CLASS_ATTRIBUTE;
this.enclosing = enclosing;
this.hash = computeHashCode();
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 f5698aa..42e0bb1 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
@@ -191,7 +191,7 @@
throw new LambdaStructureError("unexpected method annotations [" +
method.annotations.toSmaliString() + "] on " + method.method.toSourceString());
}
- if (!method.parameterAnnotations.isEmpty()) {
+ if (!method.parameterAnnotationsList.isEmpty()) {
throw new LambdaStructureError("unexpected method parameters annotations [" +
method.annotations.toSmaliString() + "] on " + method.method.toSourceString());
}
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 e49ad85..2970fb4 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -13,7 +13,6 @@
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.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexEncodedField;
@@ -34,6 +33,7 @@
import com.android.tools.r8.graph.DexValue.UnknownDexValue;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.JarClassFileReader;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.naming.ProguardMapSupplier;
import com.android.tools.r8.utils.ExceptionUtils;
@@ -252,7 +252,7 @@
}
}
writeAnnotations(visitor::visitAnnotation, method.annotations.annotations);
- writeParameterAnnotations(visitor, method.parameterAnnotations);
+ writeParameterAnnotations(visitor, method.parameterAnnotationsList);
if (!method.accessFlags.isAbstract() && !method.accessFlags.isNative()) {
writeCode(method.getCode(), visitor);
}
@@ -260,21 +260,21 @@
}
private void writeParameterAnnotations(
- MethodVisitor visitor, DexAnnotationSetRefList parameterAnnotations) {
- int missingParameterAnnotations = parameterAnnotations.getMissingParameterAnnotations();
- for (int i = 0; i < missingParameterAnnotations; i++) {
- AnnotationVisitor av =
- visitor.visitParameterAnnotation(i, JarClassFileReader.SYNTHETIC_ANNOTATION, false);
- if (av != null) {
- av.visitEnd();
+ MethodVisitor visitor, ParameterAnnotationsList parameterAnnotations) {
+ for (int i = 0; i < parameterAnnotations.size(); i++) {
+ if (parameterAnnotations.isMissing(i)) {
+ AnnotationVisitor av =
+ visitor.visitParameterAnnotation(i, JarClassFileReader.SYNTHETIC_ANNOTATION, false);
+ if (av != null) {
+ av.visitEnd();
+ }
+ } else {
+ int iFinal = i;
+ writeAnnotations(
+ (d, vis) -> visitor.visitParameterAnnotation(iFinal, d, vis),
+ parameterAnnotations.get(i).annotations);
}
}
- for (int i = 0; i < parameterAnnotations.values.length; i++) {
- int parameterIndex = i + missingParameterAnnotations;
- writeAnnotations(
- (d, vis) -> visitor.visitParameterAnnotation(parameterIndex, d, vis),
- parameterAnnotations.values[i].annotations);
- }
}
private interface AnnotationConsumer {
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 871812a..28ca9fc 100644
--- a/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AnnotationRemover.java
@@ -5,8 +5,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexAnnotation;
-import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -15,9 +13,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.function.Predicate;
public class AnnotationRemover {
@@ -127,20 +122,20 @@
keep.ensureValid(options.forceProguardCompatibility, compatibility);
for (DexProgramClass clazz : appInfo.classes()) {
stripAttributes(clazz);
- clazz.annotations = stripAnnotations(clazz.annotations, this::filterAnnotations);
+ clazz.annotations = clazz.annotations.keepIf(this::filterAnnotations);
clazz.forEachMethod(this::processMethod);
clazz.forEachField(this::processField);
}
}
private void processMethod(DexEncodedMethod method) {
- method.annotations = stripAnnotations(method.annotations, this::filterAnnotations);
- method.parameterAnnotations = stripAnnotations(method.parameterAnnotations,
- this::filterParameterAnnotations);
+ method.annotations = method.annotations.keepIf(this::filterAnnotations);
+ method.parameterAnnotationsList =
+ method.parameterAnnotationsList.keepIf(this::filterParameterAnnotations);
}
private void processField(DexEncodedField field) {
- field.annotations = stripAnnotations(field.annotations, this::filterAnnotations);
+ field.annotations = field.annotations.keepIf(this::filterAnnotations);
}
private void stripAttributes(DexProgramClass clazz) {
@@ -152,52 +147,4 @@
}
}
- private DexAnnotationSetRefList stripAnnotations(DexAnnotationSetRefList annotations,
- Predicate<DexAnnotation> filter) {
- DexAnnotationSet[] filtered = null;
- for (int i = 0; i < annotations.values.length; i++) {
- DexAnnotationSet updated = stripAnnotations(annotations.values[i], filter);
- if (updated != annotations.values[i]) {
- if (filtered == null) {
- filtered = annotations.values.clone();
- filtered[i] = updated;
- }
- }
- }
- if (filtered == null) {
- return annotations;
- } else {
- if (Arrays.stream(filtered).allMatch(DexAnnotationSet::isEmpty)) {
- return DexAnnotationSetRefList.empty();
- }
- return new DexAnnotationSetRefList(filtered);
- }
- }
-
- private DexAnnotationSet stripAnnotations(DexAnnotationSet annotations,
- Predicate<DexAnnotation> filter) {
- ArrayList<DexAnnotation> filtered = null;
- for (int i = 0; i < annotations.annotations.length; i++) {
- DexAnnotation annotation = annotations.annotations[i];
- if (filter.test(annotation)) {
- if (filtered != null) {
- filtered.add(annotation);
- }
- } else {
- if (filtered == null) {
- filtered = new ArrayList<>(annotations.annotations.length);
- for (int j = 0; j < i; j++) {
- filtered.add(annotations.annotations[j]);
- }
- }
- }
- }
- if (filtered == null) {
- return annotations;
- } else if (filtered.isEmpty()) {
- return DexAnnotationSet.empty();
- } else {
- return new DexAnnotationSet(filtered.toArray(new DexAnnotation[filtered.size()]));
- }
- }
}
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 25df235..c359fc7 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -15,7 +15,6 @@
import com.android.tools.r8.graph.AppInfoWithSubtyping;
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.DexApplication;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
@@ -552,14 +551,18 @@
private void processAnnotations(DexAnnotation[] annotations) {
for (DexAnnotation annotation : annotations) {
- DexType type = annotation.annotation.type;
- if (liveTypes.contains(type)) {
- // The type of this annotation is already live, so pick up its dependencies.
- handleAnnotationOfLiveType(annotation);
- } else {
- // Remember this annotation for later.
- deferredAnnotations.computeIfAbsent(type, ignore -> new HashSet<>()).add(annotation);
- }
+ processAnnotation(annotation);
+ }
+ }
+
+ private void processAnnotation(DexAnnotation annotation) {
+ DexType type = annotation.annotation.type;
+ if (liveTypes.contains(type)) {
+ // The type of this annotation is already live, so pick up its dependencies.
+ handleAnnotationOfLiveType(annotation);
+ } else {
+ // Remember this annotation for later.
+ deferredAnnotations.computeIfAbsent(type, ignore -> new HashSet<>()).add(annotation);
}
}
@@ -1239,9 +1242,7 @@
}
}
processAnnotations(method.annotations.annotations);
- for (DexAnnotationSet parameterAnnotation : method.parameterAnnotations.values) {
- processAnnotations(parameterAnnotation.annotations);
- }
+ method.parameterAnnotationsList.forEachAnnotation(this::processAnnotation);
if (protoLiteExtension != null && protoLiteExtension.appliesTo(method)) {
protoLiteExtension.processMethod(method, new UseRegistry(method), protoLiteFields);
} else {
diff --git a/src/test/java/com/android/tools/r8/debug/ContinuousSteppingTest.java b/src/test/java/com/android/tools/r8/debug/ContinuousSteppingTest.java
index 45e3c96..eca0441 100644
--- a/src/test/java/com/android/tools/r8/debug/ContinuousSteppingTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ContinuousSteppingTest.java
@@ -51,8 +51,9 @@
.add(KotlinD8Config.DEBUGGEE_KOTLIN_JAR, ContinuousSteppingTest::allVersions)
.addAll(findAllJarsIn(Paths.get(ToolHelper.EXAMPLES_ANDROID_N_BUILD_DIR)),
ContinuousSteppingTest::fromAndroidN)
- .addAll(findAllJarsIn(Paths.get(ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR)),
- ContinuousSteppingTest::fromAndroidO)
+ // TODO(b/79911828) Investigate timeout issues for Android O examples.
+ // .addAll(findAllJarsIn(Paths.get(ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR)),
+ // ContinuousSteppingTest::fromAndroidO)
.build();
private static final Map<Path, DebugTestConfig> compiledJarConfig = new HashMap<>();
diff --git a/src/test/java/com/android/tools/r8/debug/UnusedCheckCastTargetOptimizationTest.java b/src/test/java/com/android/tools/r8/debug/UnusedCheckCastTargetOptimizationTest.java
new file mode 100644
index 0000000..8fd6cd8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/UnusedCheckCastTargetOptimizationTest.java
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, 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.debug;
+
+public class UnusedCheckCastTargetOptimizationTest {
+
+ class Super {}
+
+ class Subclass extends Super {}
+
+ public static void main(String[] args) {
+ Super[] b = new Subclass[10];
+ Subclass[] c = (Subclass[]) b;
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debug/UnusedCheckCastTargetOptimizationTestRunner.java b/src/test/java/com/android/tools/r8/debug/UnusedCheckCastTargetOptimizationTestRunner.java
new file mode 100644
index 0000000..2b93218
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debug/UnusedCheckCastTargetOptimizationTestRunner.java
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, 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.debug;
+
+import org.junit.Test;
+
+public class UnusedCheckCastTargetOptimizationTestRunner extends DebugTestBase {
+
+ private static final Class MAIN_CLASS = UnusedCheckCastTargetOptimizationTest.class;
+ private static final Class SUPER_CLASS = UnusedCheckCastTargetOptimizationTest.Super.class;
+ private static final Class SUBCLASS_CLASS = UnusedCheckCastTargetOptimizationTest.Subclass.class;
+ private static final String FILE = MAIN_CLASS.getSimpleName() + ".java";
+ private static final String NAME = MAIN_CLASS.getCanonicalName();
+
+ @Test
+ public void test() throws Throwable {
+ runDebugTest(
+ new D8DebugTestConfig().compileAndAddClasses(temp, MAIN_CLASS, SUPER_CLASS, SUBCLASS_CLASS),
+ NAME,
+ breakpoint(NAME, "main", 14),
+ run(),
+ checkLine(FILE, 14),
+ checkLocal("b"),
+ checkNoLocal("c"),
+ stepOver(),
+ checkLine(FILE, 15),
+ checkLocal("b"),
+ checkLocal("c"),
+ run());
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
index 9edc735..89935a7 100644
--- a/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
+++ b/src/test/java/com/android/tools/r8/dex/SharedClassWritingTest.java
@@ -11,7 +11,6 @@
import com.android.tools.r8.errors.DexOverflowException;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexCode.Try;
@@ -25,6 +24,7 @@
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.origin.SynthesizedOrigin;
import com.android.tools.r8.utils.DefaultDiagnosticsHandler;
@@ -80,7 +80,7 @@
holder, dexItemFactory.createProto(dexItemFactory.voidType), "theMethod"),
MethodAccessFlags.fromSharedAccessFlags(Constants.ACC_PUBLIC, false),
DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(),
+ ParameterAnnotationsList.empty(),
code);
}
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 2ff2f71..9de9f5a 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -29,7 +29,6 @@
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexAnnotationSet;
-import com.android.tools.r8.graph.DexAnnotationSetRefList;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -40,6 +39,7 @@
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DirectMappedDexApplication;
import com.android.tools.r8.graph.MethodAccessFlags;
+import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Position;
@@ -617,7 +617,7 @@
DexString.EMPTY_ARRAY),
access,
DexAnnotationSet.empty(),
- DexAnnotationSetRefList.empty(),
+ ParameterAnnotationsList.empty(),
code);
IRCode ir = code.buildIR(method, options, Origin.unknown());
RegisterAllocator allocator = new LinearScanRegisterAllocator(ir, options);
diff --git a/tools/archive.py b/tools/archive.py
index 76df65e..07f138a 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -3,22 +3,25 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-import gradle
import create_maven_release
-import d8
+import gradle
import os
-import r8
+import shutil
import subprocess
import sys
+import toolhelper
import utils
-import shutil
import zipfile
ARCHIVE_BUCKET = 'r8-releases'
+def GetToolVersion(jar_path):
+ output = subprocess.check_output(['java', '-jar', jar_path, '--version'])
+ return output.splitlines()[0].strip()
+
def GetVersion():
- r8_version = r8.run(['--version'], build = False).splitlines()[0].strip()
- d8_version = d8.run(['--version'], build = False).splitlines()[0].strip()
+ r8_version = GetToolVersion(utils.R8_JAR)
+ d8_version = GetToolVersion(utils.D8_JAR)
# The version printed is "D8 vVERSION_NUMBER" and "R8 vVERSION_NUMBER"
# Sanity check that versions match.
if d8_version.split()[1] != r8_version.split()[1]:
diff --git a/tools/bisect.py b/tools/bisect.py
index c8d1501..74c880e 100755
--- a/tools/bisect.py
+++ b/tools/bisect.py
@@ -3,33 +3,8 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-import gradle
-import os
-import subprocess
import sys
-import utils
-
-JAR = os.path.join(utils.REPO_ROOT, 'build', 'libs', 'bisect.jar')
-
-def run(args, build, debug):
- if build:
- gradle.RunGradle(['bisect'])
- cmd = ['java']
- if debug:
- cmd.append('-ea')
- cmd.extend(['-jar', JAR])
- cmd.extend(args)
- subprocess.check_call(cmd)
-
-def main():
- build = True
- args = []
- for arg in sys.argv[1:]:
- if arg in ("--build", "--no-build"):
- build = arg == "--build"
- else:
- args.append(arg)
- run(args, build, True)
+import toolhelper
if __name__ == '__main__':
- sys.exit(main())
+ sys.exit(toolhelper.run('bisect', sys.argv[1:]))
diff --git a/tools/compatdx.py b/tools/compatdx.py
index 25a59db..c4cb320 100755
--- a/tools/compatdx.py
+++ b/tools/compatdx.py
@@ -3,42 +3,8 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-import gradle
-import os
-import subprocess
import sys
-import utils
-
-def run(args, build = True, debug = True, profile = False, track_memory_file=None):
- if build:
- gradle.RunGradle(['CompatDX'])
- cmd = []
- if track_memory_file:
- cmd.extend(['tools/track_memory.sh', track_memory_file])
- cmd.append('java')
- if debug:
- cmd.append('-ea')
- if profile:
- cmd.append('-agentlib:hprof=cpu=samples,interval=1,depth=8')
- cmd.extend(['-jar', utils.COMPATDX_JAR])
- cmd.extend(args)
- subprocess.check_call(cmd)
-
-def main():
- build = True
- args = []
- for arg in sys.argv[1:]:
- if arg in ("--build", "--no-build"):
- build = arg == "--build"
- else:
- args.append(arg)
- try:
- run(args, build)
- except subprocess.CalledProcessError as e:
- # In case anything relevant was printed to stdout, normally this is already
- # on stderr.
- print(e.output)
- return e.returncode
+import toolhelper
if __name__ == '__main__':
- sys.exit(main())
+ sys.exit(toolhelper.run('compatdx', sys.argv[1:]))
diff --git a/tools/compatproguard.py b/tools/compatproguard.py
new file mode 100755
index 0000000..10542e3
--- /dev/null
+++ b/tools/compatproguard.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('compatproguard', sys.argv[1:]))
diff --git a/tools/d8.py b/tools/d8.py
index bf97845..18a4a67 100755
--- a/tools/d8.py
+++ b/tools/d8.py
@@ -3,46 +3,8 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-import gradle
-import os
-import subprocess
import sys
-import utils
-
-def run(args, build=True, debug=True, profile=False,
- track_memory_file=None):
- if build:
- gradle.RunGradle(['D8'])
- cmd = []
- if track_memory_file:
- cmd.extend(['tools/track_memory.sh', track_memory_file])
- cmd.append('java')
- if debug:
- cmd.append('-ea')
- if profile:
- cmd.append('-agentlib:hprof=cpu=samples,interval=1,depth=8')
- cmd.extend(['-jar', utils.D8_JAR])
- cmd.extend(args)
- utils.PrintCmd(cmd)
- result = subprocess.check_output(cmd)
- print(result)
- return result
-
-def main():
- build = True
- args = []
- for arg in sys.argv[1:]:
- if arg in ("--build", "--no-build"):
- build = arg == "--build"
- else:
- args.append(arg)
- try:
- run(args, build)
- except subprocess.CalledProcessError as e:
- # In case anything relevant was printed to stdout, normally this is already
- # on stderr.
- print(e.output)
- return e.returncode
+import toolhelper
if __name__ == '__main__':
- sys.exit(main())
+ sys.exit(toolhelper.run('d8', sys.argv[1:]))
diff --git a/tools/d8logger.py b/tools/d8logger.py
new file mode 100755
index 0000000..9fb3508
--- /dev/null
+++ b/tools/d8logger.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('d8logger', sys.argv[1:]))
diff --git a/tools/dexfilemerger.py b/tools/dexfilemerger.py
new file mode 100755
index 0000000..7bdfc22
--- /dev/null
+++ b/tools/dexfilemerger.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('dexfilemerger', sys.argv[1:]))
diff --git a/tools/dexsegments.py b/tools/dexsegments.py
new file mode 100755
index 0000000..f984063
--- /dev/null
+++ b/tools/dexsegments.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('dexsegments', sys.argv[1:]))
diff --git a/tools/dexsplitter.py b/tools/dexsplitter.py
new file mode 100755
index 0000000..415b149
--- /dev/null
+++ b/tools/dexsplitter.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('dexsplitter', sys.argv[1:]))
diff --git a/tools/disasm.py b/tools/disasm.py
new file mode 100755
index 0000000..0d2599a
--- /dev/null
+++ b/tools/disasm.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('disasm', sys.argv[1:]))
diff --git a/tools/extractmarker.py b/tools/extractmarker.py
new file mode 100755
index 0000000..36a9c88
--- /dev/null
+++ b/tools/extractmarker.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('extractmarker', sys.argv[1:]))
diff --git a/tools/jardiff.py b/tools/jardiff.py
new file mode 100755
index 0000000..894131c
--- /dev/null
+++ b/tools/jardiff.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('jardiff', sys.argv[1:]))
diff --git a/tools/maindex.py b/tools/maindex.py
new file mode 100755
index 0000000..ff5329a
--- /dev/null
+++ b/tools/maindex.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# Copyright (c) 2018, 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.
+
+import sys
+import toolhelper
+
+if __name__ == '__main__':
+ sys.exit(toolhelper.run('maindex', sys.argv[1:]))
diff --git a/tools/r8.py b/tools/r8.py
index 3ae4da7..60c60a0 100755
--- a/tools/r8.py
+++ b/tools/r8.py
@@ -3,46 +3,8 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-import gradle
-import os
-import subprocess
import sys
-import utils
-
-def run(args, build=True, debug=True, profile=False,
- track_memory_file=None):
- if build:
- gradle.RunGradle(['r8'])
- cmd = []
- if track_memory_file:
- cmd.extend(['tools/track_memory.sh', track_memory_file])
- cmd.append('java')
- if debug:
- cmd.append('-ea')
- if profile:
- cmd.append('-agentlib:hprof=cpu=samples,interval=1,depth=8')
- cmd.extend(['-jar', utils.R8_JAR])
- cmd.extend(args)
- utils.PrintCmd(cmd)
- result = subprocess.check_output(cmd)
- print(result)
- return result
-
-def main():
- build = True
- args = []
- for arg in sys.argv[1:]:
- if arg in ("--build", "--no-build"):
- build = arg == "--build"
- else:
- args.append(arg)
- try:
- run(args, build)
- except subprocess.CalledProcessError as e:
- # In case anything relevant was printed to stdout, normally this is already
- # on stderr.
- print(e.output)
- return e.returncode
+import toolhelper
if __name__ == '__main__':
- sys.exit(main())
+ sys.exit(toolhelper.run('r8', sys.argv[1:]))
diff --git a/tools/run-d8-on-gmscore.py b/tools/run-d8-on-gmscore.py
index 63865d0..b1bdc6e 100755
--- a/tools/run-d8-on-gmscore.py
+++ b/tools/run-d8-on-gmscore.py
@@ -3,11 +3,11 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-import d8
import gmscore_data
import optparse
import os
import sys
+import toolhelper
def ParseOptions():
result = optparse.OptionParser()
@@ -70,8 +70,13 @@
with open(options.dump_args_file, 'w') as args_file:
args_file.writelines([arg + os.linesep for arg in args])
else:
- d8.run(args, not options.no_build, not options.no_debug, options.profile,
- options.track_memory_to_file)
+ toolhelper.run(
+ 'd8',
+ args,
+ build=not options.no_build,
+ debug=not options.no_debug,
+ profile=options.profile,
+ track_memory_to_file=options.track_memory_to_file)
if __name__ == '__main__':
sys.exit(main())
diff --git a/tools/run_on_app.py b/tools/run_on_app.py
index b9bcc60..571d96d 100755
--- a/tools/run_on_app.py
+++ b/tools/run_on_app.py
@@ -10,10 +10,9 @@
import sys
import time
-import d8
import gmail_data
import gmscore_data
-import r8
+import toolhelper
import utils
import youtube_data
@@ -191,22 +190,20 @@
if options.print_memoryuse and not options.track_memory_to_file:
options.track_memory_to_file = os.path.join(temp,
utils.MEMORY_USE_TMP_FILE)
- if options.compiler == 'd8':
- d8.run(args, not options.no_build, not options.no_debug,
- options.profile, options.track_memory_to_file)
- else:
- if app_provided_pg_conf:
- # Ensure that output of -printmapping and -printseeds go to the output
- # location and not where the app Proguard configuration places them.
- if outdir.endswith('.zip') or outdir.endswith('.jar'):
- pg_outdir = os.path.dirname(outdir)
- else:
- pg_outdir = outdir
- additional_pg_conf = GenerateAdditionalProguardConfiguration(
- temp, os.path.abspath(pg_outdir))
- args.extend(['--pg-conf', additional_pg_conf])
- r8.run(args, not options.no_build, not options.no_debug,
- options.profile, options.track_memory_to_file)
+ if options.compiler == 'r8' and app_provided_pg_conf:
+ # Ensure that output of -printmapping and -printseeds go to the output
+ # location and not where the app Proguard configuration places them.
+ if outdir.endswith('.zip') or outdir.endswith('.jar'):
+ pg_outdir = os.path.dirname(outdir)
+ else:
+ pg_outdir = outdir
+ additional_pg_conf = GenerateAdditionalProguardConfiguration(
+ temp, os.path.abspath(pg_outdir))
+ args.extend(['--pg-conf', additional_pg_conf])
+ toolhelper.run(options.compiler, args, build=not options.no_build,
+ debug=not options.no_debug,
+ profile=options.profile,
+ track_memory_to_file=options.track_memory_to_file)
if options.print_memoryuse:
print('{}(MemoryUse): {}'
.format(options.print_memoryuse,
diff --git a/tools/toolhelper.py b/tools/toolhelper.py
new file mode 100644
index 0000000..a7f509c
--- /dev/null
+++ b/tools/toolhelper.py
@@ -0,0 +1,38 @@
+# Copyright (c) 2018, 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.
+
+import gradle
+import os
+import subprocess
+import sys
+import utils
+
+def run(tool, args, build=None, debug=True,
+ profile=False, track_memory_file=None):
+ if build is None:
+ build, args = extract_build_from_args(args)
+ if build:
+ gradle.RunGradle(['r8'])
+ cmd = []
+ if track_memory_file:
+ cmd.extend(['tools/track_memory.sh', track_memory_file])
+ cmd.append('java')
+ if debug:
+ cmd.append('-ea')
+ if profile:
+ cmd.append('-agentlib:hprof=cpu=samples,interval=1,depth=8')
+ cmd.extend(['-jar', utils.R8_JAR, tool])
+ cmd.extend(args)
+ utils.PrintCmd(cmd)
+ return subprocess.call(cmd)
+
+def extract_build_from_args(input_args):
+ build = True
+ args = []
+ for arg in input_args:
+ if arg in ("--build", "--no-build"):
+ build = arg == "--build"
+ else:
+ args.append(arg)
+ return build, args