Merge "Print retraced stack-trace on test-error"
diff --git a/build.gradle b/build.gradle
index 8ff95c8..93d7e1b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -678,7 +678,6 @@
baseName = "r8tests"
from sourceSets.test.output
if (!project.hasProperty('exclude_deps')) {
- relocate('com.google.common', 'com.android.tools.r8.com.google.common')
relocate('org.objectweb.asm', 'com.android.tools.r8.org.objectweb.asm')
}
}
diff --git a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
index a55033a..5eb0151 100644
--- a/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
+++ b/src/main/java/com/android/tools/r8/GenerateMainDexListCommand.java
@@ -25,7 +25,7 @@
@Keep
public class GenerateMainDexListCommand extends BaseCommand {
- private final ImmutableList<ProguardConfigurationRule> mainDexKeepRules;
+ private final List<ProguardConfigurationRule> mainDexKeepRules;
private final StringConsumer mainDexListConsumer;
private final GraphConsumer mainDexKeptGraphConsumer;
private final DexItemFactory factory;
@@ -108,7 +108,7 @@
return new GenerateMainDexListCommand(isPrintHelp(), isPrintVersion());
}
- ImmutableList<ProguardConfigurationRule> mainDexKeepRules;
+ List<ProguardConfigurationRule> mainDexKeepRules;
if (this.mainDexRules.isEmpty()) {
mainDexKeepRules = ImmutableList.of();
} else {
@@ -199,7 +199,7 @@
private GenerateMainDexListCommand(
DexItemFactory factory,
AndroidApp inputApp,
- ImmutableList<ProguardConfigurationRule> mainDexKeepRules,
+ List<ProguardConfigurationRule> mainDexKeepRules,
StringConsumer mainDexListConsumer,
GraphConsumer mainDexKeptGraphConsumer,
Reporter reporter) {
diff --git a/src/main/java/com/android/tools/r8/R8Command.java b/src/main/java/com/android/tools/r8/R8Command.java
index 39630f3..cca17bf 100644
--- a/src/main/java/com/android/tools/r8/R8Command.java
+++ b/src/main/java/com/android/tools/r8/R8Command.java
@@ -357,7 +357,7 @@
private R8Command makeR8Command() {
Reporter reporter = getReporter();
DexItemFactory factory = new DexItemFactory();
- ImmutableList<ProguardConfigurationRule> mainDexKeepRules;
+ List<ProguardConfigurationRule> mainDexKeepRules;
if (this.mainDexRules.isEmpty()) {
mainDexKeepRules = ImmutableList.of();
} else {
@@ -510,7 +510,7 @@
static final String USAGE_MESSAGE = R8CommandParser.USAGE_MESSAGE;
- private final ImmutableList<ProguardConfigurationRule> mainDexKeepRules;
+ private final List<ProguardConfigurationRule> mainDexKeepRules;
private final ProguardConfiguration proguardConfiguration;
private final boolean enableTreeShaking;
private final boolean enableMinification;
@@ -571,7 +571,7 @@
private R8Command(
AndroidApp inputApp,
ProgramConsumer programConsumer,
- ImmutableList<ProguardConfigurationRule> mainDexKeepRules,
+ List<ProguardConfigurationRule> mainDexKeepRules,
StringConsumer mainDexListConsumer,
ProguardConfiguration proguardConfiguration,
CompilationMode mode,
diff --git a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
index fd04436..a45064e 100644
--- a/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
+++ b/src/main/java/com/android/tools/r8/graph/AppInfoWithSubtyping.java
@@ -57,7 +57,7 @@
return Collections.unmodifiableSet(missingClasses);
}
- public ImmutableSet<DexType> subtypes(DexType type) {
+ public Set<DexType> subtypes(DexType type) {
assert type.isClassType();
ImmutableSet<DexType> subtypes = subtypeMap.get(type);
return subtypes == null ? ImmutableSet.of() : subtypes;
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
index 07e9440..8eb786a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableMap;
+import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -17,7 +18,7 @@
public final DexString sourceFile;
public final boolean prologueEnd;
public final boolean epilogueBegin;
- public final ImmutableMap<Integer, DebugLocalInfo> locals;
+ public final Map<Integer, DebugLocalInfo> locals;
public final DexMethod method;
public final Position callerPosition;
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index 99833f4..1dcd217 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.conversion.IRBuilder;
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.android.tools.r8.utils.StringUtils.BraceType;
@@ -1297,10 +1298,13 @@
}
public static BasicBlock createRethrowBlock(
- IRCode code, Position position, TypeLatticeElement guardTypeLattice) {
+ IRCode code, Position position, DexType guard, AppInfo appInfo, InternalOptions options) {
+ TypeLatticeElement guardTypeLattice = TypeLatticeElement.fromDexType(guard, false, appInfo);
BasicBlock block = new BasicBlock();
MoveException moveException = new MoveException(
- new Value(code.valueNumberGenerator.next(), guardTypeLattice, null));
+ new Value(code.valueNumberGenerator.next(), guardTypeLattice, null),
+ guard,
+ options);
moveException.setPosition(position);
Throw throwInstruction = new Throw(moveException.outValue);
throwInstruction.setPosition(position);
@@ -1518,7 +1522,10 @@
* Clone catch successors from `fromBlock` into this block.
*/
public void copyCatchHandlers(
- IRCode code, ListIterator<BasicBlock> blockIterator, BasicBlock fromBlock) {
+ IRCode code,
+ ListIterator<BasicBlock> blockIterator,
+ BasicBlock fromBlock,
+ InternalOptions options) {
if (catchHandlers != null && catchHandlers.hasCatchAll()) {
return;
}
@@ -1538,7 +1545,8 @@
catchSuccessor.splitCriticalExceptionEdges(
code.getHighestBlockNumber() + 1,
code.valueNumberGenerator,
- blockIterator::add);
+ blockIterator::add,
+ options);
}
}
@@ -1558,16 +1566,19 @@
public int splitCriticalExceptionEdges(
int nextBlockNumber,
ValueNumberGenerator valueNumberGenerator,
- Consumer<BasicBlock> onNewBlock) {
+ Consumer<BasicBlock> onNewBlock,
+ InternalOptions options) {
List<BasicBlock> predecessors = getMutablePredecessors();
boolean hasMoveException = entry().isMoveException();
TypeLatticeElement exceptionTypeLattice = null;
+ DexType exceptionType = null;
MoveException move = null;
Position position = entry().getPosition();
if (hasMoveException) {
// Remove the move-exception instruction.
move = entry().asMoveException();
exceptionTypeLattice = move.outValue().getTypeLattice();
+ exceptionType = move.getExceptionType();
assert move.getDebugValues().isEmpty();
getInstructions().remove(0);
}
@@ -1588,7 +1599,7 @@
exceptionTypeLattice,
move.getLocalInfo());
values.add(value);
- MoveException newMove = new MoveException(value);
+ MoveException newMove = new MoveException(value, exceptionType, options);
newBlock.add(newMove);
newMove.setPosition(position);
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
index af2dae6..1f9c5e6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
@@ -278,7 +278,7 @@
} else {
nextBlock = null;
}
- currentBlock.copyCatchHandlers(code, blocksIterator, invokeBlock);
+ currentBlock.copyCatchHandlers(code, blocksIterator, invokeBlock, code.options);
if (nextBlock != null) {
BasicBlock b = blocksIterator.next();
assert b == nextBlock;
@@ -311,7 +311,7 @@
if (inlinedBlock.hasCatchHandlers()) {
// The block already has catch handlers, so it has only one throwing instruction, and no
// splitting is required.
- inlinedBlock.copyCatchHandlers(code, blocksIterator, invokeBlock);
+ inlinedBlock.copyCatchHandlers(code, blocksIterator, invokeBlock, code.options);
} else {
// The block does not have catch handlers, so it can have several throwing instructions.
// Therefore the block must be split after each throwing instruction, and the catch
@@ -427,7 +427,7 @@
BasicBlock inlineEntry = inlinee.blocks.getFirst();
BasicBlock inlineExit = null;
- ImmutableList<BasicBlock> normalExits = inlinee.computeNormalExitBlocks();
+ List<BasicBlock> normalExits = inlinee.computeNormalExitBlocks();
if (!normalExits.isEmpty()) {
// Ensure and locate the single return instruction of the inlinee.
InstructionListIterator inlineeIterator =
@@ -516,9 +516,7 @@
}
private InstructionListIterator ensureSingleReturnInstruction(
- AppInfo appInfo,
- IRCode code,
- ImmutableList<BasicBlock> normalExits) {
+ AppInfo appInfo, IRCode code, List<BasicBlock> normalExits) {
if (normalExits.size() == 1) {
InstructionListIterator it = normalExits.get(0).listIterator();
it.nextUntil(Instruction::isReturn);
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index 5644ed7..f961b80 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -711,7 +711,7 @@
return new IRCodeInstructionsIterator(this);
}
- public ImmutableList<BasicBlock> computeNormalExitBlocks() {
+ public List<BasicBlock> computeNormalExitBlocks() {
ImmutableList.Builder<BasicBlock> builder = ImmutableList.builder();
for (BasicBlock block : blocks) {
if (block.exit().isReturn()) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index 7cdcd76..fae3557 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -7,21 +7,22 @@
import com.android.tools.r8.cf.TypeVerificationHelper;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppInfo;
-import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
import com.android.tools.r8.ir.optimize.InliningConstraints;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import com.android.tools.r8.utils.InternalOptions;
public class MoveException extends Instruction {
+ private final DexType exceptionType;
+ private final InternalOptions options;
- public MoveException(Value dest) {
+ public MoveException(Value dest, DexType exceptionType, InternalOptions options) {
super(dest);
+ this.exceptionType = exceptionType;
+ this.options = options;
dest.markNeverNull();
}
@@ -48,7 +49,13 @@
@Override
public boolean identicalNonValueNonPositionParts(Instruction other) {
- return other.isMoveException();
+ if (!other.isMoveException()) {
+ return false;
+ }
+ if (options.canHaveExceptionTypeBug()) {
+ return other.asMoveException().exceptionType == exceptionType;
+ }
+ return true;
}
@Override
@@ -88,34 +95,17 @@
return true;
}
- public static Set<DexType> collectExceptionTypes(
- BasicBlock currentBlock, DexItemFactory dexItemFactory) {
- Set<DexType> exceptionTypes = new HashSet<>(currentBlock.getPredecessors().size());
- for (BasicBlock block : currentBlock.getPredecessors()) {
- int size = block.getCatchHandlers().size();
- List<BasicBlock> targets = block.getCatchHandlers().getAllTargets();
- List<DexType> guards = block.getCatchHandlers().getGuards();
- for (int i = 0; i < size; i++) {
- if (targets.get(i) == currentBlock) {
- DexType guard = guards.get(i);
- exceptionTypes.add(
- guard == DexItemFactory.catchAllType
- ? dexItemFactory.throwableType
- : guard);
- }
- }
- }
- return exceptionTypes;
- }
-
@Override
public DexType computeVerificationType(TypeVerificationHelper helper) {
- return helper.join(collectExceptionTypes(getBlock(), helper.getFactory()));
+ return exceptionType;
}
@Override
public TypeLatticeElement evaluate(AppInfo appInfo) {
- Set<DexType> exceptionTypes = collectExceptionTypes(getBlock(), appInfo.dexItemFactory);
- return TypeLatticeElement.joinTypes(exceptionTypes, false, appInfo);
+ return TypeLatticeElement.fromDexType(exceptionType, false, appInfo);
+ }
+
+ public DexType getExceptionType() {
+ return exceptionType;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 007cac1..835399c 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -101,6 +101,7 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IteratorUtils;
import com.android.tools.r8.utils.Pair;
+import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
@@ -116,7 +117,6 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.IdentityHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
@@ -193,11 +193,14 @@
}
private static class MoveExceptionWorklistItem extends WorklistItem {
+ private final DexType guard;
private final int sourceOffset;
private final int targetOffset;
- private MoveExceptionWorklistItem(BasicBlock block, int sourceOffset, int targetOffset) {
+ private MoveExceptionWorklistItem(
+ BasicBlock block, DexType guard, int sourceOffset, int targetOffset) {
super(block, -1);
+ this.guard = guard;
this.sourceOffset = sourceOffset;
this.targetOffset = targetOffset;
}
@@ -707,12 +710,9 @@
// construction and prior to building the IR.
for (BlockInfo info : targets.values()) {
if (info != null && info.block == block) {
- assert info.predecessorCount() == block.getPredecessors().size();
+ assert info.predecessorCount() == nonSplitPredecessorCount(block);
assert info.normalSuccessors.size() == block.getNormalSuccessors().size();
- if (block.hasCatchHandlers()) {
- assert info.exceptionalSuccessors.size()
- == block.getCatchHandlers().getUniqueTargets().size();
- } else {
+ if (!block.hasCatchHandlers()) {
assert !block.canThrow()
|| info.exceptionalSuccessors.isEmpty()
|| (info.exceptionalSuccessors.size() == 1
@@ -726,6 +726,38 @@
return true;
}
+ private int nonSplitPredecessorCount(BasicBlock block) {
+ Set<BasicBlock> set = Sets.newIdentityHashSet();
+ for (BasicBlock predecessor : block.getPredecessors()) {
+ if (offsets.containsKey(predecessor)) {
+ set.add(predecessor);
+ } else {
+ assert predecessor.getSuccessors().size() == 1;
+ assert predecessor.getPredecessors().size() == 1;
+ assert trivialGotoBlockPotentiallyWithMoveException(predecessor);
+ // Combine the exceptional edges to just one, for normal edges that have been split
+ // record them separately. That means that we are checking that there are the expected
+ // number of normal edges and some number of exceptional edges (which we count as one edge).
+ if (predecessor.getPredecessors().get(0).hasCatchSuccessor(predecessor)) {
+ set.add(predecessor.getPredecessors().get(0));
+ } else {
+ set.add(predecessor);
+ }
+ }
+ }
+ return set.size();
+ }
+
+ // Check that all instructions are either move-exception, goto or debug instructions.
+ private boolean trivialGotoBlockPotentiallyWithMoveException(BasicBlock block) {
+ for (Instruction instruction : block.getInstructions()) {
+ assert instruction.isMoveException()
+ || instruction.isGoto()
+ || instruction.isDebugInstruction();
+ }
+ return true;
+ }
+
private void processWorklist() {
for (WorklistItem item = ssaWorklist.poll(); item != null; item = ssaWorklist.poll()) {
if (item.block.isFilled()) {
@@ -782,10 +814,10 @@
int moveExceptionDest = source.getMoveExceptionRegister(targetIndex);
Position position = source.getCanonicalDebugPositionAtOffset(moveExceptionItem.targetOffset);
if (moveExceptionDest >= 0) {
- Set<DexType> exceptionTypes = MoveException.collectExceptionTypes(currentBlock, getFactory());
- TypeLatticeElement typeLattice = TypeLatticeElement.joinTypes(exceptionTypes, false, appInfo);
+ TypeLatticeElement typeLattice =
+ TypeLatticeElement.fromDexType(moveExceptionItem.guard, false, appInfo);
Value out = writeRegister(moveExceptionDest, typeLattice, ThrowingInfo.NO_THROW, null);
- MoveException moveException = new MoveException(out);
+ MoveException moveException = new MoveException(out, moveExceptionItem.guard, options);
moveException.setPosition(position);
currentBlock.add(moveException);
}
@@ -2196,21 +2228,22 @@
assert !throwingInstructionInCurrentBlock;
throwingInstructionInCurrentBlock = true;
List<BasicBlock> targets = new ArrayList<>(catchHandlers.getAllTargets().size());
- // Construct unique move-exception header blocks for each unique target.
- Map<BasicBlock, BasicBlock> moveExceptionHeaders =
- new IdentityHashMap<>(catchHandlers.getUniqueTargets().size());
- for (int targetOffset : catchHandlers.getAllTargets()) {
- BasicBlock target = getTarget(targetOffset);
- BasicBlock header = moveExceptionHeaders.get(target);
- if (header == null) {
- header = new BasicBlock();
- header.incrementUnfilledPredecessorCount();
- moveExceptionHeaders.put(target, header);
- ssaWorklist.add(
- new MoveExceptionWorklistItem(header, currentInstructionOffset, targetOffset));
- }
+ Set<BasicBlock> moveExceptionTargets = Sets.newIdentityHashSet();
+ catchHandlers.forEach((type, targetOffset) -> {
+ DexType exceptionType = type == options.itemFactory.catchAllType
+ ? options.itemFactory.throwableType
+ : type;
+ BasicBlock header = new BasicBlock();
+ header.incrementUnfilledPredecessorCount();
+ ssaWorklist.add(
+ new MoveExceptionWorklistItem(
+ header, exceptionType, currentInstructionOffset, targetOffset));
targets.add(header);
- }
+ BasicBlock target = getTarget(targetOffset);
+ if (!moveExceptionTargets.add(target)) {
+ target.incrementUnfilledPredecessorCount();
+ }
+ });
currentBlock.linkCatchSuccessors(catchHandlers.getGuards(), targets);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index b92d772..5814486 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -332,6 +332,6 @@
BasicBlock currentBlock = newInstance.getBlock();
BasicBlock nextBlock = instructions.split(code, blocks);
assert !instructions.hasNext();
- nextBlock.copyCatchHandlers(code, blocks, currentBlock);
+ nextBlock.copyCatchHandlers(code, blocks, currentBlock, code.options);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
index 293065e..2be7320 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
@@ -394,7 +394,7 @@
}
// Copy catch handlers after all blocks are split.
for (BasicBlock newBlock : newBlocks) {
- newBlock.copyCatchHandlers(code, blocks, currentBlock);
+ newBlock.copyCatchHandlers(code, blocks, currentBlock, code.options);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 0349327..5c1fae1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -321,7 +321,9 @@
BasicBlock rethrowBlock = BasicBlock.createRethrowBlock(
code,
lastSelfRecursiveCall.getPosition(),
- TypeLatticeElement.fromDexType(guard, true, appInfo));
+ guard,
+ appInfo,
+ options);
code.blocks.add(rethrowBlock);
// Add catch handler to the block containing the last recursive call.
newBlock.addCatchHandler(rethrowBlock, guard);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
index fc9f368..c46504c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/PeepholeOptimizer.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.ir.regalloc.LiveIntervals;
import com.android.tools.r8.ir.regalloc.RegisterAllocator;
import com.google.common.base.Equivalence.Wrapper;
-import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import java.util.ArrayList;
@@ -46,7 +45,7 @@
IRCode code, RegisterAllocator allocator, int overhead) {
Collection<BasicBlock> blocks = code.blocks;
BasicBlock normalExit = null;
- ImmutableList<BasicBlock> normalExits = code.computeNormalExitBlocks();
+ List<BasicBlock> normalExits = code.computeNormalExitBlocks();
if (normalExits.size() > 1) {
normalExit = new BasicBlock();
normalExit.getMutablePredecessors().addAll(normalExits);
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
index c1afba9..9cdb95c 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMapper.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.utils.BiMapContainer;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
@@ -96,7 +97,7 @@
}
private final ImmutableMap<String, ClassNamingForNameMapper> classNameMappings;
- private ImmutableBiMap<String, String> nameMapping;
+ private BiMapContainer<String, String> nameMapping;
private final Map<Signature, Signature> signatureMap = new HashMap<>();
@@ -195,13 +196,14 @@
}
}
- public BiMap<String, String> getObfuscatedToOriginalMapping() {
+ public BiMapContainer<String, String> getObfuscatedToOriginalMapping() {
if (nameMapping == null) {
ImmutableBiMap.Builder<String, String> builder = ImmutableBiMap.builder();
for (String name : classNameMappings.keySet()) {
builder.put(name, classNameMappings.get(name).originalName);
}
- nameMapping = builder.build();
+ BiMap<String, String> classNameMappings = builder.build();
+ nameMapping = new BiMapContainer<>(classNameMappings, classNameMappings.inverse());
}
return nameMapping;
}
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
index 1f0e3de..ad084e4 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNameMinifier.java
@@ -33,7 +33,6 @@
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.Timing;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -41,6 +40,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -60,8 +60,8 @@
private final Map<DexType, DexString> renaming = Maps.newIdentityHashMap();
private final Map<String, Namespace> states = new HashMap<>();
- private final ImmutableList<String> packageDictionary;
- private final ImmutableList<String> classDictionary;
+ private final List<String> packageDictionary;
+ private final List<String> classDictionary;
private final boolean keepInnerClassStructure;
private final Set<DexType> noObfuscationTypes;
diff --git a/src/main/java/com/android/tools/r8/naming/ClassRenamingMapper.java b/src/main/java/com/android/tools/r8/naming/ClassRenamingMapper.java
index 71cbc4f..8609fff 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassRenamingMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassRenamingMapper.java
@@ -4,10 +4,11 @@
package com.android.tools.r8.naming;
-import com.google.common.collect.BiMap;
+import com.android.tools.r8.utils.BiMapContainer;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
+import java.util.Map;
/**
* Provides a translation between class names based on a source and target proguard map.
@@ -28,10 +29,11 @@
ImmutableBiMap.Builder<String, String> translationBuilder = ImmutableBiMap.builder();
ImmutableSet.Builder<String> newClasses = ImmutableSet.builder();
- BiMap<String, String> sourceObfuscatedToOriginal = originalMap.getObfuscatedToOriginalMapping();
- BiMap<String, String> sourceOriginalToObfuscated = sourceObfuscatedToOriginal.inverse();
- BiMap<String, String> targetObfuscatedToOriginal = targetMap.getObfuscatedToOriginalMapping();
- BiMap<String, String> targetOriginalToObfuscated = targetObfuscatedToOriginal.inverse();
+ Map<String, String> sourceOriginalToObfuscated =
+ originalMap.getObfuscatedToOriginalMapping().inverse;
+
+ BiMapContainer<String, String> targetMapping = targetMap.getObfuscatedToOriginalMapping();
+ Map<String, String> targetOriginalToObfuscated = targetMapping.inverse;
for (String originalName : sourceOriginalToObfuscated.keySet()) {
String sourceObfuscatedName = sourceOriginalToObfuscated.get(originalName);
@@ -44,8 +46,8 @@
}
ImmutableBiMap<String, String> translation = translationBuilder.build();
- ImmutableSet<String> unusedNames = ImmutableSet
- .copyOf(Sets.difference(targetObfuscatedToOriginal.keySet(), translation.values()));
+ ImmutableSet<String> unusedNames =
+ ImmutableSet.copyOf(Sets.difference(targetMapping.original.keySet(), translation.values()));
return new ClassRenamingMapper(translation, newClasses.build(), unusedNames);
}
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
index 312991e..7f28744 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNameMinifier.java
@@ -9,8 +9,8 @@
import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
import com.android.tools.r8.utils.InternalOptions;
-import com.google.common.collect.ImmutableList;
import java.util.IdentityHashMap;
+import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -19,7 +19,7 @@
protected final AppInfoWithLiveness appInfo;
protected final RootSet rootSet;
protected final InternalOptions options;
- protected final ImmutableList<String> dictionary;
+ protected final List<String> dictionary;
protected final Map<MemberType, DexString> renaming = new IdentityHashMap<>();
protected final Map<DexType, NamingState<StateType, ?>> states = new IdentityHashMap<>();
diff --git a/src/main/java/com/android/tools/r8/naming/NamingState.java b/src/main/java/com/android/tools/r8/naming/NamingState.java
index 4beff54..999579a 100644
--- a/src/main/java/com/android/tools/r8/naming/NamingState.java
+++ b/src/main/java/com/android/tools/r8/naming/NamingState.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
@@ -24,13 +23,13 @@
private final NamingState<ProtoType, KeyType> parent;
private final Map<KeyType, InternalState> usedNames = new HashMap<>();
private final DexItemFactory itemFactory;
- private final ImmutableList<String> dictionary;
+ private final List<String> dictionary;
private final Function<ProtoType, KeyType> keyTransform;
private final boolean useUniqueMemberNames;
static <S, T extends CachedHashValueDexItem> NamingState<T, S> createRoot(
DexItemFactory itemFactory,
- ImmutableList<String> dictionary,
+ List<String> dictionary,
Function<T, S> keyTransform,
boolean useUniqueMemberNames) {
return new NamingState<>(null, itemFactory, dictionary, keyTransform, useUniqueMemberNames);
@@ -39,7 +38,7 @@
private NamingState(
NamingState<ProtoType, KeyType> parent,
DexItemFactory itemFactory,
- ImmutableList<String> dictionary,
+ List<String> dictionary,
Function<ProtoType, KeyType> keyTransform,
boolean useUniqueMemberNames) {
this.parent = parent;
diff --git a/src/main/java/com/android/tools/r8/shaking/FilteredClassPath.java b/src/main/java/com/android/tools/r8/shaking/FilteredClassPath.java
index c67af00..9badf35 100644
--- a/src/main/java/com/android/tools/r8/shaking/FilteredClassPath.java
+++ b/src/main/java/com/android/tools/r8/shaking/FilteredClassPath.java
@@ -7,6 +7,7 @@
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.util.List;
/**
* Implements class path filtering as per
@@ -21,9 +22,9 @@
private final Path path;
private final ImmutableList<String> pattern;
- public FilteredClassPath(Path path, ImmutableList<String> pattern) {
+ public FilteredClassPath(Path path, List<String> pattern) {
this.path = path;
- this.pattern = pattern;
+ this.pattern = ImmutableList.copyOf(pattern);
}
private FilteredClassPath(Path path) {
diff --git a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
index c153fe3..0f511d4 100644
--- a/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
+++ b/src/main/java/com/android/tools/r8/shaking/ProguardConfiguration.java
@@ -466,11 +466,11 @@
return dexItemFactory;
}
- public ImmutableList<FilteredClassPath> getInjars() {
+ public List<FilteredClassPath> getInjars() {
return injars;
}
- public ImmutableList<FilteredClassPath> getLibraryjars() {
+ public List<FilteredClassPath> getLibraryjars() {
return libraryjars;
}
@@ -554,7 +554,7 @@
return dontNotePatterns;
}
- public ImmutableList<ProguardConfigurationRule> getRules() {
+ public List<ProguardConfigurationRule> getRules() {
return rules;
}
@@ -562,15 +562,15 @@
return overloadAggressively && !useUniqueClassMemberNames;
}
- public ImmutableList<String> getObfuscationDictionary() {
+ public List<String> getObfuscationDictionary() {
return obfuscationDictionary;
}
- public ImmutableList<String> getClassObfuscationDictionary() {
+ public List<String> getClassObfuscationDictionary() {
return classObfuscationDictionary;
}
- public ImmutableList<String> getPackageObfuscationDictionary() {
+ public List<String> getPackageObfuscationDictionary() {
return packageObfuscationDictionary;
}
diff --git a/src/main/java/com/android/tools/r8/utils/BiMapContainer.java b/src/main/java/com/android/tools/r8/utils/BiMapContainer.java
new file mode 100644
index 0000000..e8f4f2f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/utils/BiMapContainer.java
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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 java.util.Map;
+
+/**
+ * BiMapContainer is a utility class that can be used when testing BiMaps in R8, reducing the need
+ * to relocate com.google.common in our tests.
+ *
+ * @param <K> The type of keys
+ * @param <V> The type of values
+ */
+public class BiMapContainer<K, V> {
+
+ public final Map<K, V> original;
+ public final Map<K, V> inverse;
+
+ public BiMapContainer(Map<K, V> original, Map<K, V> inverse) {
+ this.original = original;
+ this.inverse = inverse;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index c0c6e59..1e39494 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -261,7 +261,7 @@
public boolean debug = false;
public final TestingOptions testing = new TestingOptions();
- public ImmutableList<ProguardConfigurationRule> mainDexKeepRules = ImmutableList.of();
+ public List<ProguardConfigurationRule> mainDexKeepRules = ImmutableList.of();
public boolean minimalMainDex;
/**
* Enable usage of InheritanceClassInDexDistributor for multidex legacy builds.
@@ -875,4 +875,17 @@
// Marshmallow and Nougat arm64 devices and they do not have the bug.
return minApiLevel < AndroidApiLevel.M.getLevel();
}
+
+ // The Art VM for Android N through P has a bug in the JIT that means that if the same
+ // exception block with a move-exception instruction is targeted with more than one type
+ // of exception the JIT will incorrectly assume that the exception object has one of these
+ // types and will optimize based on that one type instead of taking all the types into account.
+ //
+ // In order to workaround that, we always generate distinct move-exception instructions for
+ // distinct dex types.
+ //
+ // See b/120164595.
+ public boolean canHaveExceptionTypeBug() {
+ return minApiLevel < AndroidApiLevel.Q.getLevel();
+ }
}
diff --git a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
index e6a1fcd..fb61f45 100644
--- a/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
+++ b/src/test/java/com/android/tools/r8/debug/DebugTestBase.java
@@ -779,7 +779,7 @@
public String getObfuscatedClassName(String originalClassName) {
// TODO(tamaskenez) Watch for inline methods (we can be in a different class).
String obfuscatedClassName =
- classNameMapper.getObfuscatedToOriginalMapping().inverse().get(originalClassName);
+ classNameMapper.getObfuscatedToOriginalMapping().inverse.get(originalClassName);
return obfuscatedClassName == null ? originalClassName : obfuscatedClassName;
}
@@ -788,7 +788,7 @@
String originalClassName, String originalMethodName, String methodSignatureOrNull) {
ClassNamingForNameMapper naming;
String obfuscatedClassName =
- classNameMapper.getObfuscatedToOriginalMapping().inverse().get(originalClassName);
+ classNameMapper.getObfuscatedToOriginalMapping().inverse.get(originalClassName);
if (obfuscatedClassName != null) {
naming = classNameMapper.getClassNaming(obfuscatedClassName);
} else {
diff --git a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
index 90aad41..c416c6e 100644
--- a/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
+++ b/src/test/java/com/android/tools/r8/ir/SplitBlockTest.java
@@ -201,7 +201,7 @@
public void runCatchHandlerTest(boolean codeThrows, boolean twoGuards) throws Exception {
final int secondBlockInstructions = 4;
- final int initialBlockCount = 6;
+ final int initialBlockCount = twoGuards ? 7 : 6;
// Try split between all instructions in second block.
for (int i = 1; i < secondBlockInstructions; i++) {
TestApplication test = codeWithCatchHandlers(codeThrows, twoGuards);
@@ -240,7 +240,7 @@
public void runCatchHandlerSplitThreeTest(boolean codeThrows, boolean twoGuards)
throws Exception {
final int secondBlockInstructions = 4;
- final int initialBlockCount = 6;
+ final int initialBlockCount = twoGuards ? 7 : 6;
// Try split out all instructions in second block.
for (int i = 1; i < secondBlockInstructions - 1; i++) {
TestApplication test = codeWithCatchHandlers(codeThrows, twoGuards);
diff --git a/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java b/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
index bfd3b76..437f2dd 100644
--- a/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
+++ b/src/test/java/com/android/tools/r8/naming/AdaptResourceFileNamesTest.java
@@ -471,7 +471,7 @@
break;
}
if (typeName != null) {
- String renamedName = mapper.getObfuscatedToOriginalMapping().inverse().get(typeName);
+ String renamedName = mapper.getObfuscatedToOriginalMapping().inverse.get(typeName);
assertNotNull(renamedName);
assertNotEquals(typeName, renamedName);
return renamedName.replace('.', '/') + suffix;
@@ -506,7 +506,7 @@
break;
}
if (samePackageAsType != null) {
- String renamedName = mapper.getObfuscatedToOriginalMapping().inverse().get(samePackageAsType);
+ String renamedName = mapper.getObfuscatedToOriginalMapping().inverse.get(samePackageAsType);
assertNotNull(renamedName);
assertNotEquals(samePackageAsType, renamedName);
if (renamedName.contains(".")) {
diff --git a/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java b/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
index 983abaa..8a8f137 100644
--- a/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ProguardMapReaderTest.java
@@ -60,7 +60,7 @@
@Test
public void parseMapWithPackageInfo() throws IOException {
ClassNameMapper mapper = ClassNameMapper.mapperFromString(EXAMPLE_MAP_WITH_PACKAGE_INFO);
- Assert.assertTrue(mapper.getObfuscatedToOriginalMapping().isEmpty());
+ Assert.assertTrue(mapper.getObfuscatedToOriginalMapping().original.isEmpty());
}
@Test
diff --git a/src/test/java/com/android/tools/r8/regress/b120164595/B120164595.java b/src/test/java/com/android/tools/r8/regress/b120164595/B120164595.java
index 08e86e6..9d633f2 100644
--- a/src/test/java/com/android/tools/r8/regress/b120164595/B120164595.java
+++ b/src/test/java/com/android/tools/r8/regress/b120164595/B120164595.java
@@ -4,16 +4,14 @@
package com.android.tools.r8.regress.b120164595;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestCompileResult;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.ProcessResult;
-import com.google.common.collect.ImmutableList;
import java.io.IOException;
import org.junit.Test;
@@ -72,8 +70,7 @@
},
DexVm.ART_9_0_0_HOST
);
- // TODO(120164595): Remove when workaround lands.
- assertNotEquals(artResult.exitCode, 0);
- assertTrue(artResult.stderr.contains("Expected NullPointerException"));
+ assertEquals(0, artResult.exitCode);
+ assertFalse(artResult.stderr.contains("Expected NullPointerException"));
}
}
diff --git a/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java b/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
index ba79ec5..1c28054 100644
--- a/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
+++ b/src/test/java/com/android/tools/r8/resource/KeepDirectoriesTest.java
@@ -67,7 +67,7 @@
private String pathForThisPackage(AndroidApp app) throws Exception {
ClassNameMapper mapper =
ClassNameMapper.mapperFromString(app.getProguardMapOutputData().getString());
- String x = mapper.getObfuscatedToOriginalMapping().inverse().get(Main.class.getCanonicalName());
+ String x = mapper.getObfuscatedToOriginalMapping().inverse.get(Main.class.getCanonicalName());
return x.substring(0, x.lastIndexOf('.')).replace('.', '/');
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 3f53530..1f520ff 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -37,11 +37,11 @@
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.BiMapContainer;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.codeinspector.InstructionSubject.JumboStringMode;
-import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.lang.reflect.Method;
@@ -61,7 +61,8 @@
private final DexApplication application;
final DexItemFactory dexItemFactory;
private final ClassNameMapper mapping;
- final BiMap<String, String> originalToObfuscatedMapping;
+ final Map<String, String> originalToObfuscatedMapping;
+ final Map<String, String> obfuscatedToOriginalMapping;
public static MethodSignature MAIN =
new MethodSignature("main", "void", new String[] {"java.lang.String[]"});
@@ -83,10 +84,13 @@
throws IOException, ExecutionException {
if (mappingFile != null) {
this.mapping = ClassNameMapper.mapperFromFile(Paths.get(mappingFile));
- originalToObfuscatedMapping = this.mapping.getObfuscatedToOriginalMapping().inverse();
+ BiMapContainer<String, String> nameMapping = this.mapping.getObfuscatedToOriginalMapping();
+ obfuscatedToOriginalMapping = nameMapping.original;
+ originalToObfuscatedMapping = nameMapping.inverse;
} else {
this.mapping = null;
originalToObfuscatedMapping = null;
+ obfuscatedToOriginalMapping = null;
}
Timing timing = new Timing("CodeInspector");
InternalOptions options = new InternalOptions();
@@ -97,7 +101,7 @@
dexItemFactory = options.itemFactory;
AndroidApp input = AndroidApp.builder().addProgramFiles(files).build();
application = new ApplicationReader(input, options, timing).read();
- }
+ }
public CodeInspector(AndroidApp app) throws IOException, ExecutionException {
this(
@@ -139,8 +143,14 @@
dexItemFactory = application.dexItemFactory;
this.application = application;
this.mapping = application.getProguardMap();
- originalToObfuscatedMapping =
- mapping == null ? null : mapping.getObfuscatedToOriginalMapping().inverse();
+ if (mapping == null) {
+ originalToObfuscatedMapping = null;
+ obfuscatedToOriginalMapping = null;
+ } else {
+ BiMapContainer<String, String> nameMapping = mapping.getObfuscatedToOriginalMapping();
+ obfuscatedToOriginalMapping = nameMapping.original;
+ originalToObfuscatedMapping = nameMapping.inverse;
+ }
}
public DexItemFactory getFactory() {
@@ -251,7 +261,7 @@
name = obfuscated;
} else {
// Figure out if the name is an already obfuscated name.
- String original = originalToObfuscatedMapping.inverse().get(name);
+ String original = obfuscatedToOriginalMapping.get(name);
if (original != null) {
naming = mapping.getClassNaming(name);
}
@@ -393,8 +403,8 @@
@Override
public String parsedTypeName(String name) {
String type = name;
- if (originalToObfuscatedMapping != null) {
- String original = mapType(originalToObfuscatedMapping.inverse(), name);
+ if (obfuscatedToOriginalMapping != null) {
+ String original = mapType(obfuscatedToOriginalMapping, name);
type = original != null ? original : name;
}
signature.append(type);
@@ -409,7 +419,7 @@
String minifiedEnclosing = originalToObfuscatedMapping.get(enclosingType);
if (minifiedEnclosing != null) {
assert !minifiedEnclosing.contains("[");
- type = mapType(originalToObfuscatedMapping.inverse(), minifiedEnclosing + "$" + name);
+ type = mapType(obfuscatedToOriginalMapping, minifiedEnclosing + "$" + name);
if (type != null) {
assert type.startsWith(enclosingType + "$");
name = type.substring(enclosingType.length() + 1);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
index 7efc794..92fc0a0 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundFieldSubject.java
@@ -83,7 +83,7 @@
// whereas the final signature is for X.a is "a a"
String obfuscatedType = signature.type;
String originalType =
- codeInspector.mapType(codeInspector.originalToObfuscatedMapping.inverse(), obfuscatedType);
+ codeInspector.mapType(codeInspector.obfuscatedToOriginalMapping, obfuscatedType);
String fieldType = originalType != null ? originalType : obfuscatedType;
FieldSignature lookupSignature = new FieldSignature(signature.name, fieldType);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 2b4825e..5643091 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -4,9 +4,6 @@
package com.android.tools.r8.utils.codeinspector;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertTrue;
-
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfPosition;
import com.android.tools.r8.code.Instruction;
@@ -125,12 +122,11 @@
String[] OriginalParameters = new String[signature.parameters.length];
for (int i = 0; i < OriginalParameters.length; i++) {
String obfuscated = signature.parameters[i];
- String original = codeInspector.originalToObfuscatedMapping.inverse().get(obfuscated);
+ String original = codeInspector.obfuscatedToOriginalMapping.get(obfuscated);
OriginalParameters[i] = original != null ? original : obfuscated;
}
String obfuscatedReturnType = signature.type;
- String originalReturnType =
- codeInspector.originalToObfuscatedMapping.inverse().get(obfuscatedReturnType);
+ String originalReturnType = codeInspector.obfuscatedToOriginalMapping.get(obfuscatedReturnType);
String returnType = originalReturnType != null ? originalReturnType : obfuscatedReturnType;
MethodSignature lookupSignature =
diff --git a/tools/golem_build.py b/tools/golem_build.py
index 6d3a9b7..d55def1 100755
--- a/tools/golem_build.py
+++ b/tools/golem_build.py
@@ -8,8 +8,8 @@
import gradle
import sys
-GRADLE_ARGS = ['--no-daemon']
-BUILD_TARGETS = ['R8', 'D8', 'buildExampleJars', 'CompatDx',
+GRADLE_ARGS = ['--no-daemon', '-Pno_internal']
+BUILD_TARGETS = ['R8', 'D8', 'R8Lib', 'buildExampleJars', 'CompatDx',
'downloadAndroidCts', 'downloadDx']
def Main():
diff --git a/tools/run_on_as_app.py b/tools/run_on_as_app.py
index 56ea215..244c093 100755
--- a/tools/run_on_as_app.py
+++ b/tools/run_on_as_app.py
@@ -117,7 +117,8 @@
return subprocess.check_output(['git', 'clone', git_url]).strip()
def GitPull():
- return subprocess.call(['git', 'pull']) == 0
+ # Use --no-edit to accept the auto-generated merge message, if any.
+ return subprocess.call(['git', 'pull', '--no-edit']) == 0
def GitCheckout(file):
return subprocess.check_output(['git', 'checkout', file]).strip()
@@ -164,8 +165,12 @@
if not os.path.exists(checkout_dir):
with utils.ChangedWorkingDirectory(WORKING_DIR):
GitClone(git_repo)
- else:
+ elif options.pull:
with utils.ChangedWorkingDirectory(checkout_dir):
+ # Checkout build.gradle to avoid merge conflicts.
+ if IsTrackedByGit('build.gradle'):
+ GitCheckout('build.gradle')
+
if not GitPull():
result['status'] = 'failed'
result['error_message'] = 'Unable to pull from remote'
@@ -185,7 +190,7 @@
with utils.ChangedWorkingDirectory(checkout_dir):
for shrinker in SHRINKERS:
- if options.shrinker is not None and shrinker != options.shrinker:
+ if options.shrinker and shrinker not in options.shrinker:
continue
apk_dest = None
@@ -313,8 +318,12 @@
print(' skipped ({})'.format(error_message))
continue
- baseline = result_per_shrinker.get('proguard', {}).get('dex_size', -1)
- for shrinker, result in result_per_shrinker.iteritems():
+ baseline = float(
+ result_per_shrinker.get('proguard', {}).get('dex_size', -1))
+ for shrinker in SHRINKERS:
+ if shrinker not in result_per_shrinker:
+ continue
+ result = result_per_shrinker.get(shrinker)
build_status = result.get('build_status')
if build_status != 'success':
warn(' {}: {}'.format(shrinker, build_status))
@@ -323,10 +332,13 @@
dex_size = result.get('dex_size')
if dex_size != baseline and baseline >= 0:
if dex_size < baseline:
- success(' dex size: {} ({})'.format(
- dex_size, dex_size - baseline))
- elif dex_size > baseline:
- warn(' dex size: {} ({})'.format(dex_size, dex_size - baseline))
+ success(' dex size: {} ({}, -{}%)'.format(
+ dex_size, dex_size - baseline,
+ round((1.0 - dex_size / baseline) * 100), 1))
+ elif dex_size >= baseline:
+ warn(' dex size: {} ({}, +{}%)'.format(
+ dex_size, dex_size - baseline,
+ round((baseline - dex_size) / dex_size * 100, 1)))
else:
print(' dex size: {}'.format(dex_size))
if options.monkey:
@@ -345,18 +357,26 @@
help='Whether to install and run app(s) with monkey',
default=False,
action='store_true')
+ result.add_option('--pull',
+ help='Whether to pull the latest version of each app',
+ default=False,
+ action='store_true')
result.add_option('--sign_apks',
help='Whether the APKs should be signed',
default=False,
action='store_true')
result.add_option('--shrinker',
- help='The shrinker to use (by default, all are run)',
- choices=SHRINKERS)
+ help='The shrinkers to use (by default, all are run)',
+ action='append')
result.add_option('--disable_tot',
help='Whether to disable the use of the ToT version of R8',
default=False,
action='store_true')
- return result.parse_args(argv)
+ (options, args) = result.parse_args(argv)
+ if options.shrinker:
+ for shrinker in options.shrinker:
+ assert shrinker in SHRINKERS
+ return (options, args)
def main(argv):
global SHRINKERS