aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/android/tools/r8
diff options
context:
space:
mode:
authorLars Bak <bak@google.com>2017-07-14 08:12:41 +0200
committerLars Bak <bak@google.com>2017-07-14 08:12:41 +0200
commitd6868d33a233569769fda3d8e18db42281a9528e (patch)
tree155b62ad595947cf8473572792f952041ab15acd /src/main/java/com/android/tools/r8
parent787d44d2fc67d976f5f97d8c9aaa023369b8f179 (diff)
downloadr8-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')
-rw-r--r--src/main/java/com/android/tools/r8/ir/code/Value.java4
-rw-r--r--src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java14
-rw-r--r--src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java3
-rw-r--r--src/main/java/com/android/tools/r8/ir/optimize/Inliner.java46
-rw-r--r--src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java26
-rw-r--r--src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java4
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].