Merge "Value-based worklist in type analysis."
diff --git a/build.gradle b/build.gradle
index 8893820..9b8d59b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,6 +25,22 @@
}
}
+ext {
+ androidSupportVersion = '25.4.0'
+ apacheCommonsVersion = '1.12'
+ asmVersion = '6.0'
+ autoValueVersion = '1.5'
+ espressoVersion = '3.0.0'
+ fastutilVersion = '7.2.0'
+ guavaVersion = '23.0'
+ joptSimpleVersion = '4.6'
+ jsonSimpleVersion = '1.1'
+ junitVersion = '4.12'
+ kotlinVersion = '1.2.0'
+ protobufVersion = '3.0.0'
+ smaliVersion = '2.2b4'
+}
+
def errorProneConfiguration = [
'-XepDisableAllChecks',
// D8 want to use reference equality, thus disable the checker explicitly
@@ -192,48 +208,48 @@
}
dependencies {
- compile 'net.sf.jopt-simple:jopt-simple:4.6'
- compile 'com.googlecode.json-simple:json-simple:1.1'
+ compile "net.sf.jopt-simple:jopt-simple:$joptSimpleVersion"
+ compile "com.googlecode.json-simple:json-simple:$jsonSimpleVersion"
// Include all of guava when compiling the code, but exclude annotations that we don't
// need from the packaging.
- compileOnly('com.google.guava:guava:23.0')
- compile('com.google.guava:guava:23.0', {
+ compileOnly("com.google.guava:guava:$guavaVersion")
+ compile("com.google.guava:guava:$guavaVersion", {
exclude group: 'com.google.errorprone'
exclude group: 'com.google.code.findbugs'
exclude group: 'com.google.j2objc'
exclude group: 'org.codehaus.mojo'
})
- compile group: 'it.unimi.dsi', name: 'fastutil', version: '7.2.0'
- compile group: 'org.ow2.asm', name: 'asm', version: '6.0'
- compile group: 'org.ow2.asm', name: 'asm-commons', version: '6.0'
- compile group: 'org.ow2.asm', name: 'asm-tree', version: '6.0'
- compile group: 'org.ow2.asm', name: 'asm-analysis', version: '6.0'
- compile group: 'org.ow2.asm', name: 'asm-util', version: '6.0'
+ compile group: 'it.unimi.dsi', name: 'fastutil', version: fastutilVersion
+ compile group: 'org.ow2.asm', name: 'asm', version: asmVersion
+ compile group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion
+ compile group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion
+ compile group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion
+ compile group: 'org.ow2.asm', name: 'asm-util', version: asmVersion
testCompile sourceSets.examples.output
- testCompile 'junit:junit:4.12'
- testCompile group: 'org.smali', name: 'smali', version: '2.2b4'
+ testCompile "junit:junit:$junitVersion"
+ testCompile group: 'org.smali', name: 'smali', version: smaliVersion
testCompile files('third_party/jasmin/jasmin-2.4.jar')
testCompile files('third_party/jdwp-tests/apache-harmony-jdwp-tests-host.jar')
testCompile files('third_party/ddmlib/ddmlib.jar')
- bsPatchCompile group: 'org.apache.commons', name: 'commons-compress', version: '1.12'
- jctfCommonCompile 'junit:junit:4.12'
- jctfTestsCompile 'junit:junit:4.12'
+ bsPatchCompile "org.apache.commons:commons-compress:$apacheCommonsVersion"
+ jctfCommonCompile "junit:junit:$junitVersion"
+ jctfTestsCompile "junit:junit:$junitVersion"
jctfTestsCompile sourceSets.jctfCommon.output
- examplesAndroidOCompile group: 'org.ow2.asm', name: 'asm', version: '6.0'
- examplesAndroidPCompile group: 'org.ow2.asm', name: 'asm', version: '6.0'
+ examplesAndroidOCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion
+ examplesAndroidPCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion
// Import Guava for @Nullable annotation
- examplesCompile 'com.google.guava:guava:23.0'
- examplesCompile 'com.google.protobuf:protobuf-lite:3.0.0'
- examplesCompileOnly "com.google.auto.value:auto-value:1.5"
- examplesRuntime 'com.google.protobuf:protobuf-lite:3.0.0'
- supportLibs 'com.android.support:support-v4:25.4.0'
- supportLibs 'junit:junit:4.12'
- supportLibs 'com.android.support.test.espresso:espresso-core:3.0.0'
+ examplesCompile "com.google.guava:guava:$guavaVersion"
+ examplesCompile "com.google.protobuf:protobuf-lite:$protobufVersion"
+ examplesCompileOnly "com.google.auto.value:auto-value:$autoValueVersion"
+ examplesRuntime "com.google.protobuf:protobuf-lite:$protobufVersion"
+ supportLibs "com.android.support:support-v4:$androidSupportVersion"
+ supportLibs "junit:junit:$junitVersion"
+ supportLibs "com.android.support.test.espresso:espresso-core:$espressoVersion"
apiUsageSampleCompile sourceSets.main.output
- debugTestResourcesKotlinCompileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.2.0'
- examplesKotlinCompileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.2.0'
- kotlinR8TestResourcesCompileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.2.0'
- apt 'com.google.auto.value:auto-value:1.5'
+ debugTestResourcesKotlinCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
+ examplesKotlinCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
+ kotlinR8TestResourcesCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
+ apt "com.google.auto.value:auto-value:$autoValueVersion"
}
configurations.bsPatchCompile.extendsFrom configurations.compile
@@ -245,11 +261,11 @@
protobuf {
protoc {
// Download from repositories
- artifact = 'com.google.protobuf:protoc:3.0.0'
+ artifact = "com.google.protobuf:protoc:$protobufVersion"
}
plugins {
javalite {
- artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
+ artifact = "com.google.protobuf:protoc-gen-javalite:$protobufVersion"
}
}
generateProtoTasks {
@@ -1167,13 +1183,17 @@
task buildKotlinR8TestResources {
def examplesDir = file("src/test/kotlinR8TestResources")
examplesDir.eachDir { dir ->
- def name = dir.getName()
- def taskName = "jar_kotlinR8TestResources_${name}"
- task "${taskName}"(type: kotlin.Kotlinc) {
- source = fileTree(dir: file("${examplesDir}/${name}"), include: '**/*.kt')
- destination = file("build/test/kotlinR8TestResources/${name}.jar")
+ kotlin.Kotlinc.KotlinTargetVersion.values().each { kotlinTargetVersion ->
+ def name = dir.getName()
+ def taskName = "jar_kotlinR8TestResources_${name}_${kotlinTargetVersion}"
+ def outputFile = "build/test/kotlinR8TestResources/${kotlinTargetVersion}/${name}.jar"
+ task "${taskName}"(type: kotlin.Kotlinc) {
+ source = fileTree(dir: file("${examplesDir}/${name}"), include: '**/*.kt')
+ destination = file(outputFile)
+ targetVersion = kotlinTargetVersion
+ }
+ dependsOn taskName
}
- dependsOn taskName
}
}
diff --git a/buildSrc/src/main/java/kotlin/Kotlinc.java b/buildSrc/src/main/java/kotlin/Kotlinc.java
index 261acc3..0c0a50a 100644
--- a/buildSrc/src/main/java/kotlin/Kotlinc.java
+++ b/buildSrc/src/main/java/kotlin/Kotlinc.java
@@ -19,16 +19,29 @@
import utils.Utils;
/**
- * Gradle task to compile Kotlin source files.
+ * Gradle task to compile Kotlin source files. By default the generated classes target Java 1.6.
*/
public class Kotlinc extends DefaultTask {
+ enum KotlinTargetVersion {
+ JAVA_6("1.6"),
+ JAVA_8("1.8");
+
+ private final String optionName;
+
+ KotlinTargetVersion(String optionName) {
+ this.optionName = optionName;
+ }
+ }
+
@InputFiles
private FileTree source;
@OutputFile
private File destination;
+ private KotlinTargetVersion targetVersion = KotlinTargetVersion.JAVA_6;
+
public FileTree getSource() {
return source;
}
@@ -45,6 +58,14 @@
this.destination = destination;
}
+ public KotlinTargetVersion getTargetVersion() {
+ return targetVersion;
+ }
+
+ public void setTargetVersion(KotlinTargetVersion targetVersion) {
+ this.targetVersion = targetVersion;
+ }
+
@TaskAction
public void compile() {
getProject().exec(new Action<ExecSpec>() {
@@ -57,6 +78,7 @@
execSpec.setExecutable(kotlincExecPath.toFile());
execSpec.args("-include-runtime");
execSpec.args("-nowarn");
+ execSpec.args("-jvm-target", targetVersion.optionName);
execSpec.args("-d", destination.getCanonicalPath());
execSpec.args(source.getFiles());
} catch (IOException e) {
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index 2cdfd76..5369069 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -372,7 +372,7 @@
classes = sortClassesByPackage(classes, originalNames);
new PackageSplitPopulator(
- filesForDistribution, classes, originalNames, null, application.dexItemFactory,
+ filesForDistribution, classes, originalNames, application.dexItemFactory,
fillStrategy, fileIndexOffset, writer.namingLens)
.call();
return virtualFiles;
@@ -701,7 +701,6 @@
private final List<DexProgramClass> classes;
private final Map<DexProgramClass, String> originalNames;
- private final Set<String> previousPrefixes;
private final DexItemFactory dexItemFactory;
private final FillStrategy fillStrategy;
private final VirtualFileCycler cycler;
@@ -710,14 +709,12 @@
List<VirtualFile> files,
Set<DexProgramClass> classes,
Map<DexProgramClass, String> originalNames,
- Set<String> previousPrefixes,
DexItemFactory dexItemFactory,
FillStrategy fillStrategy,
int fileIndexOffset,
NamingLens namingLens) {
this.classes = new ArrayList<>(classes);
this.originalNames = originalNames;
- this.previousPrefixes = previousPrefixes;
this.dexItemFactory = dexItemFactory;
this.fillStrategy = fillStrategy;
this.cycler = new VirtualFileCycler(files, namingLens, fileIndexOffset);
@@ -774,9 +771,7 @@
// com.android.* and com.android.foo.*.
do {
newPrefix = extractPrefixToken(++prefixLength, originalName, false);
- } while (currentPrefix != null &&
- (currentPrefix.startsWith(newPrefix)
- || conflictsWithPreviousPrefix(newPrefix, originalName)));
+ } while (currentPrefix != null && currentPrefix.startsWith(newPrefix));
// Don't set the current prefix if we did not extract one.
if (!newPrefix.equals("")) {
currentPrefix = extractPrefixToken(prefixLength, originalName, true);
@@ -871,28 +866,5 @@
}
return current;
}
-
- private boolean conflictsWithPreviousPrefix(String newPrefix, String originalName) {
- if (previousPrefixes == null) {
- return false;
- }
- for (String previous : previousPrefixes) {
- // Check whether a previous prefix starts with this new prefix and, if so,
- // whether the new prefix already is maximal. So for example a new prefix of
- // foo.bar
- // would match
- // foo.bar.goo.*
- // However, if the original class is
- // foo.bar.X
- // then this prefix is the best we can do, and will not turn into a .* prefix and
- // thus does not conflict.
- if (previous.startsWith(newPrefix)
- && (originalName.lastIndexOf('.') > newPrefix.length())) {
- return true;
- }
- }
-
- return false;
- }
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
index dba4842..35108bd 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
@@ -213,8 +213,12 @@
@Override
public void collectIndexedItems(IndexedItemCollection collection) {
- name.collectIndexedItems(collection);
- type.collectIndexedItems(collection);
+ if (name != null) {
+ name.collectIndexedItems(collection);
+ }
+ if (type != null) {
+ type.collectIndexedItems(collection);
+ }
if (signature != null) {
signature.collectIndexedItems(collection);
}
@@ -234,8 +238,8 @@
public int hashCode() {
return Constants.DBG_START_LOCAL
+ registerNum * 7
- + name.hashCode() * 13
- + type.hashCode() * 17
+ + Objects.hashCode(name) * 13
+ + Objects.hashCode(type) * 17
+ Objects.hashCode(signature) * 19;
}
@@ -248,10 +252,10 @@
if (registerNum != o.registerNum) {
return false;
}
- if (!name.equals(o.name)) {
+ if (!Objects.equals(name, o.name)) {
return false;
}
- if (!type.equals(o.type)) {
+ if (!Objects.equals(type, o.type)) {
return false;
}
return Objects.equals(signature, o.signature);
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 03c4c33..82eb242 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.function.Consumer;
@@ -89,18 +88,19 @@
@Override
void forAllRenamedTypes(Consumer<DexType> consumer) {
- Iterables.filter(renaming.keySet(), DexType.class).forEach(consumer);
+ renaming.keySet().stream()
+ .filter(DexType.class::isInstance)
+ .map(DexType.class::cast)
+ .forEach(consumer);
}
@Override
<T extends DexItem> Map<String, T> getRenamedItems(
Class<T> clazz, Predicate<T> predicate, Function<T, String> namer) {
- return renaming
- .keySet()
- .stream()
- .filter(item -> (item.getClass() == clazz) && predicate.test(clazz.cast(item)))
+ return renaming.keySet().stream()
+ .filter(item -> (clazz.isInstance(item) && predicate.test(clazz.cast(item))))
.map(clazz::cast)
- .collect(ImmutableMap.toImmutableMap(namer::apply, i -> i));
+ .collect(ImmutableMap.toImmutableMap(namer, i -> i));
}
/**
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index d9f10ae..cc325e2 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1245,4 +1245,19 @@
options,
null);
}
+
+ public enum KotlinTargetVersion {
+ JAVA_6("JAVA_6"),
+ JAVA_8("JAVA_8");
+
+ private final String folderName;
+
+ KotlinTargetVersion(String folderName) {
+ this.folderName = folderName;
+ }
+
+ public String getFolderName() {
+ return folderName;
+ }
+ }
}
diff --git a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
index 15c20c5..9f520a2 100644
--- a/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
+++ b/src/test/java/com/android/tools/r8/kotlin/AbstractR8KotlinTestBase.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.OutputMode;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
@@ -21,24 +22,35 @@
import com.android.tools.r8.utils.DexInspector.ClassSubject;
import com.android.tools.r8.utils.DexInspector.MethodSubject;
import com.android.tools.r8.utils.FileUtils;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Map;
import org.junit.Assume;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
-// TODO(shertz) also run with backend 1.8
+@RunWith(Parameterized.class)
public abstract class AbstractR8KotlinTestBase extends TestBase {
- public static final String KOTLIN_R8_TEST_RESOURCES_BUILD_DIR =
- ToolHelper.TESTS_BUILD_DIR + "/kotlinR8TestResources";
-
- protected final boolean allowAccessModification;
-
- protected AbstractR8KotlinTestBase(boolean allowAccessModification) {
- this.allowAccessModification = allowAccessModification;
+ @Parameters(name = "{0}_{1}")
+ public static Collection<Object[]> data() {
+ ImmutableList.Builder<Object[]> builder = new Builder<>();
+ for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
+ builder.add(new Object[]{Boolean.TRUE, targetVersion});
+ builder.add(new Object[]{Boolean.FALSE, targetVersion});
+ }
+ return builder.build();
}
+ @Parameter(0) public boolean allowAccessModification;
+ @Parameter(1) public KotlinTargetVersion targetVersion;
+
protected static void checkMethodIsInvokedAtLeastOnce(DexCode dexCode,
MethodSignature... methodSignatures) {
for (MethodSignature methodSignature : methodSignatures) {
@@ -143,8 +155,7 @@
AndroidAppInspector inspector) throws Exception {
Assume.assumeTrue(ToolHelper.artSupported());
- Path jarFile =
- Paths.get(KOTLIN_R8_TEST_RESOURCES_BUILD_DIR, folder + FileUtils.JAR_EXTENSION);
+ Path jarFile = getJarFile(folder);
String proguardRules = buildProguardRules(mainClass);
if (extraProguardRules != null) {
@@ -176,6 +187,11 @@
inspector.inspectApp(app);
}
+ private Path getJarFile(String folder) {
+ return Paths.get(ToolHelper.TESTS_BUILD_DIR, "kotlinR8TestResources",
+ targetVersion.getFolderName(), folder + FileUtils.JAR_EXTENSION);
+ }
+
@FunctionalInterface
interface AndroidAppInspector {
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
index fe0efd1..379579f 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
@@ -9,15 +9,9 @@
import com.android.tools.r8.utils.DexInspector;
import com.android.tools.r8.utils.DexInspector.ClassSubject;
import com.android.tools.r8.utils.DexInspector.MethodSubject;
-import com.google.common.collect.ImmutableList;
-import java.util.Collection;
import java.util.Collections;
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 R8KotlinDataClassTest extends AbstractR8KotlinTestBase {
private static final KotlinDataClass TEST_DATA_CLASS = new KotlinDataClass("dataclass.Person")
@@ -37,15 +31,6 @@
private static final MethodSignature COPY_DEFAULT_METHOD =
TEST_DATA_CLASS.getCopyDefaultSignature();
- public R8KotlinDataClassTest(boolean allowAccessModification) {
- super(allowAccessModification);
- }
-
- @Parameters(name = "{0}")
- public static Collection<Object> data() {
- return ImmutableList.of(Boolean.TRUE, Boolean.FALSE);
- }
-
@Test
public void test_dataclass_gettersOnly() throws Exception {
final String mainClassName = "dataclass.MainGettersOnlyKt";
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java
index fc2a7bb..b059382 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java
@@ -7,15 +7,12 @@
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.DexInspector;
import com.android.tools.r8.utils.DexInspector.ClassSubject;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
-import java.util.Collection;
import java.util.Collections;
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 R8KotlinIntrinsicsTest extends AbstractR8KotlinTestBase {
@@ -23,15 +20,6 @@
private static final KotlinDataClass KOTLIN_INTRINSICS_CLASS =
new KotlinDataClass("kotlin.jvm.internal.Intrinsics");
- @Parameters(name = "{0}")
- public static Collection<Object> data() {
- return ImmutableList.of(Boolean.TRUE, Boolean.FALSE);
- }
-
- public R8KotlinIntrinsicsTest(boolean allowAccessModification) {
- super(allowAccessModification);
- }
-
@Test
public void testParameterNullCheckIsInlined() throws Exception {
final String extraRules = keepClassMethod("intrinsics.IntrinsicsKt",
diff --git a/tools/notify.py b/tools/notify.py
index f7ae50e..f6db21b 100644
--- a/tools/notify.py
+++ b/tools/notify.py
@@ -5,12 +5,13 @@
try:
import gi
+ gi.require_version('Notify', '0.7')
from gi.repository import Notify
- Notify.init("R8 build tools")
+ Notify.init('R8 build tools')
def notify(message):
try:
- Notify.Notification.new("R8 build tools", message).show()
+ Notify.Notification.new('R8 build tools', message).show()
except:
return