diff options
author | Lars Bak <bak@google.com> | 2017-07-14 08:12:41 +0200 |
---|---|---|
committer | Lars Bak <bak@google.com> | 2017-07-14 08:12:41 +0200 |
commit | d6868d33a233569769fda3d8e18db42281a9528e (patch) | |
tree | 155b62ad595947cf8473572792f952041ab15acd /src/main/java/com/android/tools/r8 | |
parent | 787d44d2fc67d976f5f97d8c9aaa023369b8f179 (diff) | |
download | r8-d6868d33a233569769fda3d8e18db42281a9528e.tar.gz |
Fixes a race condition when running R8.
2f4517160f9ce402be795a6555f68b8129cb09da
Bug:
Change-Id: I9c73bc0b9db9feef1cd2b02e62af21861aee6367
Diffstat (limited to 'src/main/java/com/android/tools/r8')
6 files changed, 54 insertions, 43 deletions
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java index 92bb7b20a..e0bfdd0c9 100644 --- a/src/main/java/com/android/tools/r8/ir/code/Value.java +++ b/src/main/java/com/android/tools/r8/ir/code/Value.java @@ -57,7 +57,7 @@ public class Value { public static final Value UNDEFINED = new Value(-1, MoveType.OBJECT, null); protected final int number; - protected MoveType type; + protected final MoveType type; public Instruction definition = null; private LinkedList<Instruction> users = new LinkedList<>(); private Set<Instruction> uniqueUsers = null; @@ -71,7 +71,7 @@ public class Value { private boolean isThis = false; private boolean isArgument = false; private LongInterval valueRange; - private DebugData debugData; + private final DebugData debugData; public Value(int number, MoveType type, DebugInfo debugInfo) { this.number = number; 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 1586496c1..0a6a0ad9f 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 @@ -277,11 +277,9 @@ public class IRConverter { // Process the application identifying outlining candidates. timing.begin("IR conversion phase 1"); - int count = 0; OptimizationFeedback directFeedback = new OptimizationFeedbackDirect(); OptimizationFeedbackDelayed delayedFeedback = new OptimizationFeedbackDelayed(); while (!callGraph.isEmpty()) { - count++; CallGraph.Leaves leaves = callGraph.pickLeaves(); List<DexEncodedMethod> methods = leaves.getLeaves(); assert methods.size() > 0; @@ -320,13 +318,9 @@ public class IRConverter { Builder builder = new Builder(application); builder.setHighestSortingString(highestSortingString); - // Second inlining pass. - if ((inliner != null) && (inliner.doubleInlineCallers.size() > 0)) { - inliner.applyDoubleInlining = true; - for (DexEncodedMethod method : inliner.doubleInlineCallers) { - processMethod(method, ignoreOptimizationFeedback, Outliner::noProcessing); - assert method.isProcessed(); - } + // Second inlining pass for dealing with double inline callers. + if (inliner != null) { + inliner.processDoubleInlineCallers(this, ignoreOptimizationFeedback); } synthesizeLambdaClasses(builder); @@ -430,7 +424,7 @@ public class IRConverter { return options.useSmaliSyntax ? method.toSmaliString(null) : method.codeToString(); } - private void processMethod(DexEncodedMethod method, + public void processMethod(DexEncodedMethod method, OptimizationFeedback feedback, BiConsumer<IRCode, DexEncodedMethod> outlineHandler) { Code code = method.getCode(); 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 2364668ab..203ca80a3 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 @@ -66,6 +66,7 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -853,7 +854,7 @@ public class CodeRewriter { private void splitPhiConstants(IRCode code, BasicBlock block) { for (int i = 0; i < block.getPredecessors().size(); i++) { - Map<ConstNumber, ConstNumber> oldToNew = new HashMap<>(); + Map<ConstNumber, ConstNumber> oldToNew = new IdentityHashMap<>(); BasicBlock predecessor = block.getPredecessors().get(i); for (Phi phi : block.getPhis()) { Value operand = phi.getOperand(i); 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 1f21f5245..6d6981757 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 @@ -19,7 +19,9 @@ import com.android.tools.r8.ir.code.InvokeMethod; import com.android.tools.r8.ir.code.Value; import com.android.tools.r8.ir.code.ValueNumberGenerator; import com.android.tools.r8.ir.conversion.CallGraph; +import com.android.tools.r8.ir.conversion.IRConverter; import com.android.tools.r8.ir.conversion.LensCodeRewriter; +import com.android.tools.r8.ir.conversion.OptimizationFeedback; import com.android.tools.r8.logging.Log; import com.android.tools.r8.utils.InternalOptions; import com.google.common.collect.Sets; @@ -39,10 +41,10 @@ public class Inliner { private final InternalOptions options; // State for inlining methods which are known to be called twice. - public boolean applyDoubleInlining = false; - public final Set<DexEncodedMethod> doubleInlineCallers = Sets.newIdentityHashSet(); - public final Set<DexEncodedMethod> doubleInlineSelectedTargets = Sets.newIdentityHashSet(); - public final Map<DexEncodedMethod, DexEncodedMethod> doubleInlineeCandidates = new HashMap<>(); + private boolean applyDoubleInlining = false; + private final Set<DexEncodedMethod> doubleInlineCallers = Sets.newIdentityHashSet(); + private final Set<DexEncodedMethod> doubleInlineSelectedTargets = Sets.newIdentityHashSet(); + private final Map<DexEncodedMethod, DexEncodedMethod> doubleInlineeCandidates = new HashMap<>(); public Inliner(AppInfoWithSubtyping appInfo, GraphLense graphLense, InternalOptions options) { this.appInfo = appInfo; @@ -89,7 +91,7 @@ public class Inliner { return result; } - protected boolean hasInliningAccess(DexEncodedMethod method, DexEncodedMethod target) { + boolean hasInliningAccess(DexEncodedMethod method, DexEncodedMethod target) { if (target.accessFlags.isPublic()) { return true; } @@ -105,6 +107,40 @@ public class Inliner { return methodHolder.isSamePackage(targetHolder); } + synchronized DexEncodedMethod doubleInlining(DexEncodedMethod method, + DexEncodedMethod target) { + if (!applyDoubleInlining) { + if (doubleInlineeCandidates.containsKey(target)) { + // Both calls can be inlined. + doubleInlineCallers.add(doubleInlineeCandidates.get(target)); + doubleInlineCallers.add(method); + doubleInlineSelectedTargets.add(target); + } else { + // First call can be inlined. + doubleInlineeCandidates.put(target, method); + } + // Just preparing for double inlining. + return null; + } else { + // Don't perform the actual inlining if this was not selected. + if (!doubleInlineSelectedTargets.contains(target)) { + return null; + } + } + return target; + } + + public synchronized void processDoubleInlineCallers(IRConverter converter, + OptimizationFeedback feedback) { + if (doubleInlineCallers.size() > 0) { + applyDoubleInlining = true; + for (DexEncodedMethod method : doubleInlineCallers) { + converter.processMethod(method, feedback, Outliner::noProcessing); + assert method.isProcessed(); + } + } + } + public enum Constraint { // The ordinal values are important so please do not reorder. NEVER, // Never inline this. diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java index febef8206..4b93d8d77 100644 --- a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java +++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java @@ -82,28 +82,6 @@ public class InliningOracle { return candidate; } - private synchronized DexEncodedMethod doubleInlining(DexEncodedMethod candidate) { - if (!inliner.applyDoubleInlining) { - if (inliner.doubleInlineeCandidates.containsKey(candidate)) { - // Both calls can be inlined. - inliner.doubleInlineCallers.add(inliner.doubleInlineeCandidates.get(candidate)); - inliner.doubleInlineCallers.add(method); - inliner.doubleInlineSelectedTargets.add(candidate); - } else { - // First call can be inlined. - inliner.doubleInlineeCandidates.put(candidate, method); - } - // Just preparing for double inlining. - return null; - } else { - // Don't perform the actual inlining if this was not selected. - if (!inliner.doubleInlineSelectedTargets.contains(candidate)) { - return null; - } - } - return candidate; - } - private Reason computeInliningReason(DexEncodedMethod target) { if (target.getOptimizationInfo().forceInline()) { return Reason.FORCE; @@ -185,7 +163,7 @@ public class InliningOracle { } // Attempt to inline a candidate that is only called twice. - if ((reason == Reason.DUAL_CALLER) && (doubleInlining(target) == null)) { + if ((reason == Reason.DUAL_CALLER) && (inliner.doubleInlining(method, target) == null)) { if (info != null) { info.exclude(invoke, "target is not ready for double inlining"); } @@ -253,7 +231,7 @@ public class InliningOracle { } // Attempt to inline a candidate that is only called twice. - if ((reason == Reason.DUAL_CALLER) && (doubleInlining(candidate) == null)) { + if ((reason == Reason.DUAL_CALLER) && (inliner.doubleInlining(method, candidate) == null)) { if (info != null) { info.exclude(invoke, "target is not ready for double inlining"); } 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 af99a36ae..fe59b791b 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 @@ -38,6 +38,8 @@ import it.unimi.dsi.fastutil.ints.IntArraySet; import it.unimi.dsi.fastutil.ints.IntIterator; import it.unimi.dsi.fastutil.ints.IntSet; import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Iterator; @@ -136,7 +138,7 @@ public class LinearScanRegisterAllocator implements RegisterAllocator { private List<LiveIntervals> inactive = new LinkedList<>(); // List of intervals that no register has been allocated to sorted by first live range. private PriorityQueue<LiveIntervals> unhandled = - new PriorityQueue<>((o1, o2) -> Integer.compare(o1.getStart(), o2.getStart())); + new PriorityQueue<>(Comparator.comparingInt(LiveIntervals::getStart)); // The first register used for parallel moves. After register allocation the parallel move // temporary registers are [firstParallelMoveTemporary, maxRegisterNumber]. |