Merge "Don't consider local-associated SSA values as constants."
diff --git a/build.gradle b/build.gradle
index dfb4623..d8402bc 100644
--- a/build.gradle
+++ b/build.gradle
@@ -109,6 +109,7 @@
"third_party": [
"android_jar/lib-v14.tar.gz",
"android_jar/lib-v19.tar.gz",
+ "android_jar/lib-v21.tar.gz",
"android_jar/lib-v24.tar.gz",
"android_jar/lib-v25.tar.gz",
"android_jar/lib-v26.tar.gz",
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index fbcd34c..11cc9bc 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -207,7 +207,6 @@
RootSet rootSet;
byte[] proguardSeedsData = null;
timing.begin("Strip unused code");
- Set<DexType> mainDexBaseClasses = null;
try {
Set<DexType> missingClasses = appInfo.getMissingClasses();
missingClasses = filterMissingClasses(missingClasses, options.dontWarnPatterns);
@@ -281,7 +280,7 @@
// Lets find classes which may have code executed before secondary dex files installation.
RootSet mainDexRootSet =
new RootSetBuilder(application, appInfo, options.mainDexKeepRules).run(executorService);
- mainDexBaseClasses = enqueuer.traceMainDex(mainDexRootSet, timing);
+ Set<DexType> mainDexBaseClasses = enqueuer.traceMainDex(mainDexRootSet, timing);
// Calculate the automatic main dex list according to legacy multidex constraints.
// Add those classes to an eventual manual list of classes.
@@ -309,7 +308,8 @@
}
}
- if (!rootSet.checkDiscarded.isEmpty()) {
+ // Only perform discard-checking if tree-shaking is turned on.
+ if (options.useTreeShaking && !rootSet.checkDiscarded.isEmpty()) {
new DiscardedChecker(rootSet, application).run();
}
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index d7fb9f8..1636c56 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.dex.VirtualFile.FilePerClassDistributor;
import com.android.tools.r8.dex.VirtualFile.FillFilesDistributor;
import com.android.tools.r8.dex.VirtualFile.PackageMapDistributor;
+import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationSet;
@@ -124,6 +125,16 @@
assert packageDistribution == null :
"Cannot combine package distribution definition with file-per-class option.";
distributor = new FilePerClassDistributor(this);
+ } else if (options.minApiLevel < Constants.ANDROID_L_API
+ && options.mainDexKeepRules.isEmpty()
+ && application.mainDexList.isEmpty()) {
+ if (packageDistribution != null) {
+ throw new CompilationError("Cannot apply package distribution. Multidex is not"
+ + " supported with API level " + options.minApiLevel +"."
+ + " For API level < " + Constants.ANDROID_L_API + ", main dex classes list or"
+ + " rules must be specified.");
+ }
+ distributor = new VirtualFile.MonoDexDistributor(this);
} else if (packageDistribution != null) {
assert !options.minimalMainDex :
"Cannot combine package distribution definition with minimal-main-dex option.";
diff --git a/src/main/java/com/android/tools/r8/dex/Constants.java b/src/main/java/com/android/tools/r8/dex/Constants.java
index 9527a97..3ea63bb 100644
--- a/src/main/java/com/android/tools/r8/dex/Constants.java
+++ b/src/main/java/com/android/tools/r8/dex/Constants.java
@@ -10,8 +10,8 @@
public static final int ANDROID_O_API = 26;
public static final int ANDROID_N_API = 24;
- public static final int ANDROID_K_API = 19;
public static final int ANDROID_L_API = 21;
+ public static final int ANDROID_K_API = 19;
public static final int DEFAULT_ANDROID_API = 1;
/** dex file version number for Android O (API level 26) */
diff --git a/src/main/java/com/android/tools/r8/dex/VirtualFile.java b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
index 55511fd..0e89d4a 100644
--- a/src/main/java/com/android/tools/r8/dex/VirtualFile.java
+++ b/src/main/java/com/android/tools/r8/dex/VirtualFile.java
@@ -325,6 +325,27 @@
}
}
+ public static class MonoDexDistributor extends DistributorBase {
+ public MonoDexDistributor(ApplicationWriter writer) {
+ super(writer);
+ }
+
+ @Override
+ public Map<Integer, VirtualFile> run() throws ExecutionException, IOException {
+ VirtualFile mainDexFile = new VirtualFile(0, writer.namingLens);
+ nameToFileMap.put(0, mainDexFile);
+
+ for (DexProgramClass programClass : classes) {
+ mainDexFile.addClass(programClass);
+ if (mainDexFile.isFull()) {
+ throw new CompilationError("Cannot fit all classes in a single dex file.");
+ }
+ }
+ mainDexFile.commitTransaction();
+ return nameToFileMap;
+ }
+ }
+
public static class PackageMapDistributor extends DistributorBase {
private final PackageDistribution packageDistribution;
private final ExecutorService executorService;
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index 04c01be..dca5e02 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -19,7 +19,7 @@
public abstract String toString();
- public abstract String toString(ClassNameMapper naming);
+ public abstract String toString(DexEncodedMethod method, ClassNameMapper naming);
public boolean isDexCode() {
return false;
diff --git a/src/main/java/com/android/tools/r8/graph/DexApplication.java b/src/main/java/com/android/tools/r8/graph/DexApplication.java
index e7485aa..eea0169 100644
--- a/src/main/java/com/android/tools/r8/graph/DexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DexApplication.java
@@ -174,7 +174,7 @@
ps.println("Bytecode for");
ps.println("Class: '" + clazzName + "'");
ps.println("Method: '" + methodName + "':");
- ps.println(method.getCode().toString(naming));
+ ps.println(method.getCode().toString(method, naming));
} catch (IOException e) {
e.printStackTrace();
} finally {
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index ebfd388..f48e7db 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -15,9 +15,11 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringUtils;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -157,10 +159,10 @@
}
public String toString() {
- return toString(null);
+ return toString(null, null);
}
- public String toString(ClassNameMapper naming) {
+ public String toString(DexEncodedMethod method, ClassNameMapper naming) {
StringBuilder builder = new StringBuilder();
builder.append("registers: ").append(registerSize);
builder.append(", inputs: ").append(incomingRegisterSize);
@@ -168,12 +170,22 @@
builder.append("------------------------------------------------------------\n");
builder.append("inst# offset instruction arguments\n");
builder.append("------------------------------------------------------------\n");
+ DexDebugEntry debugInfo = null;
+ Iterator<DexDebugEntry> debugInfoIterator = Collections.emptyIterator();
+ if (getDebugInfo() != null && method != null) {
+ debugInfoIterator = new DexDebugEntryBuilder(method, new DexItemFactory()).build().iterator();
+ debugInfo = debugInfoIterator.hasNext() ? debugInfoIterator.next() : null;
+ }
int instructionNumber = 0;
for (Instruction insn : instructions) {
StringUtils.appendLeftPadded(builder, Integer.toString(instructionNumber++), 5);
builder.append(": ")
.append(insn.toString(naming))
.append('\n');
+ if (debugInfo != null && debugInfo.address == insn.getOffset()) {
+ builder.append(" ").append(debugInfo).append("\n");
+ debugInfo = debugInfoIterator.hasNext() ? debugInfoIterator.next() : null;
+ }
}
if (tries.length > 0) {
builder.append("Tries (numbers are offsets)\n");
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
index f6d8fb4..4410f2a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
+import com.android.tools.r8.ir.code.MoveType;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.HashMap;
@@ -60,19 +61,19 @@
DexCode code = method.getCode().asDexCode();
DexDebugInfo info = code.getDebugInfo();
int argumentRegister = code.registerSize - code.incomingRegisterSize;
- int argumentCount = code.incomingRegisterSize;
if (!method.accessFlags.isStatic()) {
- --argumentCount;
DexString name = factory.thisName;
DexType type = method.method.getHolder();
- startLocal(argumentRegister++, name, type, null);
+ startLocal(argumentRegister, name, type, null);
+ argumentRegister += MoveType.fromDexType(type).requiredRegisters();
}
DexType[] types = method.method.proto.parameters.values;
DexString[] names = info.parameters;
- for (int i = 0; i < argumentCount; i++) {
+ for (int i = 0; i < types.length; i++) {
// If null, the parameter has a parameterized type and the local is introduced in the stream.
if (names[i] != null) {
- startLocal(argumentRegister++, names[i], types[i], null);
+ startLocal(argumentRegister, names[i], types[i], null);
+ argumentRegister += MoveType.fromDexType(types[i]).requiredRegisters();
}
}
currentLine = info.startLine;
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 35ebaf2..3df2fab 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -348,7 +348,7 @@
}
public String codeToString() {
- return code == null ? "<no code>" : code.toString();
+ return code == null ? "<no code>" : code.toString(this, null);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/JarCode.java b/src/main/java/com/android/tools/r8/graph/JarCode.java
index 2766684..9a367ff 100644
--- a/src/main/java/com/android/tools/r8/graph/JarCode.java
+++ b/src/main/java/com/android/tools/r8/graph/JarCode.java
@@ -112,7 +112,7 @@
}
@Override
- public String toString(ClassNameMapper naming) {
+ public String toString(DexEncodedMethod method, ClassNameMapper naming) {
return toString();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
index 0da5b43..6c5fbb7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
@@ -90,7 +90,7 @@
@Override
public void buildDex(DexBuilder builder) {
if (!dest().needsRegister()) {
- builder.addNop(this);
+ builder.addFallThrough(this);
return;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
index 4e078a5..28d6b2b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
@@ -35,7 +35,7 @@
@Override
public void buildDex(DexBuilder builder) {
- builder.addNop(this);
+ builder.addDebugPosition(this);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index 50afe5f..a306bbd 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -44,6 +44,7 @@
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.DebugPosition;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.InstructionIterator;
@@ -331,8 +332,13 @@
public void addGoto(com.android.tools.r8.ir.code.Goto jump) {
if (jump.getTarget() != nextBlock) {
add(jump, new GotoInfo(jump));
+ return;
+ }
+ List<com.android.tools.r8.ir.code.Instruction> instructions = jump.getBlock().getInstructions();
+ if (instructions.size() > 1) {
+ addFallThroughOrNop(jump, instructions.get(instructions.size() - 2), nextBlock.entry());
} else {
- addNop(jump);
+ addFallThrough(jump);
}
}
@@ -345,10 +351,32 @@
add(move, new MoveInfo(move));
}
- public void addNop(com.android.tools.r8.ir.code.Instruction instruction) {
+ public void addFallThrough(com.android.tools.r8.ir.code.Instruction instruction) {
add(instruction, new FallThroughInfo(instruction));
}
+ private void addFallThroughOrNop(
+ com.android.tools.r8.ir.code.Instruction key,
+ com.android.tools.r8.ir.code.Instruction instruction,
+ com.android.tools.r8.ir.code.Instruction nextInstruction) {
+ if (nextInstruction != null
+ && instruction.isDebugPosition()
+ && nextInstruction.isDebugPosition()) {
+ add(key, new FixedSizeInfo(key, new Nop()));
+ } else {
+ addFallThrough(key);
+ }
+ }
+
+ public void addDebugPosition(DebugPosition position) {
+ BasicBlock block = position.getBlock();
+ int nextIndex = block.getInstructions().indexOf(position) + 1;
+ List<com.android.tools.r8.ir.code.Instruction> instructions = block.getInstructions();
+ com.android.tools.r8.ir.code.Instruction nextInstruction =
+ nextIndex < instructions.size() ? instructions.get(nextIndex) : null;
+ addFallThroughOrNop(position, position, nextInstruction);
+ }
+
public void add(com.android.tools.r8.ir.code.Instruction ir, Instruction dex) {
assert !ir.isGoto();
add(ir, new FixedSizeInfo(ir, dex));
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 5984820..f58ea72 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -560,7 +560,7 @@
// Always perform dead code elimination before register allocation. The register allocator
// does not allow dead code (to make sure that we do not waste registers for unneeded values).
DeadCodeRemover.removeDeadCode(code, codeRewriter, options);
- LinearScanRegisterAllocator registerAllocator = new LinearScanRegisterAllocator(code);
+ LinearScanRegisterAllocator registerAllocator = new LinearScanRegisterAllocator(code, options);
registerAllocator.allocateRegisters(options.debug);
printMethod(code, "After register allocation (non-SSA)");
printLiveRanges(registerAllocator, "Final live ranges.");
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index baaf7d0..c3f2d08 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -166,7 +166,7 @@
private boolean isInMainDexList(DexType iface) {
ImmutableSet<DexType> list = converter.application.mainDexList;
- return list != null && list.contains(iface);
+ return list.contains(iface);
}
// Represent a static interface method as a method of companion class.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 4ab72f6..0ea5761 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -991,7 +991,7 @@
}
@Override
- public String toString(ClassNameMapper naming) {
+ public String toString(DexEncodedMethod method, ClassNameMapper naming) {
return null;
}
}
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 a30f574..9276f45 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
@@ -25,6 +25,7 @@
import com.android.tools.r8.ir.code.Xor;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.utils.CfgPrinter;
+import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.HashMultiset;
@@ -109,6 +110,8 @@
private final IRCode code;
// Number of registers used for arguments.
private final int numberOfArgumentRegisters;
+ // Compiler options.
+ private final InternalOptions options;
// Mapping from basic blocks to the set of values live at entry to that basic block.
private Map<BasicBlock, Set<Value>> liveAtEntrySets = new IdentityHashMap<>();
@@ -144,8 +147,9 @@
// register.
private boolean hasDedicatedMoveExceptionRegister = false;
- public LinearScanRegisterAllocator(IRCode code) {
+ public LinearScanRegisterAllocator(IRCode code, InternalOptions options) {
this.code = code;
+ this.options = options;
int argumentRegisters = 0;
for (Instruction instruction : code.blocks.getFirst().getInstructions()) {
if (instruction.isArgument()) {
@@ -919,6 +923,13 @@
if (mode == ArgumentReuseMode.ALLOW_ARGUMENT_REUSE) {
// The sentinel registers cannot be used and we block them.
freePositions.set(0, 0, false);
+ if (options.debug && !code.method.accessFlags.isStatic()) {
+ // If we are generating debug information, we pin the this value register since the
+ // debugger expects to always be able to find it in the input register.
+ assert numberOfArgumentRegisters > 0;
+ assert preArgumentSentinelValue.getNextConsecutive().requiredRegisters() == 1;
+ freePositions.set(1, 0, false);
+ }
int lastSentinelRegister = numberOfArgumentRegisters + NUMBER_OF_SENTINEL_REGISTERS - 1;
if (lastSentinelRegister <= registerConstraint) {
freePositions.set(lastSentinelRegister, 0, false);
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
index 7716663..3d3f9f1 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/SynthesizedCode.java
@@ -37,7 +37,7 @@
@Override
public final String toString() {
- return toString(null);
+ return toString(null, null);
}
private static void registerReachableDefinitionsDefault(UseRegistry registry) {
@@ -61,7 +61,7 @@
}
@Override
- public final String toString(ClassNameMapper naming) {
+ public final String toString(DexEncodedMethod method, ClassNameMapper naming) {
return "SynthesizedCode: " + sourceCode.toString();
}
}
diff --git a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
index f7cbee8..d548e11 100644
--- a/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
+++ b/src/test/java/com/android/tools/r8/JctfTestSpecifications.java
@@ -7,6 +7,7 @@
import static com.android.tools.r8.TestCondition.D8_COMPILER;
import static com.android.tools.r8.TestCondition.R8_AFTER_D8_COMPILER;
import static com.android.tools.r8.TestCondition.R8_COMPILER;
+import static com.android.tools.r8.TestCondition.R8_NOT_AFTER_D8_COMPILER;
import static com.android.tools.r8.TestCondition.any;
import static com.android.tools.r8.TestCondition.match;
import static com.android.tools.r8.TestCondition.runtimes;
@@ -4415,7 +4416,7 @@
// 1) t02
// java.lang.AssertionError: Failed to load serialization resource file: serialization/com/google/jctf/test/lib/java/util/concurrent/PriorityBlockingQueue/serialization/PriorityBlockingQueue_serialization_A01.golden.0.ser
- .put("lang.ThreadGroup.destroy.ThreadGroup_destroy_A01", match(R8_COMPILER))
+ .put("lang.ThreadGroup.destroy.ThreadGroup_destroy_A01", match(R8_NOT_AFTER_D8_COMPILER))
// 1) t05
// java.lang.AssertionError: Destroyed thread group was not finalized
diff --git a/src/test/java/com/android/tools/r8/compatdx/CompatDxTests.java b/src/test/java/com/android/tools/r8/compatdx/CompatDxTests.java
index bd97a3b..81f660a 100644
--- a/src/test/java/com/android/tools/r8/compatdx/CompatDxTests.java
+++ b/src/test/java/com/android/tools/r8/compatdx/CompatDxTests.java
@@ -103,7 +103,7 @@
public void singleDexProgramIsTooLarge() throws IOException, ExecutionException {
// Generate an application that will not fit into a single dex file.
AndroidApp generated = MainDexListTests.generateApplication(
- ImmutableList.of("A", "B"), Constants.DEFAULT_ANDROID_API, Constants.U16BIT_MAX / 2 + 1);
+ ImmutableList.of("A", "B"), Constants.ANDROID_L_API, Constants.U16BIT_MAX / 2 + 1);
Path applicationJar = temp.newFile("application.jar").toPath();
generated.write(applicationJar, OutputMode.Indexed, true);
thrown.expect(CompilationError.class);
diff --git a/src/test/java/com/android/tools/r8/debuginfo/BackBranchToSelfTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/BackBranchToSelfTestRunner.java
index ebd1b0b..24eae68 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/BackBranchToSelfTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/BackBranchToSelfTestRunner.java
@@ -27,14 +27,8 @@
}
private void checkBackBranchToSelf(DebugInfoInspector info, boolean dx) {
- if (dx) {
- info.checkStartLine(10);
- // b/37494646 D8/R8 if-simplification has replaced if by a goto and lost this position.
- info.checkLineHasExactLocals(10, "loop", "boolean");
- } else {
- // D8/R8 will always start at the first debuggable line.
- info.checkStartLine(13);
- }
+ info.checkStartLine(10);
+ info.checkLineHasExactLocals(10, "loop", "boolean");
info.checkNoLine(11);
info.checkNoLine(12);
info.checkLineHasExactLocals(13, "loop", "boolean");
diff --git a/src/test/java/com/android/tools/r8/dex/ExtraFileTest.java b/src/test/java/com/android/tools/r8/dex/ExtraFileTest.java
index 376577c..d1e46f3 100644
--- a/src/test/java/com/android/tools/r8/dex/ExtraFileTest.java
+++ b/src/test/java/com/android/tools/r8/dex/ExtraFileTest.java
@@ -47,6 +47,7 @@
R8Command.builder()
.addProgramFiles(original)
.setOutputPath(out)
+ .setMinApiLevel(Constants.ANDROID_L_API) // Allow native multidex.
.setProguardMapFile(proguardMap)
.setPackageDistributionFile(packageMap)
.build();
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 2841779..d5e66b8 100644
--- a/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
+++ b/src/test/java/com/android/tools/r8/internal/CompilationTestBase.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.ArtErrorParser;
@@ -70,6 +71,7 @@
outputApp = ToolHelper.runR8(builder.build(),
options -> {
options.printSeeds = false;
+ options.minApiLevel = Constants.ANDROID_L_API;
});
} else {
assert compiler == CompilerUnderTest.D8;
@@ -78,6 +80,7 @@
D8Command.builder()
.addProgramFiles(ListUtils.map(inputs, Paths::get))
.setMode(mode)
+ .setMinApiLevel(Constants.ANDROID_L_API)
.build());
}
Path out = temp.getRoot().toPath().resolve("all.zip");
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreDeterministicTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreDeterministicTest.java
index 755fcab..74f9ef9 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreDeterministicTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreDeterministicTest.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.R8Command;
import com.android.tools.r8.Resource;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.ir.conversion.CallGraph;
import com.android.tools.r8.shaking.ProguardRuleParserException;
@@ -43,6 +44,7 @@
options.testing.irOrdering = this::shuffle;
// Only use one thread to process to process in the order decided by the callback.
options.numberOfThreads = 1;
+ options.minApiLevel = Constants.ANDROID_L_API;
});
}
diff --git a/src/test/java/com/android/tools/r8/internal/R8GMSCoreFixedPointTest.java b/src/test/java/com/android/tools/r8/internal/R8GMSCoreFixedPointTest.java
index b6d3dac..376ccf3 100644
--- a/src/test/java/com/android/tools/r8/internal/R8GMSCoreFixedPointTest.java
+++ b/src/test/java/com/android/tools/r8/internal/R8GMSCoreFixedPointTest.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.CompilationException;
import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.shaking.ProguardRuleParserException;
import com.android.tools.r8.utils.AndroidApp;
import java.io.IOException;
@@ -21,14 +22,18 @@
throws ExecutionException, IOException, ProguardRuleParserException, CompilationException {
// First compilation.
AndroidApp app = AndroidApp.fromProgramDirectory(Paths.get(GMSCORE_V7_DIR));
- AndroidApp app1 = ToolHelper.runR8(app);
+ AndroidApp app1 =
+ ToolHelper.runR8(app, options -> options.minApiLevel = Constants.ANDROID_L_API);
// Second compilation.
// Add option --skip-outline-opt for second compilation. The second compilation can find
// additional outlining opportunities as member rebinding from the first compilation can move
// methods.
// See b/33410508 and b/33475705.
- AndroidApp app2 = ToolHelper.runR8(app1, options -> options.outline.enabled = false);
+ AndroidApp app2 = ToolHelper.runR8(app1, options -> {
+ options.outline.enabled = false;
+ options.minApiLevel = Constants.ANDROID_L_API;
+ });
// TODO: Require that the results of the two compilations are the same.
assertEquals(
diff --git a/src/test/java/com/android/tools/r8/jasmin/JumpSubroutineDebugInfoTests.java b/src/test/java/com/android/tools/r8/jasmin/JumpSubroutineDebugInfoTests.java
index d0d1e83..f5254fc 100644
--- a/src/test/java/com/android/tools/r8/jasmin/JumpSubroutineDebugInfoTests.java
+++ b/src/test/java/com/android/tools/r8/jasmin/JumpSubroutineDebugInfoTests.java
@@ -60,8 +60,7 @@
assertEquals(expected, artResult);
DebugInfoInspector info = new DebugInfoInspector(d8App, clazz.name, foo);
- // The first debuggable line will be line 3.
- info.checkStartLine(3);
+ info.checkStartLine(1);
// Check the subroutine line is duplicated 3 times.
assertEquals(3, info.checkLineHasExactLocals(3, "x", "int"));
}
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 4eb8545..a0a77d1 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -396,6 +396,7 @@
throws IOException, ExecutionException {
Timing timing = new Timing("MainDexListTests");
InternalOptions options = new InternalOptions();
+ options.minApiLevel = minApi;
DexItemFactory factory = options.itemFactory;
DexApplication.Builder builder = new DexApplication.Builder(factory, timing);
for (String clazz : classes) {
@@ -419,7 +420,7 @@
DexAnnotationSetRefList.empty(),
code);
IRCode ir = code.buildIR(method, options);
- RegisterAllocator allocator = new LinearScanRegisterAllocator(ir);
+ RegisterAllocator allocator = new LinearScanRegisterAllocator(ir, options);
method.setCode(ir, allocator, factory);
directMethods[i] = method;
}
diff --git a/third_party/android_jar/lib-v21.tar.gz.sha1 b/third_party/android_jar/lib-v21.tar.gz.sha1
new file mode 100644
index 0000000..8d42abc
--- /dev/null
+++ b/third_party/android_jar/lib-v21.tar.gz.sha1
@@ -0,0 +1 @@
+83d20da35ba7b7b1a8b48a2da8dfe3b95d59392a
\ No newline at end of file
diff --git a/tools/gmscore_data.py b/tools/gmscore_data.py
index 4b9c430..9939e1c 100644
--- a/tools/gmscore_data.py
+++ b/tools/gmscore_data.py
@@ -20,6 +20,7 @@
V10_BASE = os.path.join(BASE, 'gmscore_v10')
V10_PREFIX = os.path.join(V10_BASE, 'GmsCore_prod_alldpi_release_all_locales')
+ANDROID_L_API = '21'
# NOTE: we always use android.jar for SDK v25, later we might want to revise it
# to use proper android.jar version for each of gmscore version separately.
@@ -32,6 +33,7 @@
'pgmap' : os.path.join(V4_BASE, 'proguard.map'),
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
}
},
'v5': {
@@ -40,6 +42,7 @@
'pgmap' : os.path.join(V5_BASE, 'proguard.map'),
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
}
},
'v6': {
@@ -48,6 +51,7 @@
'pgmap' : os.path.join(V6_BASE, 'proguard.map'),
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
}
},
'v7': {
@@ -56,6 +60,7 @@
'pgmap' : os.path.join(V7_BASE, 'proguard.map'),
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
}
},
'v8': {
@@ -64,6 +69,7 @@
'pgmap' : os.path.join(V8_BASE, 'proguard.map'),
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
}
},
'v9': {
@@ -72,15 +78,18 @@
'pgmap': '%s_proguard.map' % V9_PREFIX,
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
},
'deploy' : {
'pgconf': ['%s_proguard.config' % V9_PREFIX],
- 'inputs': ['%s_deploy.jar' % V9_PREFIX]
+ 'inputs': ['%s_deploy.jar' % V9_PREFIX],
+ 'min-sdk-version' : ANDROID_L_API,
},
'proguarded' : {
'inputs': ['%s_proguard.jar' % V9_PREFIX],
- 'pgmap': '%s_proguard.map' % V9_PREFIX
- }
+ 'pgmap': '%s_proguard.map' % V9_PREFIX,
+ 'min-sdk-version' : ANDROID_L_API,
+ }
},
'v10': {
'dex' : {
@@ -88,14 +97,17 @@
'pgmap': '%s_proguard.map' % V10_PREFIX,
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
},
'deploy' : {
'inputs': ['%s_deploy.jar' % V10_PREFIX],
'pgconf': ['%s_proguard.config' % V10_PREFIX],
+ 'min-sdk-version' : ANDROID_L_API,
},
'proguarded' : {
'inputs': ['%s_proguard.jar' % V10_PREFIX],
- 'pgmap': '%s_proguard.map' % V10_PREFIX
+ 'pgmap': '%s_proguard.map' % V10_PREFIX,
+ 'min-sdk-version' : ANDROID_L_API,
}
},
}
diff --git a/tools/run_on_app.py b/tools/run_on_app.py
index ddc1e47..312f4b0a 100755
--- a/tools/run_on_app.py
+++ b/tools/run_on_app.py
@@ -125,6 +125,8 @@
inputs = values['inputs']
args.extend(['--output', outdir])
+ if 'min-sdk-version' in values:
+ args.extend(['--min-sdk-version', values['min-sdk-version']])
if options.compiler == 'r8':
if 'pgmap' in values:
diff --git a/tools/youtube_data.py b/tools/youtube_data.py
index b32a372..5ec6bee 100644
--- a/tools/youtube_data.py
+++ b/tools/youtube_data.py
@@ -7,6 +7,7 @@
import utils
THIRD_PARTY = os.path.join(utils.REPO_ROOT, 'third_party')
+ANDROID_L_API = '21'
BASE = os.path.join(THIRD_PARTY, 'youtube')
V12_10_BASE = os.path.join(BASE, 'youtube.android_12.10')
@@ -29,15 +30,18 @@
'pgmap': '%s_proguard.map' % V12_10_PREFIX,
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
},
'deploy' : {
'inputs': ['%s_deploy.jar' % V12_10_PREFIX],
'pgconf': ['%s_proguard.config' % V12_10_PREFIX,
'%s/proguardsettings/YouTubeRelease_proguard.config' % THIRD_PARTY],
+ 'min-sdk-version' : ANDROID_L_API,
},
'proguarded' : {
'inputs': ['%s_proguard.jar' % V12_10_PREFIX],
- 'pgmap': '%s_proguard.map' % V12_10_PREFIX
+ 'pgmap': '%s_proguard.map' % V12_10_PREFIX,
+ 'min-sdk-version' : ANDROID_L_API,
}
},
'12.17': {
@@ -46,15 +50,18 @@
'pgmap': '%s_proguard.map' % V12_17_PREFIX,
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
},
'deploy' : {
'inputs': ['%s_deploy.jar' % V12_17_PREFIX],
'pgconf': ['%s_proguard.config' % V12_17_PREFIX,
'%s/proguardsettings/YouTubeRelease_proguard.config' % THIRD_PARTY],
+ 'min-sdk-version' : ANDROID_L_API,
},
'proguarded' : {
'inputs': ['%s_proguard.jar' % V12_17_PREFIX],
- 'pgmap': '%s_proguard.map' % V12_17_PREFIX
+ 'pgmap': '%s_proguard.map' % V12_17_PREFIX,
+ 'min-sdk-version' : ANDROID_L_API,
}
},
'12.22': {
@@ -63,6 +70,7 @@
'pgmap': '%s_proguard.map' % V12_22_PREFIX,
'libraries' : [ANDROID_JAR],
'r8-flags': '--ignore-missing-classes',
+ 'min-sdk-version' : ANDROID_L_API,
},
'deploy' : {
'inputs': ['%s_deploy.jar' % V12_22_PREFIX],
@@ -73,10 +81,12 @@
os.path.join(V12_22_BASE, 'mainDexClasses.rules'),
os.path.join(V12_22_BASE, 'main-dex-classes-release.cfg'),
os.path.join(V12_22_BASE, 'main_dex_YouTubeRelease_proguard.cfg')],
+ 'min-sdk-version' : ANDROID_L_API,
},
'proguarded' : {
'inputs': ['%s_proguard.jar' % V12_22_PREFIX],
- 'pgmap': '%s_proguard.map' % V12_22_PREFIX
+ 'pgmap': '%s_proguard.map' % V12_22_PREFIX,
+ 'min-sdk-version' : ANDROID_L_API,
}
},
}