Merge "Add java8 debug tests"
diff --git a/build.gradle b/build.gradle
index f0cd8a2..7d13d0c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -81,6 +81,7 @@
dependencies {
compile 'net.sf.jopt-simple:jopt-simple:4.6'
compile group: 'com.google.guava', name: 'guava', version: '19.0'
+ compile group: 'it.unimi.dsi', name: 'fastutil', version: '7.2.0'
compile group: 'org.apache.commons', name: 'commons-compress', version: '1.12'
compile group: 'org.ow2.asm', name: 'asm', version: '5.1'
compile group: 'org.ow2.asm', name: 'asm-commons', version: '5.1'
@@ -170,6 +171,16 @@
}
}
+task downloadProguard {
+ cloudDependencies.each { entry ->
+ entry.value.each { entryFile ->
+ if (entryFile.contains("proguard")) {
+ dependsOn "download_deps_${entry.key}/${entryFile}"
+ }
+ }
+ }
+}
+
task downloadDeps {
cloudDependencies.each { entry ->
entry.value.each { entryFile ->
@@ -290,18 +301,17 @@
task createArtTests(type: Exec) {
def outputDir = "build/generated/test/java/com/android/tools/r8/art"
- def createArtTestsScript = "scripts/create-art-tests.sh"
+ def createArtTestsScript = "tools/create_art_tests.py"
inputs.file "tests/art.tar.gz"
inputs.file createArtTestsScript
outputs.dir outputDir
dependsOn downloadDeps
- executable "bash"
- args "${projectDir}/${createArtTestsScript}"
+ commandLine "python", createArtTestsScript
workingDir = projectDir
}
task createJctfTests(type: Exec) {
- def outputDir = "build/generated/test/java/com/android/tools/r8/art"
+ def outputDir = "build/generated/test/java/com/android/tools/r8/jctf"
def script = "scripts/create-jctf-tests.sh"
inputs.file script
outputs.dir outputDir
@@ -385,7 +395,7 @@
}
task buildExampleJars {
- dependsOn downloadDeps
+ dependsOn downloadProguard
def examplesDir = file("src/test/examples")
def proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.sh"
task "compile_examples"(type: JavaCompile) {
@@ -672,10 +682,10 @@
}
// TODO(tamaskenez) enable jctf on all_tests when consolidated
if (!project.hasProperty('jctf') && !project.hasProperty('only_jctf')) {
- exclude "com/android/tools/r8/art/jctf/**"
+ exclude "com/android/tools/r8/jctf/**"
}
if (project.hasProperty('only_jctf')) {
- include "com/android/tools/r8/art/jctf/**"
+ include "com/android/tools/r8/jctf/**"
}
if (project.hasProperty('jctf_compile_only')) {
println "JCTF: compiling only"
diff --git a/scripts/create-art-tests.sh b/scripts/create-art-tests.sh
deleted file mode 100755
index dc6d6d2..0000000
--- a/scripts/create-art-tests.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-function generate_test() {
- local name=$1
- local testClassName=$2
- local testGeneratingToolchain=$3
- # The bash uppercase substitution ^^ is not supported on the bash version on Mac OS.
- local testGeneratingToolchainEnum=$(echo $testGeneratingToolchain | tr /a-z/ /A-Z/)
- local fileName=$4
- local compilerUnderTest=$5
- local compilerUnderTestEnum=$(echo ${compilerUnderTest} | tr /a-z/ /A-Z/)
-
- cat <<EOF > $fileName
-// 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.art.${testGeneratingToolchain}.${compilerUnderTest};
-
-import static com.android.tools.r8.R8RunArtTestsTest.DexTool.${testGeneratingToolchainEnum};
-
-import com.android.tools.r8.R8RunArtTestsTest;
-import org.junit.Test;
-
-/**
- * Auto-generated test for the art ${name} test using the ${testGeneratingToolchain} toolchain.
- *
- * DO NOT EDIT THIS FILE. EDIT THE HERE DOCUMENT TEMPLATE IN scripts/create-art-tests.sh INSTEAD!
- */
-public class ${testClassName} extends R8RunArtTestsTest {
-
- public ${testClassName}() {
- super("${name}", ${testGeneratingToolchainEnum});
- }
-
- @Test
- public void run${testClassName}() throws Throwable {
- // For testing with other Art VMs than the default pass the VM version as a argument to
- // runArtTest, e.g. runArtTest(ToolHelper.ART_4_4_4).
- runArtTest(CompilerUnderTest.${compilerUnderTestEnum});
- }
-}
-EOF
-}
-
-TESTDIR="tests/art"
-TOOLCHAINS=("dx" "jack" "none")
-DESTINATIONDIR="build/generated/test/java/com/android/tools/r8/art"
-
-if [ ! -e $TESTDIR ]; then
- echo "Missing art tests in $TESTDIR."
- exit
-fi
-
-for TOOLCHAIN in ${TOOLCHAINS[@]}; do
- for d in $DESTINATIONDIR/$TOOLCHAIN/r8 $DESTINATIONDIR/$TOOLCHAIN/d8; do
- rm -rf $d
- mkdir -p $d
- done
- # class files are found in the dx directory.
- if [ "$TOOLCHAIN" == "none" ]; then
- SOURCEDIR=${TESTDIR}/dx
- else
- SOURCEDIR=${TESTDIR}/${TOOLCHAIN}
- fi
- for TEST in ${SOURCEDIR}/*; do
- TESTNAME=$(basename $TEST)
- TESTCLASSNAME="Art${TESTNAME//-/_}Test"
- generate_test $TESTNAME $TESTCLASSNAME ${TOOLCHAIN} $DESTINATIONDIR/$TOOLCHAIN/r8/$TESTCLASSNAME.java r8
- generate_test $TESTNAME $TESTCLASSNAME ${TOOLCHAIN} $DESTINATIONDIR/$TOOLCHAIN/d8/$TESTCLASSNAME.java d8
- done
-done
diff --git a/scripts/create-jctf-tests.sh b/scripts/create-jctf-tests.sh
index 538f3c3..2f4e91e 100755
--- a/scripts/create-jctf-tests.sh
+++ b/scripts/create-jctf-tests.sh
@@ -26,7 +26,7 @@
// Copyright (c) 2017, 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.art.jctf.${compilerUnderTest}.${relativePackage};
+package com.android.tools.r8.jctf.${compilerUnderTest}.${relativePackage};
import org.junit.Test;
import com.android.tools.r8.R8RunArtTestsTest;
@@ -57,14 +57,14 @@
}
JCTFROOT="third_party/jctf"
-DESTINATIONDIR="build/generated/test/java/com/android/tools/r8/art"
+DESTINATIONDIR="build/generated/test/java/com/android/tools/r8/jctf"
if [ ! -e $JCTFROOT ]; then
echo "Missing jctf tests in $JCTFROOT."
exit
fi
-for d in $DESTINATIONDIR/jctf/r8 $DESTINATIONDIR/jctf/d8; do
+for d in $DESTINATIONDIR/r8 $DESTINATIONDIR/d8; do
rm -rf $d
mkdir -p $d
done
@@ -86,10 +86,10 @@
RELATIVE_PACKAGE=$(expr "$PACKAGE" : ".*\.java\.\(.*$\)")
generate_test $PACKAGE.$TESTNAME $TESTCLASSNAME \
- "$DESTINATIONDIR/jctf/r8/$RELATIVE_TEST_PATH" r8 \
+ "$DESTINATIONDIR/r8/$RELATIVE_TEST_PATH" r8 \
$CLASSFILE $RELATIVE_PACKAGE
generate_test $PACKAGE.$TESTNAME $TESTCLASSNAME \
- "$DESTINATIONDIR/jctf/d8/$RELATIVE_TEST_PATH" d8 \
+ "$DESTINATIONDIR/d8/$RELATIVE_TEST_PATH" d8 \
$CLASSFILE $RELATIVE_PACKAGE
done
diff --git a/src/main/java/com/android/tools/r8/IncrementalDexingBenchmark.java b/src/main/java/com/android/tools/r8/IncrementalDexingBenchmark.java
index 7b9d8aa..e509bf1 100644
--- a/src/main/java/com/android/tools/r8/IncrementalDexingBenchmark.java
+++ b/src/main/java/com/android/tools/r8/IncrementalDexingBenchmark.java
@@ -33,7 +33,7 @@
compile(executor);
}
double elapsedMs = (System.nanoTime() - start) / 1000000.0;
- System.out.println("Runtime: " + elapsedMs + " ms");
+ System.out.println("IncrementalDexing(Runtime): " + elapsedMs + " ms");
} finally {
executor.shutdown();
}
diff --git a/src/main/java/com/android/tools/r8/dex/DexFileReader.java b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
index a38d397..627d106 100644
--- a/src/main/java/com/android/tools/r8/dex/DexFileReader.java
+++ b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
@@ -50,8 +50,8 @@
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.OffsetToObjectMapping;
import com.android.tools.r8.logging.Log;
-import com.android.tools.r8.utils.IntHashMap;
-import com.android.tools.r8.utils.InternalResource;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ShortBuffer;
@@ -91,10 +91,10 @@
private OffsetToObjectMapping indexedItems = new OffsetToObjectMapping();
// Mapping from offset to code item;
- private IntHashMap<DexCode> codes = new IntHashMap<>();
+ private Int2ObjectMap<DexCode> codes = new Int2ObjectOpenHashMap<>();
// Mapping from offset to dex item;
- private IntHashMap<Object> offsetMap = new IntHashMap<>();
+ private Int2ObjectMap<Object> offsetMap = new Int2ObjectOpenHashMap<>();
// Factory to canonicalize certain dexitems.
private final DexItemFactory dexItemFactory;
@@ -140,7 +140,9 @@
}
private DexTypeList typeListAt(int offset) {
- if (offset == 0) return DexTypeList.empty();
+ if (offset == 0) {
+ return DexTypeList.empty();
+ }
return (DexTypeList) cacheAt(offset, this::parseTypeList);
}
@@ -358,9 +360,13 @@
}
private <T> Object cacheAt(int offset, Supplier<T> function) {
- if (offset == 0) return null; // return null for offset zero.
+ if (offset == 0) {
+ return null; // return null for offset zero.
+ }
Object result = offsetMap.get(offset);
- if (result != null) return result; // return the cached result.
+ if (result != null) {
+ return result; // return the cached result.
+ }
// Cache is empty so parse the structure.
file.position(offset);
result = function.get();
@@ -812,7 +818,7 @@
private static void populateMethodHandles(DexFileReader reader) {
Segment segment = reader.lookupSegment(Constants.TYPE_METHOD_HANDLE_ITEM);
reader.indexedItems.initializeMethodHandles(segment.size);
- for (int i = 0; i < segment.size; i++){
+ for (int i = 0; i < segment.size; i++) {
reader.indexedItems.setMethodHandle(i, reader.methodHandleAt(i));
}
}
@@ -820,7 +826,7 @@
private static void populateCallSites(DexFileReader reader) {
Segment segment = reader.lookupSegment(Constants.TYPE_CALL_SITE_ID_ITEM);
reader.indexedItems.initializeCallSites(segment.size);
- for (int i = 0; i < segment.size; i++){
+ for (int i = 0; i < segment.size; i++) {
reader.indexedItems.setCallSites(i, reader.callSiteAt(i));
}
}
@@ -828,7 +834,7 @@
private static void populateTypes(DexFileReader reader) {
Segment segment = reader.lookupSegment(Constants.TYPE_TYPE_ID_ITEM);
reader.indexedItems.initializeTypes(segment.size);
- for (int i = 0; i < segment.size; i++){
+ for (int i = 0; i < segment.size; i++) {
reader.indexedItems.setType(i, reader.typeAt(i));
}
}
@@ -836,7 +842,7 @@
private static void populateFields(DexFileReader reader) {
Segment segment = reader.lookupSegment(Constants.TYPE_FIELD_ID_ITEM);
reader.indexedItems.initializeFields(segment.size);
- for (int i = 0; i < segment.size; i++){
+ for (int i = 0; i < segment.size; i++) {
reader.indexedItems.setField(i, reader.fieldAt(i));
}
}
@@ -844,7 +850,7 @@
private static void populateProtos(DexFileReader reader) {
Segment segment = reader.lookupSegment(Constants.TYPE_PROTO_ID_ITEM);
reader.indexedItems.initializeProtos(segment.size);
- for (int i = 0; i < segment.size; i++){
+ for (int i = 0; i < segment.size; i++) {
reader.indexedItems.setProto(i, reader.protoAt(i));
}
}
@@ -852,7 +858,7 @@
private static void populateMethods(DexFileReader reader) {
Segment segment = reader.lookupSegment(Constants.TYPE_METHOD_ID_ITEM);
reader.indexedItems.initializeMethods(segment.size);
- for (int i = 0; i < segment.size; i++){
+ for (int i = 0; i < segment.size; i++) {
reader.indexedItems.setMethod(i, reader.methodAt(i));
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index 2d5d803..1eb8707 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -96,7 +96,7 @@
continue;
}
DexMethod actualTarget = graphLense.lookupMethod(invokedMethod, method);
- Invoke.Type invokeType = getInvokeType(invoke, actualTarget);
+ Invoke.Type invokeType = getInvokeType(invoke, actualTarget, invokedMethod);
if (actualTarget != invokedMethod || invoke.getType() != invokeType) {
Invoke newInvoke = Invoke
.create(invokeType, actualTarget, null,
@@ -228,16 +228,26 @@
return methodHandle;
}
- private Type getInvokeType(InvokeMethod invoke, DexMethod actualTarget) {
+ private Type getInvokeType(InvokeMethod invoke, DexMethod actualTarget,
+ DexMethod originalTarget) {
if (invoke.isInvokeVirtual() || invoke.isInvokeInterface()) {
// Get the invoke type of the actual definition.
- DexClass clazz = appInfo.definitionFor(actualTarget.holder);
- if (clazz == null) {
+ DexClass newTargetClass = appInfo.definitionFor(actualTarget.holder);
+ if (newTargetClass == null) {
return invoke.getType();
} else {
- return clazz.accessFlags.isInterface()
- ? Type.INTERFACE
- : Type.VIRTUAL;
+ DexClass originalTargetClass = appInfo.definitionFor(originalTarget.holder);
+ if (originalTargetClass.isInterface() ^ (invoke.getType() == Type.INTERFACE)) {
+ // The invoke was wrong to start with, so we keep it wrong. This is to ensure we get
+ // the IncompatibleClassChangeError the original invoke would have triggered.
+ return newTargetClass.accessFlags.isInterface()
+ ? Type.VIRTUAL
+ : Type.INTERFACE;
+ } else {
+ return newTargetClass.accessFlags.isInterface()
+ ? Type.INTERFACE
+ : Type.VIRTUAL;
+ }
}
} else {
return invoke.getType();
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 ba15c9d..ecda01e 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
@@ -115,7 +115,7 @@
// by this class as well as its superclasses.
DexClass current = clazz;
while (true) {
- for (DexType type : clazz.interfaces.values) {
+ for (DexType type : current.interfaces.values) {
helper.merge(getOrCreateInterfaceInfo(type));
}
@@ -139,7 +139,7 @@
current = clazz;
while (true) {
// Hide candidates by virtual method of the class.
- hideCandidates(clazz.virtualMethods, candidates, toBeImplemented);
+ hideCandidates(current.virtualMethods, candidates, toBeImplemented);
if (candidates.isEmpty()) {
return toBeImplemented;
}
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 772d74c..66cd7d9 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
@@ -121,6 +121,8 @@
companionClassFlags.unsetInterface();
companionClassFlags.setFinal();
companionClassFlags.setSynthetic();
+ // Companion class must be public so moved methods can be called from anywhere.
+ companionClassFlags.setPublic();
// Create companion class.
DexType companionClassType = rewriter.getCompanionClassType(iface.type);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index dc2ed67..bc9b95e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -138,8 +138,13 @@
assert target.getCode().isDexCode();
return target.buildIR(generator, options);
} else {
- assert target.getCode().isJarCode();
- IRCode code = target.getCode().asJarCode().buildIR(target, generator, options);
+ // Build the IR for a yet not processed method, and perform minimal IR processing.
+ IRCode code;
+ if (target.getCode().isJarCode()) {
+ code = target.getCode().asJarCode().buildIR(target, generator, options);
+ } else {
+ code = target.getCode().asDexCode().buildIR(target, generator, options);
+ }
new LensCodeRewriter(graphLense, appInfo).rewrite(code, target);
return code;
}
@@ -223,7 +228,10 @@
InlineAction result = invoke.computeInlining(oracle);
if (result != null) {
DexEncodedMethod target = appInfo.lookup(invoke.getType(), invoke.getInvokedMethod());
- assert target != null;
+ if (target == null) {
+ // The declared target cannot be found so skip inlining.
+ continue;
+ }
boolean forceInline = target.getOptimizationInfo().forceInline();
if (!target.isProcessed() && !forceInline) {
// Do not inline code that was not processed unless we have to force inline.
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index e79abc1..f621c67 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -429,9 +429,48 @@
private boolean performAllocation(ArgumentReuseMode mode) {
boolean result = performAllocationWithoutMoveInsertion(mode);
insertMoves();
+ if (mode == ArgumentReuseMode.DISALLOW_ARGUMENT_REUSE) {
+ // Now that we know the max register number we can compute whether it is safe to use
+ // argument registers in place. If it is, we redo move insertion to get rid of the moves
+ // caused by splitting of the argument registers.
+ if (unsplitArguments()) {
+ removeSpillAndPhiMoves();
+ insertMoves();
+ }
+ }
return result;
}
+ // When argument register reuse is disallowed, we split argument values to make sure that
+ // we can get the argument into low enough registers at uses that require low numbers. After
+ // register allocation we can check if it is safe to just use the argument register itself
+ // for all uses and thereby avoid moving argument values around.
+ private boolean unsplitArguments() {
+ boolean argumentRegisterUnsplit = false;
+ Value current = preArgumentSentinelValue;
+ while (current != null) {
+ LiveIntervals intervals = current.getLiveIntervals();
+ assert intervals.getRegisterLimit() == Constants.U16BIT_MAX;
+ boolean canUseArgumentRegister = true;
+ for (LiveIntervals child : intervals.getSplitChildren()) {
+ if (child.getRegisterLimit() < registersUsed()) {
+ canUseArgumentRegister = false;
+ break;
+ }
+ }
+ if (canUseArgumentRegister) {
+ argumentRegisterUnsplit = true;
+ for (LiveIntervals child : intervals.getSplitChildren()) {
+ child.clearRegisterAssignment();
+ child.setRegister(intervals.getRegister());
+ child.setSpilled(false);
+ }
+ }
+ current = current.getNextConsecutive();
+ }
+ return argumentRegisterUnsplit;
+ }
+
private void removeSpillAndPhiMoves() {
for (BasicBlock block : code.blocks) {
InstructionListIterator it = block.listIterator();
@@ -470,7 +509,7 @@
return realRegisterNumberFromAllocated(intervalsRegister);
}
- int realRegisterNumberFromAllocated(int allocated) {
+ int unadjustedRealRegisterFromAllocated(int allocated) {
assert allocated != NO_REGISTER;
assert allocated >= 0;
int register;
@@ -484,6 +523,11 @@
// For everything else use the lower numbers.
register = allocated - numberOfArgumentRegisters - NUMBER_OF_SENTINEL_REGISTERS;
}
+ return register;
+ }
+
+ int realRegisterNumberFromAllocated(int allocated) {
+ int register = unadjustedRealRegisterFromAllocated(allocated);
// Adjust for spill registers that turn out to be unused because the value can be
// rematerialized instead of spilled.
if (unusedRegisters != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java b/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
index f1d3b9e..c966813 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LiveIntervals.java
@@ -89,8 +89,12 @@
}
// If one of the non-spilled splits uses a register that is higher than U8BIT_MAX we cannot
// rematerialize it using a ConstNumber instruction and we use spill moves instead of
- // rematerialization.
- int max = registerAllocator.realRegisterNumberFromAllocated(getMaxNonSpilledRegister());
+ // rematerialization. We use this check both before and after we have computed the set
+ // of unused registers. We therefore have to be careful to use the same max number for
+ // these computations. We use the unadjusted real register number to make sure that
+ // isRematerializable for the same intervals does not change from one phase of
+ // compilation to the next.
+ int max = registerAllocator.unadjustedRealRegisterFromAllocated(getMaxNonSpilledRegister());
return max < Constants.U8BIT_MAX;
}
diff --git a/src/main/java/com/android/tools/r8/optimize/DebugStripper.java b/src/main/java/com/android/tools/r8/optimize/DebugStripper.java
index d045f76..998bc8d 100644
--- a/src/main/java/com/android/tools/r8/optimize/DebugStripper.java
+++ b/src/main/java/com/android/tools/r8/optimize/DebugStripper.java
@@ -17,9 +17,10 @@
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.Range;
import com.android.tools.r8.naming.MemberNaming.Signature;
-import com.android.tools.r8.utils.HashMapInt;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableMap;
+import it.unimi.dsi.fastutil.objects.Reference2IntMap;
+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.List;
public class DebugStripper {
@@ -50,6 +51,7 @@
}
private static class NumberedDebugInfo {
+
final int numberOfEntries;
final DexDebugInfo info;
@@ -103,7 +105,7 @@
}
private void processCode(DexEncodedMethod encodedMethod, MemberNaming naming,
- HashMapInt<DexString> nameCounts) {
+ Reference2IntMap<DexString> nameCounts) {
if (encodedMethod.getCode() == null) {
return;
}
@@ -118,7 +120,7 @@
if (options.skipDebugLineNumberOpt) {
startLine = originalInfo.startLine;
} else {
- int nameCount = nameCounts.get(name);
+ int nameCount = nameCounts.getInt(name);
if (nameCount == USED_ONCE) {
isUsedOnce = true;
startLine = 0;
@@ -132,7 +134,7 @@
DexDebugInfo newInfo = numberedInfo.info;
if (!options.skipDebugLineNumberOpt) {
// Fix up the line information.
- int previousCount = nameCounts.get(name);
+ int previousCount = nameCounts.getInt(name);
nameCounts.put(name, previousCount + numberedInfo.numberOfEntries);
// If we don't actually need line information and there are no debug entries, throw it away.
if (newInfo != null && isUsedOnce && newInfo.events.length == 0) {
@@ -147,7 +149,7 @@
}
private void processMethod(DexEncodedMethod method, ClassNaming classNaming,
- HashMapInt<DexString> nameCounts) {
+ Reference2IntMap<DexString> nameCounts) {
MemberNaming naming = null;
if (classNaming != null) {
Signature renamedSignature = classNameMapper.getRenamedMethodSignature(method.method);
@@ -157,7 +159,7 @@
}
private void processMethods(DexEncodedMethod[] methods, ClassNaming naming,
- HashMapInt<DexString> nameCounts) {
+ Reference2IntMap<DexString> nameCounts) {
if (methods == null) {
return;
}
@@ -172,14 +174,14 @@
}
String name = descriptorToName(clazz.type.toDescriptorString());
ClassNaming naming = classNameMapper == null ? null : classNameMapper.getClassNaming(name);
- HashMapInt<DexString> nameCounts = new HashMapInt<>();
+ Reference2IntMap<DexString> nameCounts = new Reference2IntOpenHashMap<>();
setIntialNameCounts(nameCounts, clazz.directMethods());
setIntialNameCounts(nameCounts, clazz.virtualMethods());
processMethods(clazz.directMethods(), naming, nameCounts);
processMethods(clazz.virtualMethods(), naming, nameCounts);
}
- private void setIntialNameCounts(HashMapInt<DexString> nameCounts,
+ private void setIntialNameCounts(Reference2IntMap<DexString> nameCounts,
DexEncodedMethod[] methods) {
for (DexEncodedMethod method : methods) {
if (nameCounts.containsKey(method.method.name)) {
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 6fb9d2e..6dbf79b 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -682,6 +682,7 @@
}
superInvokeDependencies.computeIfAbsent(from, ignore -> Sets.newIdentityHashSet()).add(target);
if (liveMethods.contains(from)) {
+ markMethodAsTargeted(target, KeepReason.invokedViaSuperFrom(from));
markVirtualMethodAsLive(target, KeepReason.invokedViaSuperFrom(from));
}
}
@@ -822,6 +823,7 @@
Log.verbose(getClass(), "Found super invoke constraint on `%s`.",
superCallTarget.method);
}
+ markMethodAsTargeted(superCallTarget, KeepReason.invokedViaSuperFrom(method));
markVirtualMethodAsLive(superCallTarget, KeepReason.invokedViaSuperFrom(method));
}
}
diff --git a/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java b/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
index bc43ae8..a2864e4 100644
--- a/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/SimpleClassMerger.java
@@ -23,9 +23,6 @@
import com.android.tools.r8.optimize.InvokeSingleTargetExtractor;
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.utils.FieldSignatureEquivalence;
-import com.android.tools.r8.utils.HashMapInt;
-import com.android.tools.r8.utils.IdentityHashMapInt;
-import com.android.tools.r8.utils.IntIntHashMap;
import com.android.tools.r8.utils.MethodSignatureEquivalence;
import com.android.tools.r8.utils.Timing;
import com.google.common.base.Equivalence;
@@ -33,6 +30,10 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
+import it.unimi.dsi.fastutil.ints.Int2IntMap;
+import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Reference2IntMap;
+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -274,7 +275,7 @@
}
private <T> Set<T> mergeArrays(T[] one, T[] other) {
- Set<T> merged = new LinkedHashSet<T>();
+ Set<T> merged = new LinkedHashSet<>();
Collections.addAll(merged, one);
Collections.addAll(merged, other);
return merged;
@@ -513,22 +514,26 @@
private static class CollisionDetector {
+ private static int NOT_FOUND = 1 << (Integer.SIZE - 1);
+
// TODO(herhut): Maybe cache seenPositions for target classes.
- private final Map<DexString, IntIntHashMap> seenPositions = new IdentityHashMap<>();
- private final HashMapInt<DexProto> targetProtoCache;
- private final HashMapInt<DexProto> sourceProtoCache;
+ private final Map<DexString, Int2IntMap> seenPositions = new IdentityHashMap<>();
+ private final Reference2IntMap<DexProto> targetProtoCache;
+ private final Reference2IntMap<DexProto> sourceProtoCache;
private final DexType source, target;
- private final Set<DexMethod> invokes;
+ private final Collection<DexMethod> invokes;
private final Map<DexType, DexType> substituions;
- private CollisionDetector(DexType source, DexType target, Set<DexMethod> invokes,
+ private CollisionDetector(DexType source, DexType target, Collection<DexMethod> invokes,
Map<DexType, DexType> substitutions) {
this.source = source;
this.target = target;
this.invokes = invokes;
this.substituions = substitutions;
- this.targetProtoCache = new IdentityHashMapInt<>(invokes.size() / 2);
- this.sourceProtoCache = new IdentityHashMapInt<>(invokes.size() / 2);
+ this.targetProtoCache = new Reference2IntOpenHashMap<>(invokes.size() / 2);
+ this.targetProtoCache.defaultReturnValue(NOT_FOUND);
+ this.sourceProtoCache = new Reference2IntOpenHashMap<>(invokes.size() / 2);
+ this.sourceProtoCache.defaultReturnValue(NOT_FOUND);
}
boolean mayCollide() {
@@ -538,11 +543,11 @@
return false;
}
for (DexMethod method : invokes) {
- IntIntHashMap positionsMap = seenPositions.get(method.name);
+ Int2IntMap positionsMap = seenPositions.get(method.name);
if (positionsMap != null) {
int arity = method.proto.parameters.values.length;
- if (positionsMap.containsKey(arity)) {
- int previous = positionsMap.get(arity);
+ int previous = positionsMap.get(arity);
+ if (previous != NOT_FOUND) {
assert previous != 0;
int positions = computePositionsFor(method.proto, source, sourceProtoCache,
substituions);
@@ -561,55 +566,58 @@
int arity = parameters.length;
int positions = computePositionsFor(method.proto, target, targetProtoCache, substituions);
if (positions != 0) {
- IntIntHashMap positionsMap =
- seenPositions.computeIfAbsent(method.name, k -> new IntIntHashMap());
+ Int2IntMap positionsMap =
+ seenPositions.computeIfAbsent(method.name, k -> {
+ Int2IntMap result = new Int2IntOpenHashMap();
+ result.defaultReturnValue(NOT_FOUND);
+ return result;
+ });
int value = 0;
- if (positionsMap.containsKey(arity)) {
- value = positionsMap.get(arity);
+ int previous = positionsMap.get(arity);
+ if (previous != NOT_FOUND) {
+ value = previous;
}
value |= positions;
positionsMap.put(arity, value);
}
}
- int filled = 0;
- for (IntIntHashMap pos : seenPositions.values()) {
- filled += pos.size();
- }
+
}
private int computePositionsFor(DexProto proto, DexType type,
- HashMapInt<DexProto> cache, Map<DexType, DexType> substituions) {
- if (cache.containsKey(proto)) {
- return cache.get(proto);
+ Reference2IntMap<DexProto> cache, Map<DexType, DexType> substitutions) {
+ int result = cache.getInt(proto);
+ if (result != NOT_FOUND) {
+ return result;
}
- int result = 0;
- int bits = 0;
+ result = 0;
+ int bitsUsed = 0;
int accumulator = 0;
for (DexType aType : proto.parameters.values) {
- if (substituions != null) {
+ if (substitutions != null) {
// Substitute the type with the already merged class to estimate what it will
// look like.
- while (substituions.containsKey(aType)) {
- aType = substituions.get(aType);
+ while (substitutions.containsKey(aType)) {
+ aType = substitutions.get(aType);
}
}
accumulator <<= 1;
- bits++;
+ bitsUsed++;
if (aType == type) {
accumulator |= 1;
}
- // Handle overflow on 32 bit boundary.
- if (bits == Integer.SIZE) {
+ // Handle overflow on 31 bit boundary.
+ if (bitsUsed == Integer.SIZE - 1) {
result |= accumulator;
accumulator = 0;
- bits = 0;
+ bitsUsed = 0;
}
}
// We also take the return type into account for potential conflicts.
DexType returnType = proto.returnType;
- if (substituions != null) {
- while (substituions.containsKey(returnType)) {
- returnType = substituions.get(returnType);
+ if (substitutions != null) {
+ while (substitutions.containsKey(returnType)) {
+ returnType = substitutions.get(returnType);
}
}
accumulator <<= 1;
diff --git a/src/main/java/com/android/tools/r8/utils/HashMapInt.java b/src/main/java/com/android/tools/r8/utils/HashMapInt.java
deleted file mode 100644
index 7e91644..0000000
--- a/src/main/java/com/android/tools/r8/utils/HashMapInt.java
+++ /dev/null
@@ -1,120 +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.utils;
-
-// Hash map based on open addressing where keys are Objects and values are basic ints.
-// Provides: put, get, and size.
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Objects;
-
-public class HashMapInt<T> extends SimpleHashMap {
-
- private Object[] keys;
- private int[] values;
-
- public HashMapInt() {
- super();
- }
-
- public HashMapInt(int initialCapacity) {
- super(initialCapacity);
- }
-
- public HashMapInt(int initialCapacity, double loadFactor) {
- super(initialCapacity, loadFactor);
- }
-
- public void put(final T key, final int value) {
- if (key == null) {
- throw new RuntimeException("HashMapInt does not support null as key.");
- }
- ensureCapacity();
- basePut(key, value);
- }
-
- boolean equals(Object one, Object other) {
- return one.equals(other);
- }
-
- public int get(final T key) {
- if (key == null) {
- throw new RuntimeException("HashMapInt does not support null as key.");
- }
- int count = 1;
- int index = firstProbe(key);
- while (!equals(key, keys[index])) {
- if (keys[index] == null) {
- throw new RuntimeException("HashMapInt get only works if key is present.");
- }
- index = nextProbe(index, count++);
- }
- return values[index];
- }
-
- int firstProbe(T key) {
- return firstProbe(key.hashCode());
- }
-
- public boolean containsKey(final T key) {
- if (key == null) {
- throw new RuntimeException("HashMapInt does not support null as key.");
- }
- int count = 1;
- for (int index = firstProbe(key); ; index = nextProbe(index, count++)) {
- Object k = keys[index];
- if (k == null) {
- return false;
- }
- if (equals(k, key)) {
- return true;
- }
- }
- }
-
- private void basePut(final T key, final int value) {
- int count = 1;
- int index = firstProbe(key);
- while ((keys[index] != null) && (keys[index] != key)) {
- index = nextProbe(index, count++);
- }
- if (keys[index] == null) {
- keys[index] = key;
- incrementSize();
- }
- values[index] = value;
- }
-
- @SuppressWarnings("unchecked")
- public Iterable<Integer> values() {
- return () -> Arrays.stream(keys).filter(Objects::nonNull).map((key) -> get((T) key)).iterator();
- }
-
- @SuppressWarnings("unchecked")
- public Iterable<T> keys() {
- return () -> (Iterator<T>) Arrays.stream(keys).filter(Objects::nonNull).iterator();
- }
-
- @SuppressWarnings("unchecked")
- void resize() {
- final Object[] oldKeys = keys;
- final int[] oldValues = values;
- final int oldLength = length();
- super.resize();
- // Repopulate.
- for (int index = 0; index < oldLength; index++) {
- T key = (T) oldKeys[index];
- if (key != null) {
- basePut(key, oldValues[index]);
- }
- }
- }
-
- void initialize(final int length, final int limit) {
- super.initialize(length, limit);
- keys = new Object[length];
- values = new int[length];
- }
-}
diff --git a/src/main/java/com/android/tools/r8/utils/IdentityHashMapInt.java b/src/main/java/com/android/tools/r8/utils/IdentityHashMapInt.java
deleted file mode 100644
index 66e62ac..0000000
--- a/src/main/java/com/android/tools/r8/utils/IdentityHashMapInt.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.utils;
-
-public class IdentityHashMapInt<T> extends HashMapInt<T> {
-
- public IdentityHashMapInt() {
- super();
- }
-
- public IdentityHashMapInt(int initialCapacity) {
- super(initialCapacity);
- }
-
- public IdentityHashMapInt(int initialCapacity, double loadFactor) {
- super(initialCapacity, loadFactor);
- }
-
- @Override
- int firstProbe(T key) {
- return firstProbe(System.identityHashCode(key));
- }
-
- @Override
- boolean equals(Object one, Object other) {
- return one == other;
- }
-}
diff --git a/src/main/java/com/android/tools/r8/utils/IntHashMap.java b/src/main/java/com/android/tools/r8/utils/IntHashMap.java
deleted file mode 100644
index 6a92316..0000000
--- a/src/main/java/com/android/tools/r8/utils/IntHashMap.java
+++ /dev/null
@@ -1,113 +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.utils;
-
-// Hash map based on open addressing where keys are basic ints and values are Objects.
-// Provides: put, get, and size.
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Objects;
-import java.util.stream.IntStream;
-
-public class IntHashMap<T> extends SimpleHashMap {
-
- private int[] keys;
- private Object[] values;
-
- public IntHashMap() {
- super();
- }
-
- public IntHashMap(int initialCapacity) {
- super(initialCapacity);
- }
-
- public IntHashMap(int initialCapacity, double loadFactor) {
- super(initialCapacity, loadFactor);
- }
-
- public void put(final int key, final T value) {
- if (value == null) {
- throw new RuntimeException("IntHashMap does not support null as value.");
- }
- ensureCapacity();
- basePut(key, value);
- }
-
- public T get(final int key) {
- int count = 1;
- int index = firstProbe(computeHash(key));
- // Note that unused entries in keys is 0.
- // That means we only need to check for value != null when key == 0.
- while ((keys[index] != key) && (values[index] != null)) {
- index = nextProbe(index, count++);
- }
- assert (keys[index] == key) || (values[index] == null);
- @SuppressWarnings("unchecked")
- T result = (T) values[index];
- return result;
- }
-
- private void basePut(final int key, final Object value) {
- assert value != null;
- int count = 1;
- int index = firstProbe(computeHash(key));
- while ((values[index] != null) && (keys[index] != key)) {
- index = nextProbe(index, count++);
- }
- if (values[index] == null) {
- keys[index] = key;
- incrementSize();
- }
- values[index] = value;
- assert value.equals(get(key));
- }
-
- void resize() {
- final int[] oldKeys = keys;
- final Object[] oldValues = values;
- final int oldLength = length();
- super.resize();
- // Repopulate.
- for (int index = 0; index < oldLength; index++) {
- Object value = oldValues[index];
- if (value != null) {
- basePut(oldKeys[index], value);
- }
- }
- }
-
- void initialize(final int length, final int limit) {
- super.initialize(length, limit);
- keys = new int[length];
- values = new Object[length];
- }
-
- @SuppressWarnings("unchecked")
- public Iterable<T> values() {
- return () -> (Iterator<T>) Arrays.stream(values).filter(Objects::nonNull).iterator();
- }
-
- public Iterable<Integer> keys() {
- if (get(0) != null) {
- return () -> IntStream.concat(IntStream.of(0), Arrays.stream(keys).filter(i -> i != 0))
- .iterator();
- }
- return () -> Arrays.stream(keys).filter(i -> i != 0 || get(i) != null).distinct().iterator();
- }
-
- // Thomas Wang, Integer Hash Functions.
- // http://www.concentric.net/~Ttwang/tech/inthash.htm
- private static int computeHash(final int key) {
- int hash = key;
- hash = ~hash + (hash << 15); // hash = (hash << 15) - hash - 1;
- hash = hash ^ (hash >> 12);
- hash = hash + (hash << 2);
- hash = hash ^ (hash >> 4);
- hash = hash * 2057; // hash = (hash + (hash << 3)) + (hash << 11);
- hash = hash ^ (hash >> 16);
- return hash & 0x3fffffff;
- }
-}
diff --git a/src/main/java/com/android/tools/r8/utils/IntIntHashMap.java b/src/main/java/com/android/tools/r8/utils/IntIntHashMap.java
deleted file mode 100644
index 03d4911..0000000
--- a/src/main/java/com/android/tools/r8/utils/IntIntHashMap.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.utils;
-
-// Hash map based on open addressing where keys are positive basic ints and values are basic ints.
-// Provides: put, get, and size.
-
-import java.util.Arrays;
-
-public class IntIntHashMap extends SimpleHashMap {
-
- private final int EMPTY_KEY = -1;
-
- private int[] keys;
- private int[] values;
-
- public IntIntHashMap() {
- super();
- }
-
- public IntIntHashMap(int initialCapacity) {
- super(initialCapacity);
- }
-
- public IntIntHashMap(int initialCapacity, double loadFactor) {
- super(initialCapacity, loadFactor);
- }
-
- public void put(final int key, final int value) {
- if (key < 0) {
- throw new RuntimeException("IntIntHashMap does not support negative ints as key.");
- }
- ensureCapacity();
- basePut(key, value);
- }
-
- public int get(final int key) {
- if (key < 0) {
- throw new RuntimeException("IntIntHashMap does not support negative ints as key.");
- }
- int count = 1;
- int index = firstProbe(key);
- while (key != keys[index]) {
- if (keys[index] == EMPTY_KEY) {
- throw new RuntimeException("IntIntHashMap get only works if key is present.");
- }
- index = nextProbe(index, count++);
- }
- return values[index];
- }
-
- public boolean containsKey(final int key) {
- if (key < 0) {
- throw new RuntimeException("IntIntHashMap does not support negative ints as key.");
- }
- int count = 1;
- for (int index = firstProbe(key); ; index = nextProbe(index, count++)) {
- int k = keys[index];
- if (k == EMPTY_KEY) {
- return false;
- }
- if (k == key) {
- return true;
- }
- }
- }
-
- private void basePut(final int key, final int value) {
- int count = 1;
- int index = firstProbe(key);
- while ((keys[index] != EMPTY_KEY) && (keys[index] != key)) {
- index = nextProbe(index, count++);
- }
- if (keys[index] != key) {
- incrementSize();
- keys[index] = key;
- }
- values[index] = value;
- }
-
- void resize() {
- final int[] oldKeys = keys;
- final int[] oldValues = values;
- final int oldLength = length();
- super.resize();
- // Repopulate.
- for (int index = 0; index < oldLength; index++) {
- int key = oldKeys[index];
- if (key != EMPTY_KEY) {
- basePut(key, oldValues[index]);
- }
- }
- }
-
- void initialize(final int length, final int limit) {
- super.initialize(length, limit);
- keys = new int[length];
- Arrays.fill(keys, EMPTY_KEY);
- values = new int[length];
- }
-
-
- @SuppressWarnings("unchecked")
- public Iterable<Integer> values() {
- return () -> Arrays.stream(keys).filter(k -> k > EMPTY_KEY).map(this::get).iterator();
- }
-
- @SuppressWarnings("unchecked")
- public Iterable<Integer> keys() {
- return () -> Arrays.stream(keys).filter(k -> k > EMPTY_KEY).iterator();
- }
-}
diff --git a/src/test/examplesAndroidN/interfacemethods/DefaultMethods.java b/src/test/examplesAndroidN/interfacemethods/DefaultMethods.java
index 49e792c..25e3fea 100644
--- a/src/test/examplesAndroidN/interfacemethods/DefaultMethods.java
+++ b/src/test/examplesAndroidN/interfacemethods/DefaultMethods.java
@@ -4,9 +4,32 @@
package interfacemethods;
+import interfacemethods.p1.I4;
+
public class DefaultMethods {
+ interface I3 {
+ default int getValue() {
+ return 1;
+ }
+
+ }
+
+ static class C3 {
+ public int getValue() {
+ return 2;
+ }
+ }
+
+ static class C4 extends C3 implements I3 {
+ }
+
+ static class C5 implements I4 {
+ }
+
public static void main(String[] args) {
new C2().d1();
+ System.out.println(new C4().getValue());
+ new C5().dump();
}
}
diff --git a/src/test/examplesAndroidN/interfacemethods/p1/I3.java b/src/test/examplesAndroidN/interfacemethods/p1/I3.java
new file mode 100644
index 0000000..f956279
--- /dev/null
+++ b/src/test/examplesAndroidN/interfacemethods/p1/I3.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2017, 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 interfacemethods.p1;
+
+interface I3 {
+
+ default void dump() {
+ System.out.println("I3");
+ }
+}
diff --git a/src/test/examplesAndroidN/interfacemethods/p1/I4.java b/src/test/examplesAndroidN/interfacemethods/p1/I4.java
new file mode 100644
index 0000000..1bb946b
--- /dev/null
+++ b/src/test/examplesAndroidN/interfacemethods/p1/I4.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, 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 interfacemethods.p1;
+
+public interface I4 extends I3 {
+}
diff --git a/src/test/java/com/android/tools/r8/D8RunExamplesAndroidNTest.java b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidNTest.java
new file mode 100644
index 0000000..7fb4bcf
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/D8RunExamplesAndroidNTest.java
@@ -0,0 +1,46 @@
+// Copyright (c) 2017, 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.D8Command.Builder;
+import com.android.tools.r8.errors.CompilationError;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.UnaryOperator;
+
+public class D8RunExamplesAndroidNTest extends RunExamplesAndroidNTest<D8Command.Builder> {
+
+ class D8TestRunner extends TestRunner {
+
+ D8TestRunner(String testName, String packageName, String mainClass) {
+ super(testName, packageName, mainClass);
+ }
+
+ @Override
+ TestRunner withMinApiLevel(int minApiLevel) {
+ return withBuilderTransformation(builder -> builder.setMinApiLevel(minApiLevel));
+ }
+
+ @Override
+ void build(Path inputFile, Path out) throws Throwable {
+ D8Command.Builder builder = D8Command.builder();
+ for (UnaryOperator<Builder> transformation : builderTransformations) {
+ builder = transformation.apply(builder);
+ }
+ builder.addLibraryFiles(Paths.get(ToolHelper.getAndroidJar(builder.getMinApiLevel())));
+ D8Command command = builder.addProgramFiles(inputFile).setOutputPath(out).build();
+ try {
+ ToolHelper.runD8(command, this::combinedOptionConsumer);
+ } catch (RuntimeException re) {
+ throw re instanceof CompilationError ? re : re.getCause();
+ }
+ }
+ }
+
+ @Override
+ TestRunner test(String testName, String packageName, String mainClass) {
+ return new D8TestRunner(testName, packageName, mainClass);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidNTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidNTest.java
index 1335970..13c38ca 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesAndroidNTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesAndroidNTest.java
@@ -4,150 +4,40 @@
package com.android.tools.r8;
-import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
-import static com.android.tools.r8.utils.FileUtils.ZIP_EXTENSION;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import com.android.tools.r8.ToolHelper.DexVm;
-import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.errors.CompilationError;
-import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.OffOrAuto;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.Map;
import java.util.concurrent.ExecutionException;
-import java.util.function.Consumer;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
+import java.util.function.UnaryOperator;
-public class R8RunExamplesAndroidNTest {
+public class R8RunExamplesAndroidNTest extends RunExamplesAndroidNTest<R8Command.Builder> {
- private static final String EXAMPLE_DIR = ToolHelper.EXAMPLES_ANDROID_N_BUILD_DIR;
+ class R8TestRunner extends TestRunner {
- private static Map<DexVm, List<String>> failsOn =
- ImmutableMap.of(
- DexVm.ART_4_4_4,
- ImmutableList.of(
- // Dex version not supported
- "staticinterfacemethods", "defaultmethods"),
- DexVm.ART_5_1_1,
- ImmutableList.of(
- // Dex version not supported
- "staticinterfacemethods", "defaultmethods"),
- DexVm.ART_6_0_1,
- ImmutableList.of(
- // Dex version not supported
- "staticinterfacemethods", "defaultmethods"),
- DexVm.ART_7_0_0,
- ImmutableList.of(),
- DexVm.ART_DEFAULT,
- ImmutableList.of());
-
- @Rule public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
-
- @Rule public ExpectedException thrown = ExpectedException.none();
-
- @Test
- public void staticInterfaceMethods() throws Throwable {
- doTest(
- "staticinterfacemethods",
- "interfacemethods",
- "StaticInterfaceMethods",
- Constants.ANDROID_N_API,
- options -> options.interfaceMethodDesugaring = OffOrAuto.Auto);
- }
-
- @Test
- public void staticInterfaceMethodsErrorDueToMinSdk() throws Throwable {
- thrown.expect(CompilationError.class);
- doTest(
- "staticinterfacemethods-error-due-to-min-sdk",
- "interfacemethods",
- "StaticInterfaceMethods");
- }
-
- @Test
- public void defaultMethods() throws Throwable {
- doTest(
- "defaultmethods",
- "interfacemethods",
- "DefaultMethods",
- Constants.ANDROID_N_API,
- options -> options.interfaceMethodDesugaring = OffOrAuto.Auto);
- }
-
- @Test
- public void defaultMethodsErrorDueToMinSdk() throws Throwable {
- thrown.expect(CompilationError.class);
- doTest("defaultmethods-error-due-to-min-sdk", "interfacemethods", "DefaultMethods");
- }
-
- private void doTest(String testName, String packageName, String className) throws Throwable {
- doTest(testName, packageName, className, R8Command.builder(), options -> {});
- }
-
- private void doTest(
- String testName,
- String packageName,
- String className,
- int minSdk,
- Consumer<InternalOptions> optionsConsumer)
- throws Throwable {
- doTest(
- testName,
- packageName,
- className,
- R8Command.builder().setMinApiLevel(minSdk),
- optionsConsumer);
- }
-
- public void doTest(
- String testName,
- String packageName,
- String className,
- R8Command.Builder builder,
- Consumer<InternalOptions> optionsConsumer)
- throws Throwable {
- String mainClass = packageName + "." + className;
- Path inputFile = Paths.get(EXAMPLE_DIR, packageName + JAR_EXTENSION);
- Path out = temp.getRoot().toPath().resolve(testName + ZIP_EXTENSION);
-
- try {
- ToolHelper.runR8(
- builder.addProgramFiles(inputFile).setOutputPath(out).build(), optionsConsumer);
- } catch (ExecutionException e) {
- throw e.getCause();
+ R8TestRunner(String testName, String packageName, String mainClass) {
+ super(testName, packageName, mainClass);
}
- if (!ToolHelper.artSupported()) {
- return;
+ @Override
+ TestRunner withMinApiLevel(int minApiLevel) {
+ return withBuilderTransformation(builder -> builder.setMinApiLevel(minApiLevel));
}
- boolean expectedToFail = false;
- if (failsOn.containsKey(ToolHelper.getDexVm())
- && failsOn.get(ToolHelper.getDexVm()).contains(testName)) {
- expectedToFail = true;
- thrown.expect(Throwable.class);
+ @Override
+ void build(Path inputFile, Path out) throws Throwable {
+ try {
+ R8Command.Builder builder = R8Command.builder();
+ for (UnaryOperator<R8Command.Builder> transformation : builderTransformations) {
+ builder = transformation.apply(builder);
+ }
+ R8Command command = builder.addProgramFiles(inputFile).setOutputPath(out).build();
+ ToolHelper.runR8(command, this::combinedOptionConsumer);
+ } catch (ExecutionException e) {
+ throw e.getCause();
+ }
}
- String output = ToolHelper.runArtNoVerificationErrors(out.toString(), mainClass);
- if (!expectedToFail) {
- ProcessResult javaResult =
- ToolHelper.runJava(ImmutableList.of(inputFile.toString()), mainClass);
- assertEquals("JVM run failed", javaResult.exitCode, 0);
- assertTrue(
- "JVM output does not match art output.\n\tjvm: "
- + javaResult.stdout
- + "\n\tart: "
- + output,
- output.equals(javaResult.stdout));
- }
+ }
+
+ @Override
+ TestRunner test(String testName, String packageName, String mainClass) {
+ return new R8TestRunner(testName, packageName, mainClass);
}
}
diff --git a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
index 3fe2173..8c5e094 100644
--- a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
@@ -78,13 +78,14 @@
"java.lang.NullPointerException: Attempt to read from field " +
"'Test Test.a' on a null object reference\n"},
{"merge-blocks-regression", "java.lang.NullPointerException: Attempt to invoke virtual"
- +" method 'Test Test.bW_()' on a null object reference\n"},
+ + " method 'Test Test.bW_()' on a null object reference\n"},
{"self-is-catch-block", "100\n-1\n"},
{"infinite-loop", ""},
{"regression/33336471",
"START\n0\n2\nLOOP\n1\n2\nLOOP\n2\n2\nDONE\n" +
"START\n0\n2\nLOOP\n1\n2\nLOOP\n2\n2\nDONE\n"},
{"regression/33846227", ""},
+ {"illegal-invokes", "ICCE\nICCE\n"},
});
}
@@ -123,7 +124,8 @@
thrown.expect(Throwable.class);
}
output =
- ToolHelper.checkArtOutputIdentical(originalDexFile.toString(), generated, mainClass, null);
+ ToolHelper
+ .checkArtOutputIdentical(originalDexFile.toString(), generated, mainClass, null);
}
assertEquals(expectedOutput, output);
}
diff --git a/src/test/java/com/android/tools/r8/RunExamplesAndroidNTest.java b/src/test/java/com/android/tools/r8/RunExamplesAndroidNTest.java
new file mode 100644
index 0000000..cb28cc4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/RunExamplesAndroidNTest.java
@@ -0,0 +1,157 @@
+// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+import static com.android.tools.r8.utils.FileUtils.ZIP_EXTENSION;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.ToolHelper.DexVm;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.OffOrAuto;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import java.util.function.UnaryOperator;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+public abstract class RunExamplesAndroidNTest<B> {
+
+ private static final String EXAMPLE_DIR = ToolHelper.EXAMPLES_ANDROID_N_BUILD_DIR;
+
+ abstract class TestRunner {
+ final String testName;
+ final String packageName;
+ final String mainClass;
+
+ final List<Consumer<InternalOptions>> optionConsumers = new ArrayList<>();
+ final List<UnaryOperator<B>> builderTransformations = new ArrayList<>();
+
+ TestRunner(String testName, String packageName, String mainClass) {
+ this.testName = testName;
+ this.packageName = packageName;
+ this.mainClass = mainClass;
+ }
+
+ TestRunner withOptionConsumer(Consumer<InternalOptions> consumer) {
+ optionConsumers.add(consumer);
+ return this;
+ }
+
+ TestRunner withInterfaceMethodDesugaring(OffOrAuto behavior) {
+ return withOptionConsumer(o -> o.interfaceMethodDesugaring = behavior);
+ }
+
+ TestRunner withBuilderTransformation(UnaryOperator<B> builderTransformation) {
+ builderTransformations.add(builderTransformation);
+ return this;
+ }
+
+ void combinedOptionConsumer(InternalOptions options) {
+ for (Consumer<InternalOptions> consumer : optionConsumers) {
+ consumer.accept(options);
+ }
+ }
+
+ void run() throws Throwable {
+ String qualifiedMainClass = packageName + "." + mainClass;
+ Path inputFile = Paths.get(EXAMPLE_DIR, packageName + JAR_EXTENSION);
+ Path out = temp.getRoot().toPath().resolve(testName + ZIP_EXTENSION);
+
+ build(inputFile, out);
+
+ if (!ToolHelper.artSupported()) {
+ return;
+ }
+
+ boolean expectedToFail = false;
+ if (failsOn.containsKey(ToolHelper.getDexVm())
+ && failsOn.get(ToolHelper.getDexVm()).contains(testName)) {
+ expectedToFail = true;
+ thrown.expect(Throwable.class);
+ }
+ String output = ToolHelper.runArtNoVerificationErrors(out.toString(), qualifiedMainClass);
+ if (!expectedToFail) {
+ ProcessResult javaResult =
+ ToolHelper.runJava(ImmutableList.of(inputFile.toString()), qualifiedMainClass);
+ assertEquals("JVM run failed", javaResult.exitCode, 0);
+ assertTrue(
+ "JVM output does not match art output.\n\tjvm: "
+ + javaResult.stdout
+ + "\n\tart: "
+ + output,
+ output.equals(javaResult.stdout));
+ }
+ }
+
+ abstract TestRunner withMinApiLevel(int minApiLevel);
+
+ abstract void build(Path inputFile, Path out) throws Throwable;
+ }
+
+ private static Map<DexVm, List<String>> failsOn =
+ ImmutableMap.of(
+ DexVm.ART_4_4_4,
+ ImmutableList.of(),
+ DexVm.ART_5_1_1,
+ ImmutableList.of(),
+ DexVm.ART_6_0_1,
+ ImmutableList.of(),
+ DexVm.ART_7_0_0,
+ ImmutableList.of(),
+ DexVm.ART_DEFAULT,
+ ImmutableList.of());
+
+ @Rule public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
+
+ @Rule public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void staticInterfaceMethods() throws Throwable {
+ test("staticinterfacemethods", "interfacemethods", "StaticInterfaceMethods")
+ .withMinApiLevel(Constants.ANDROID_K_API)
+ .withInterfaceMethodDesugaring(OffOrAuto.Auto)
+ .run();
+ }
+
+ @Test
+ public void staticInterfaceMethodsErrorDueToMinSdk() throws Throwable {
+ thrown.expect(CompilationError.class);
+ test("staticinterfacemethods-error-due-to-min-sdk", "interfacemethods",
+ "StaticInterfaceMethods")
+ .run();
+ }
+
+ @Test
+ public void defaultMethods() throws Throwable {
+ test("defaultmethods", "interfacemethods", "DefaultMethods")
+ .withMinApiLevel(Constants.ANDROID_K_API)
+ .withInterfaceMethodDesugaring(OffOrAuto.Auto)
+ .run();
+ }
+
+ @Test
+ public void defaultMethodsErrorDueToMinSdk() throws Throwable {
+ thrown.expect(CompilationError.class);
+ test("defaultmethods-error-due-to-min-sdk", "interfacemethods",
+ "DefaultMethods")
+ .run();
+ }
+
+ abstract TestRunner test(String testName, String packageName, String mainClass);
+}
diff --git a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
index 2326eb5..0d0d6f0 100644
--- a/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
+++ b/src/test/java/com/android/tools/r8/classmerging/ClassMergingTest.java
@@ -35,7 +35,10 @@
.addProgramFiles(EXAMPLE_JAR)
.addProguardConfigurationFiles(EXAMPLE_KEEP)
.setMinification(false)
- .build(), o -> o.allowAccessModification = false);
+ .build(), o -> {
+ o.allowAccessModification = false;
+ o.skipClassMerging = false;
+ });
inspector = new DexInspector(
Paths.get(temp.getRoot().getCanonicalPath()).resolve("classes.dex"));
}
diff --git a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
index 5902a6e..4b2ece0 100644
--- a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
@@ -36,17 +36,19 @@
public AndroidApp runAndCheckVerification(
CompilerUnderTest compiler,
+ CompilationMode mode,
String referenceApk,
String pgMap,
String pgConf,
String... inputs)
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
return runAndCheckVerification(
- compiler, referenceApk, pgMap, pgConf, Arrays.asList(inputs));
+ compiler, mode, referenceApk, pgMap, pgConf, Arrays.asList(inputs));
}
public AndroidApp runAndCheckVerification(
CompilerUnderTest compiler,
+ CompilationMode mode,
String referenceApk,
String pgMap,
String pgConf,
@@ -63,6 +65,7 @@
if (pgConf != null) {
builder.addProguardConfigurationFiles(Paths.get(pgConf));
}
+ builder.setMode(mode);
outputApp = ToolHelper.runR8(builder.build());
} else {
assert compiler == CompilerUnderTest.D8;
@@ -70,7 +73,7 @@
ToolHelper.runD8(
D8Command.builder()
.addProgramFiles(ListUtils.map(inputs, Paths::get))
- .setMode(CompilationMode.DEBUG)
+ .setMode(mode)
.build());
}
Path out = temp.getRoot().toPath().resolve("all.zip");
diff --git a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java
new file mode 100644
index 0000000..04c1d2e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV10DeployJarVerificationTest.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2017, 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.internal;
+
+import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
+import com.android.tools.r8.shaking.ProguardRuleParserException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+
+public class D8GMSCoreV10DeployJarVerificationTest extends GMSCoreDeployJarVerificationTest {
+
+ @Test
+ public void buildDebugFromDeployJar()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ buildFromDeployJar(
+ CompilerUnderTest.D8, CompilationMode.DEBUG,
+ GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+ }
+
+ @Test
+ public void buildReleaseFromDeployJar()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ buildFromDeployJar(
+ CompilerUnderTest.D8, CompilationMode.RELEASE,
+ GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
index d5f23d0..2e076d5 100644
--- a/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/D8GMSCoreV9DeployJarVerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
@@ -13,8 +14,18 @@
public class D8GMSCoreV9DeployJarVerificationTest extends GMSCoreDeployJarVerificationTest {
@Test
- public void buildFromDeployJar()
+ public void buildDebugFromDeployJar()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- buildFromDeployJar(CompilerUnderTest.D8, GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+ buildFromDeployJar(
+ CompilerUnderTest.D8, CompilationMode.DEBUG,
+ GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+ }
+
+ @Test
+ public void buildReleaseFromDeployJar()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ buildFromDeployJar(
+ CompilerUnderTest.D8, CompilationMode.RELEASE,
+ GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java
new file mode 100644
index 0000000..5e226bb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/internal/D8YouTubeDeployJarVerificationTest.java
@@ -0,0 +1,29 @@
+// 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.internal;
+
+import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
+import com.android.tools.r8.shaking.ProguardRuleParserException;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
+import org.junit.Test;
+
+public class D8YouTubeDeployJarVerificationTest extends YouTubeCompilationBase {
+
+ @Test
+ public void buildDebugFromDeployJar()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ runAndCheckVerification(
+ CompilerUnderTest.D8, CompilationMode.DEBUG, BASE + APK, null, null, BASE + DEPLOY_JAR);
+ }
+
+ @Test
+ public void buildReleaseFromDeployJar()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ runAndCheckVerification(
+ CompilerUnderTest.D8, CompilationMode.RELEASE, BASE + APK, null, null, BASE + DEPLOY_JAR);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java b/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
index ca8d019..1e91e0d 100644
--- a/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/GMSCoreCompilationTestBase.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
@@ -30,14 +31,16 @@
static final String DEPLOY_JAR = "GmsCore_prod_alldpi_release_all_locales_deploy.jar";
static final String REFERENCE_APK = "noshrink_x86_GmsCore_prod_alldpi_release_unsigned.apk";
- public void runR8AndCheckVerification(String version)
+ public void runR8AndCheckVerification(CompilationMode mode, String version)
throws ProguardRuleParserException, ExecutionException, IOException, CompilationException {
- runAndCheckVerification(CompilerUnderTest.R8, version);
+ runAndCheckVerification(CompilerUnderTest.R8, mode, version);
}
- public void runAndCheckVerification(CompilerUnderTest compiler, String version)
+ public void runAndCheckVerification(
+ CompilerUnderTest compiler, CompilationMode mode, String version)
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
runAndCheckVerification(
- compiler, version + GMSCORE_APK, null, null, Paths.get(version, GMSCORE_APK).toString());
+ compiler, mode, version + GMSCORE_APK, null, null,
+ Paths.get(version, GMSCORE_APK).toString());
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
index ecc7451..0a2cdae 100644
--- a/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/GMSCoreDeployJarVerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
@@ -11,9 +12,10 @@
public class GMSCoreDeployJarVerificationTest extends GMSCoreCompilationTestBase {
- public void buildFromDeployJar(CompilerUnderTest compiler, String base, boolean hasReference)
+ public void buildFromDeployJar(
+ CompilerUnderTest compiler, CompilationMode mode, String base, boolean hasReference)
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
runAndCheckVerification(
- compiler, hasReference ? base + REFERENCE_APK : null, null, null, base + DEPLOY_JAR);
+ compiler, mode, hasReference ? base + REFERENCE_APK : null, null, null, base + DEPLOY_JAR);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
index 2571490..fecc360 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreTreeShakeJarVerificationTest.java
@@ -6,6 +6,7 @@
import static junit.framework.TestCase.assertTrue;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
@@ -18,10 +19,12 @@
public class R8GMSCoreTreeShakeJarVerificationTest extends GMSCoreCompilationTestBase {
- public void buildAndTreeShakeFromDeployJar(String base, boolean hasReference, int maxSize)
+ public void buildAndTreeShakeFromDeployJar(
+ CompilationMode mode, String base, boolean hasReference, int maxSize)
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
AndroidApp app = runAndCheckVerification(
CompilerUnderTest.R8,
+ mode,
hasReference ? base + REFERENCE_APK : null,
null,
base + PG_CONF,
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
index 5894981..6118b3d 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10DeployJarVerificationTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
@@ -17,6 +18,8 @@
public void buildFromDeployJar()
// TODO(tamaskenez): set hasReference = true when we have the noshrink file for V10
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- buildFromDeployJar(CompilerUnderTest.R8, GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
+ buildFromDeployJar(
+ CompilerUnderTest.R8, CompilationMode.RELEASE,
+ GMSCoreCompilationTestBase.GMSCORE_V10_DIR, false);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
index 5253ac2..9572825 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV10TreeShakeJarVerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@@ -16,6 +17,7 @@
public void buildAndTreeShakeFromDeployJar()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
// TODO(tamaskenez): set hasReference = true when we have the noshrink file for V10
- buildAndTreeShakeFromDeployJar(GMSCORE_V10_DIR, false, GMSCORE_V10_MAX_SIZE);
+ buildAndTreeShakeFromDeployJar(
+ CompilationMode.RELEASE, GMSCORE_V10_DIR, false, GMSCORE_V10_MAX_SIZE);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
index d7de82e..0405587 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV4VerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
@Test
public void verify()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- runR8AndCheckVerification(GMSCORE_V4_DIR);
+ runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V4_DIR);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
index 6a098a8..17aab5e 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV5VerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
@Test
public void verify()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- runR8AndCheckVerification(GMSCORE_V5_DIR);
+ runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V5_DIR);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
index b7ca295..d34ad90 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV6VerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@@ -13,6 +14,6 @@
@Test
public void verify()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- runR8AndCheckVerification(GMSCORE_V6_DIR);
+ runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V6_DIR);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
index f65a8e1..2f530f4 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV7VerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@@ -14,6 +15,6 @@
@Test
public void verify()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- runR8AndCheckVerification(GMSCORE_V7_DIR);
+ runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V7_DIR);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
index bc0dbe8..128bd17 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV8VerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@@ -14,6 +15,6 @@
@Test
public void verify()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- runR8AndCheckVerification(GMSCORE_V8_DIR);
+ runR8AndCheckVerification(CompilationMode.RELEASE, GMSCORE_V8_DIR);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
index d1e6844..bc8c2b6 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9DeployJarVerificationTest.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
@@ -16,6 +17,8 @@
@Test
public void buildFromDeployJar()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- buildFromDeployJar(CompilerUnderTest.R8, GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
+ buildFromDeployJar(
+ CompilerUnderTest.R8, CompilationMode.RELEASE,
+ GMSCoreCompilationTestBase.GMSCORE_V9_DIR, true);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
index 2f5ed63..78aa1a3 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreV9TreeShakeJarVerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
@@ -14,6 +15,7 @@
@Test
public void buildAndTreeShakeFromDeployJar()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- buildAndTreeShakeFromDeployJar(GMSCORE_V9_DIR, true, GMSCORE_V9_MAX_SIZE);
+ buildAndTreeShakeFromDeployJar(
+ CompilationMode.RELEASE, GMSCORE_V9_DIR, true, GMSCORE_V9_MAX_SIZE);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java b/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
index 08b3892..3e46590 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeCompilationBase.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.internal;
public abstract class YouTubeCompilationBase extends CompilationTestBase {
- static final String BASE = "third_party/youtube/youtube.android_11.47/";
+ static final String BASE = "third_party/youtube/youtube.android_12.17/";
static final String APK = "YouTubeRelease_unsigned.apk";
static final String DEPLOY_JAR = "YouTubeRelease_deploy.jar";
static final String PG_JAR = "YouTubeRelease_proguard.jar";
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
index b40ba07..7fbfb2e 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeDeployJarVerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
@@ -13,8 +14,16 @@
public class YouTubeDeployJarVerificationTest extends YouTubeCompilationBase {
@Test
- public void buildFromDeployJar()
+ public void buildDebugFromDeployJar()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, null, null, BASE + DEPLOY_JAR);
+ runAndCheckVerification(
+ CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, null, null, BASE + DEPLOY_JAR);
+ }
+
+ @Test
+ public void buildReleaseFromDeployJar()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ runAndCheckVerification(
+ CompilerUnderTest.R8, CompilationMode.RELEASE, BASE + APK, null, null, BASE + DEPLOY_JAR);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
index 19bfe25..ba816f1 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeDexVerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
@@ -13,8 +14,16 @@
public class YouTubeDexVerificationTest extends YouTubeCompilationBase {
@Test
- public void buildFromDex()
+ public void buildDebugFromDex()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, BASE + PG_MAP, null, BASE + APK);
+ runAndCheckVerification(
+ CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, BASE + PG_MAP, null, BASE + APK);
+ }
+
+ @Test
+ public void buildReleaseFromDex()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ runAndCheckVerification(
+ CompilerUnderTest.R8, CompilationMode.RELEASE, BASE + APK, BASE + PG_MAP, null, BASE + APK);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
index 0b1e553..4bbceeb 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeProguardJarVerificationTest.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.internal;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import java.io.IOException;
@@ -13,8 +14,17 @@
public class YouTubeProguardJarVerificationTest extends YouTubeCompilationBase {
@Test
- public void buildFromProguardJar()
+ public void buildDebugFromProguardJar()
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
- runAndCheckVerification(CompilerUnderTest.R8, BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
+ runAndCheckVerification(
+ CompilerUnderTest.R8, CompilationMode.DEBUG, BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
+ }
+
+ @Test
+ public void buildReleaseFromProguardJar()
+ throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
+ runAndCheckVerification(
+ CompilerUnderTest.R8, CompilationMode.RELEASE,
+ BASE + APK, BASE + PG_MAP, null, BASE + PG_JAR);
}
}
diff --git a/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java b/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
index c51129c..229a6fb 100644
--- a/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
+++ b/src/test/java/com/android/tools/r8/internal/YouTubeTreeShakeJarVerificationTest.java
@@ -6,6 +6,7 @@
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.CompilationException;
+import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
@@ -25,7 +26,8 @@
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
int maxSize = 16000000;
AndroidApp app = runAndCheckVerification(
- CompilerUnderTest.R8, BASE + APK, null, BASE + PG_CONF, BASE + DEPLOY_JAR);
+ CompilerUnderTest.R8, CompilationMode.RELEASE,
+ BASE + APK, null, BASE + PG_CONF, BASE + DEPLOY_JAR);
int bytes = 0;
try (Closer closer = Closer.create()) {
for (InternalResource dex : app.getDexProgramResources()) {
diff --git a/src/test/java/com/android/tools/r8/utils/HashMapIntTest.java b/src/test/java/com/android/tools/r8/utils/HashMapIntTest.java
deleted file mode 100644
index 5d8fffe..0000000
--- a/src/test/java/com/android/tools/r8/utils/HashMapIntTest.java
+++ /dev/null
@@ -1,81 +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.utils;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import java.util.Random;
-import java.util.Set;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class HashMapIntTest {
-
- static private String getString(int i) {
- String SALTCHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
- StringBuilder salt = new StringBuilder();
- Random rnd = new Random();
- while (salt.length() < 18) {
- int index = (int) (rnd.nextFloat() * SALTCHARS.length());
- salt.append(SALTCHARS.charAt(index));
- }
- salt.append(" ");
- salt.append(i);
- return salt.toString();
- }
-
- @Test(expected = RuntimeException.class)
- public void putInvalid() throws Exception {
- HashMapInt<Object> map = new HashMapInt<>();
- map.put(null, 12);
- }
-
- @Test
- public void put() throws Exception {
- HashMapInt<Object> map = new HashMapInt<>();
- Object key = new Object();
- int value = 0;
- map.put(key, value);
- Assert.assertTrue(map.containsKey(key));
- Assert.assertFalse(map.containsKey(new Object[0]));
- Assert.assertEquals(map.get(key), value);
- Assert.assertEquals(map.size(), 1);
- }
-
- @Test
- public void random() throws Exception {
- final int length = 5999;
- HashMapInt<String> map = new HashMapInt<>();
- String[] array = new String[length];
- for (int i = 0; i < length; i++) {
- array[i] = getString(i);
- map.put(array[i], i * 3);
- }
- Assert.assertEquals(length, map.size());
- for (int i = 0; i < length; i++) {
- Assert.assertEquals(map.get(array[i]), i * 3);
- }
- for (int i : map.values()) {
- Assert.assertTrue(i < length * 3 && i >= 0 && i % 3 == 0);
- }
- Assert.assertEquals(length, Iterables.size(map.values()));
- Set<String> items = ImmutableSet.copyOf(array);
- for (String s : map.keys()) {
- Assert.assertTrue(items.contains(s));
- }
- Assert.assertEquals(length, Iterables.size(map.keys()));
- }
-
- @Test
- public void overwrite() throws Exception {
- HashMapInt<Object> map = new HashMapInt<>();
- Object key = new Object();
- int value1 = 0;
- map.put(key, value1);
- Assert.assertEquals(map.get(key), value1);
- int value2 = -1;
- map.put(key, value2);
- Assert.assertEquals(map.get(key), value2);
- }
-}
diff --git a/src/test/java/com/android/tools/r8/utils/IdentityHashMapIntTest.java b/src/test/java/com/android/tools/r8/utils/IdentityHashMapIntTest.java
deleted file mode 100644
index dd57960..0000000
--- a/src/test/java/com/android/tools/r8/utils/IdentityHashMapIntTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.utils;
-
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-import java.util.Collections;
-import java.util.Set;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class IdentityHashMapIntTest {
-
- @Test(expected = RuntimeException.class)
- public void putInvalid() throws Exception {
- IdentityHashMapInt<Object> map = new IdentityHashMapInt<>();
- map.put(null, 12);
- }
-
- @Test
- public void put() throws Exception {
- IdentityHashMapInt<Object> map = new IdentityHashMapInt<>();
- Object key = new AllEqual();
- int value = 0;
- map.put(key, value);
- Assert.assertTrue(map.containsKey(key));
- Assert.assertFalse(map.containsKey(new Object()));
- Assert.assertFalse(map.containsKey(new AllEqual()));
- Assert.assertEquals(map.get(key), value);
- Assert.assertEquals(map.size(), 1);
- }
-
- @Test
- public void random() throws Exception {
- final int length = 5999;
- IdentityHashMapInt<Object> map = new IdentityHashMapInt<>();
- AllEqual[] array = new AllEqual[length];
- for (int i = 0; i < length; i++) {
- array[i] = new AllEqual();
- map.put(array[i], i * 3);
- }
- Assert.assertEquals(length, map.size());
- for (int i = 0; i < length; i++) {
- Assert.assertEquals(map.get(array[i]), i * 3);
- }
- for (int i : map.values()) {
- Assert.assertTrue(i < length * 3 && i >= 0 && i % 3 == 0);
- }
- Assert.assertEquals(length, Iterables.size(map.values()));
- Set<Object> items = Sets.newIdentityHashSet();
- Collections.addAll(items, array);
- for (Object o : map.keys()) {
- Assert.assertTrue(items.contains(o));
- }
- Assert.assertEquals(length, Iterables.size(map.keys()));
- }
-
- @Test
- public void overwrite() throws Exception {
- IdentityHashMapInt<Object> map = new IdentityHashMapInt<>();
- Object key = new Object();
- int value1 = 0;
- map.put(key, value1);
- Assert.assertEquals(map.get(key), value1);
- int value2 = -1;
- map.put(key, value2);
- Assert.assertEquals(map.get(key), value2);
- }
-
- private static class AllEqual {
-
- @Override
- public boolean equals(Object o) {
- return true;
- }
- }
-}
diff --git a/src/test/java/com/android/tools/r8/utils/IntHashMapTest.java b/src/test/java/com/android/tools/r8/utils/IntHashMapTest.java
deleted file mode 100644
index c4b4dc2..0000000
--- a/src/test/java/com/android/tools/r8/utils/IntHashMapTest.java
+++ /dev/null
@@ -1,83 +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.utils;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import java.util.Random;
-import java.util.Set;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class IntHashMapTest {
-
- static private String getRandomString() {
- String SALTCHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
- StringBuilder salt = new StringBuilder();
- Random rnd = new Random();
- while (salt.length() < 18) {
- int index = (int) (rnd.nextFloat() * SALTCHARS.length());
- salt.append(SALTCHARS.charAt(index));
- }
- return salt.toString();
- }
-
- @Test(expected = RuntimeException.class)
- public void putInvalid() throws Exception {
- IntHashMap<Object> map = new IntHashMap<>();
- map.put(12, null);
- }
-
- @Test
- public void put() throws Exception {
- IntHashMap<Object> map = new IntHashMap<>();
- int key = 1;
- Object value = new Object();
- map.put(key, value);
- Assert.assertEquals(map.get(key), value);
- Assert.assertEquals(map.size(), 1);
- map.put(key + 1, value);
- Assert.assertEquals(map.get(key + 1), value);
- Assert.assertEquals(map.size(), 2);
- Assert.assertEquals(map.get(0), null);
- map.put(0, value);
- Assert.assertEquals(map.get(0), value);
- }
-
- @Test
- public void random() throws Exception {
- final int length = 5999;
- IntHashMap<String> map = new IntHashMap<>();
- String[] array = new String[length];
- for (int i = 0; i < length; i++) {
- array[i] = getRandomString();
- map.put(i, array[i]);
- }
- Assert.assertEquals(length, map.size());
- for (int i = 0; i < length; i++) {
- Assert.assertEquals(map.get(i), array[i]);
- }
- Set<String> items = ImmutableSet.copyOf(array);
- for (String s : map.values()) {
- Assert.assertTrue(items.contains(s));
- }
- Assert.assertEquals(length, Iterables.size(map.values()));
- for (int i : map.keys()) {
- Assert.assertTrue(i < length && i >= 0);
- }
- Assert.assertEquals(length, Iterables.size(map.keys()));
- }
-
- @Test
- public void overwrite() throws Exception {
- IntHashMap<Object> map = new IntHashMap<>();
- int key = 1;
- Object value1 = new Object();
- map.put(key, value1);
- Assert.assertEquals(map.get(key), value1);
- Object value2 = new Object[0];
- map.put(key, value2);
- Assert.assertEquals(map.get(key), value2);
- }
-}
diff --git a/src/test/java/com/android/tools/r8/utils/IntIntHashMapTest.java b/src/test/java/com/android/tools/r8/utils/IntIntHashMapTest.java
deleted file mode 100644
index d129a03..0000000
--- a/src/test/java/com/android/tools/r8/utils/IntIntHashMapTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-package com.android.tools.r8.utils;
-
-import com.google.common.collect.Iterables;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.Random;
-import java.util.Set;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class IntIntHashMapTest {
-
- @Test(expected = RuntimeException.class)
- public void putInvalid() throws Exception {
- IntIntHashMap map = new IntIntHashMap();
- map.put(-1, 12);
- }
-
- @Test
- public void put() throws Exception {
- IntIntHashMap map = new IntIntHashMap();
- int key = 22;
- int value = 0;
- map.put(key, value);
- Assert.assertTrue(map.containsKey(key));
- Assert.assertFalse(map.containsKey(33));
- Assert.assertEquals(map.get(key), value);
- Assert.assertEquals(map.size(), 1);
- }
-
- @Test
- public void random() throws Exception {
- final int length = 5999;
- IntIntHashMap map = new IntIntHashMap();
- Random rnd = new Random();
- Set<Integer> seen = new LinkedHashSet<>();
- String[] array = new String[length];
- for (int i = 0; i < length; i++) {
- int next;
- do {
- next = rnd.nextInt(4 * length);
- } while (seen.contains(next));
- seen.add(next);
- map.put(next, i * 3);
- }
- Assert.assertEquals(seen.size(), map.size());
- Iterator<Integer> it = seen.iterator();
- for (int i = 0; i < length; i++) {
- Assert.assertEquals(map.get(it.next()), i * 3);
- }
- for (int i : map.values()) {
- Assert.assertTrue(i < length * 3 && i >= 0 && i % 3 == 0);
- }
- Assert.assertEquals(length, Iterables.size(map.values()));
- for (Integer key : map.keys()) {
- Assert.assertTrue(seen.contains(key));
- }
- Assert.assertEquals(seen.size(), Iterables.size(map.keys()));
- }
-
- @Test
- public void overwrite() throws Exception {
- IntIntHashMap map = new IntIntHashMap();
- int key = 42;
- int value1 = 0;
- map.put(key, value1);
- Assert.assertEquals(map.get(key), value1);
- int value2 = -1;
- map.put(key, value2);
- Assert.assertEquals(map.get(key), value2);
- }
-}
diff --git a/src/test/smali/illegal-invokes/Iface.java b/src/test/smali/illegal-invokes/Iface.java
new file mode 100644
index 0000000..dd11626
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Iface.java
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, 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.
+
+public class Iface {
+
+ public void bar() {
+ }
+}
diff --git a/src/test/smali/illegal-invokes/Iface.smali b/src/test/smali/illegal-invokes/Iface.smali
new file mode 100644
index 0000000..d66777c
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Iface.smali
@@ -0,0 +1,10 @@
+# Copyright (c) 2017, 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.
+
+.class interface public LIface;
+.super Ljava/lang/Object;
+
+.method public abstract bar()V
+.end method
+
diff --git a/src/test/smali/illegal-invokes/Lowest.java b/src/test/smali/illegal-invokes/Lowest.java
new file mode 100644
index 0000000..e464313
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Lowest.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2017, 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.
+
+public class Lowest extends Iface implements Super {
+
+ @Override
+ public void foo() {
+
+ }
+}
diff --git a/src/test/smali/illegal-invokes/Lowest.smali b/src/test/smali/illegal-invokes/Lowest.smali
new file mode 100644
index 0000000..d6c5787
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Lowest.smali
@@ -0,0 +1,12 @@
+# Copyright (c) 2017, 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.
+
+.class public LLowest;
+.super LSuper;
+
+.method public bar()V
+ .locals 0
+ return-void
+.end method
+
diff --git a/src/test/smali/illegal-invokes/Super.java b/src/test/smali/illegal-invokes/Super.java
new file mode 100644
index 0000000..54a8714
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Super.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2017, 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.
+
+public interface Super {
+
+ public void foo();
+}
diff --git a/src/test/smali/illegal-invokes/Super.smali b/src/test/smali/illegal-invokes/Super.smali
new file mode 100644
index 0000000..1ec4f0e
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Super.smali
@@ -0,0 +1,13 @@
+# Copyright (c) 2017, 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.
+
+.class public LSuper;
+.super Ljava/lang/Object;
+.implements LIface;
+
+.method public foo()V
+ .locals 0
+ return-void
+.end method
+
diff --git a/src/test/smali/illegal-invokes/Test.java b/src/test/smali/illegal-invokes/Test.java
new file mode 100644
index 0000000..8ddd18e
--- /dev/null
+++ b/src/test/smali/illegal-invokes/Test.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2017, 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.
+
+public class Test {
+
+ int ignore;
+
+ public static void main(String... args) {
+ Lowest l = new Lowest();
+ callVirtualOnIface(l);
+ callIfaceOnVirtual(l);
+ }
+
+ private static void callVirtualOnIface(Iface i) {
+ try {
+ i.bar();
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("ICCE");
+ }
+ }
+
+ private static void callIfaceOnVirtual(Super s) {
+ try {
+ s.foo();
+ } catch (IncompatibleClassChangeError e) {
+ System.out.println("ICCE");
+ }
+ }
+}
diff --git a/tools/create_art_tests.py b/tools/create_art_tests.py
new file mode 100755
index 0000000..3a83cbc
--- /dev/null
+++ b/tools/create_art_tests.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+# Copyright (c) 2017, 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.
+
+from os import makedirs, listdir
+from os.path import join, exists, isdir
+from string import Template, upper
+from sys import exit
+from shutil import rmtree
+
+OUTPUT_DIR = "build/generated/test/java/com/android/tools/r8/art"
+TEST_DIR = "tests/art"
+TOOLCHAINS = ["dx", "jack", "none"]
+TOOLS = ["r8", "d8"]
+TEMPLATE = Template(
+"""// 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.art.$testGeneratingToolchain.$compilerUnderTest;
+
+import static com.android.tools.r8.R8RunArtTestsTest.DexTool.$testGeneratingToolchainEnum;
+
+import com.android.tools.r8.R8RunArtTestsTest;
+import org.junit.Test;
+
+/**
+ * Auto-generated test for the art $name test using the $testGeneratingToolchain toolchain.
+ *
+ * DO NOT EDIT THIS FILE. EDIT THE HERE DOCUMENT TEMPLATE IN tools/create_art_tests.py INSTEAD!
+ */
+public class $testClassName extends R8RunArtTestsTest {
+
+ public $testClassName() {
+ super("$name", $testGeneratingToolchainEnum);
+ }
+
+ @Test
+ public void run$testClassName() throws Throwable {
+ // For testing with other Art VMs than the default pass the VM version as a argument to
+ // runArtTest, e.g. runArtTest(ToolHelper.ART_4_4_4).
+ runArtTest(CompilerUnderTest.$compilerUnderTestEnum);
+ }
+}
+""")
+
+def create_toolchain_dirs(toolchain):
+ toolchain_dir = join(OUTPUT_DIR, toolchain)
+ if exists(toolchain_dir):
+ rmtree(toolchain_dir)
+ makedirs(join(toolchain_dir, "d8"))
+ makedirs(join(toolchain_dir, "r8"))
+
+def write_file(toolchain, tool, class_name, contents):
+ file_name = join(OUTPUT_DIR, toolchain, tool, class_name + ".java")
+ with open(file_name, "w") as file:
+ file.write(contents)
+
+def create_tests(toolchain):
+ source_dir = join(TEST_DIR, "dx" if toolchain == "none" else toolchain)
+ dirs = [d for d in listdir(source_dir)
+ if isdir(join(source_dir, d))]
+ for dir in dirs:
+ class_name = "Art" + dir.replace("-", "_") + "Test"
+ for tool in TOOLS:
+ contents = TEMPLATE.substitute(
+ name=dir,
+ compilerUnderTestEnum=upper(tool),
+ compilerUnderTest=tool,
+ testGeneratingToolchain=toolchain,
+ testGeneratingToolchainEnum=upper(toolchain),
+ testClassName=class_name)
+ write_file(toolchain, tool, class_name, contents)
+
+
+def main():
+ for toolchain in TOOLCHAINS:
+ create_toolchain_dirs(toolchain)
+ create_tests(toolchain)
+
+if __name__ == "__main__":
+ exit(main())