Version 1.0.4
Merge: Fix in removeSuccessorsByIndex
CL: https://r8-review.googlesource.com/c/r8/+/14940
Change-Id: I5adcee1132b483dfc260d7a8a461b9ee24cf34a2
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 507b6ae..6d20eda 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
// This field is accessed from release scripts using simple pattern matching.
// Therefore, changing this field could break our release scripts.
- public static final String LABEL = "v1.0.3";
+ public static final String LABEL = "v1.0.4";
private Version() {
}
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 d6fcd3c..e88f1a1 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
@@ -182,22 +182,24 @@
}
}
- private void swapSuccessors(int x, int y) {
- assert x != y;
+ public void swapSuccessorsByIndex(int index1, int index2) {
+ assert index1 != index2;
if (hasCatchHandlers()) {
List<Integer> targets = new ArrayList<>(catchHandlers.getAllTargets());
+ assert targets.contains(index1) == targets.contains(index2)
+ : "Swapping normal successor and catch handler";
for (int i = 0; i < targets.size(); i++) {
- if (targets.get(i) == x) {
- targets.set(i, y);
- } else if (targets.get(i) == y) {
- targets.set(i, x);
+ if (targets.get(i) == index1) {
+ targets.set(i, index2);
+ } else if (targets.get(i) == index2) {
+ targets.set(i, index1);
}
}
catchHandlers = new CatchHandlers<>(catchHandlers.getGuards(), targets);
}
- BasicBlock tmp = successors.get(x);
- successors.set(x, successors.get(y));
- successors.set(y, tmp);
+ BasicBlock tmp = successors.get(index1);
+ successors.set(index1, successors.get(index2));
+ successors.set(index2, tmp);
}
public void replaceSuccessor(BasicBlock block, BasicBlock newBlock) {
@@ -226,7 +228,7 @@
if (indexOfOldBlock == successors.size() - 1 && indexOfNewBlock != successors.size() - 2) {
// Replacing the goto target and the new block will not become the goto target.
// We perform a swap to get the new block into the goto target position.
- swapSuccessors(indexOfOldBlock - 1, indexOfNewBlock);
+ swapSuccessorsByIndex(indexOfOldBlock - 1, indexOfNewBlock);
}
} else if (exit().isIf()) {
if (indexOfNewBlock >= successors.size() - 2 && indexOfOldBlock >= successors.size() - 2) {
@@ -243,7 +245,7 @@
} else if (indexOfOldBlock >= successors.size() - 2) {
// Old is either true or fallthrough and we need to swap the new block into the right
// position to become that target.
- swapSuccessors(indexOfOldBlock - 1, indexOfNewBlock);
+ swapSuccessorsByIndex(indexOfOldBlock - 1, indexOfNewBlock);
}
} else if (exit().isSwitch()) {
// Rewrite fallthrough and case target indices.
@@ -290,16 +292,11 @@
assert false : "replaceSuccessor did not find the predecessor to replace";
}
- public void swapSuccessorsByIndex(int index1, int index2) {
- BasicBlock t = successors.get(index1);
- successors.set(index1, successors.get(index2));
- successors.set(index2, t);
- }
-
public void removeSuccessorsByIndex(List<Integer> successorsToRemove) {
if (successorsToRemove.isEmpty()) {
return;
}
+ assert ListUtils.verifyListIsOrdered(successorsToRemove);
List<BasicBlock> copy = new ArrayList<>(successors);
successors.clear();
int current = 0;
@@ -310,21 +307,36 @@
successors.addAll(copy.subList(current, copy.size()));
if (hasCatchHandlers()) {
+ List<Integer> currentTargets = catchHandlers.getAllTargets();
+ List<DexType> currentGuards = catchHandlers.getGuards();
int size = catchHandlers.size();
- List<DexType> guards = new ArrayList<>(size);
- List<Integer> targets = new ArrayList<>(size);
- current = 0;
- for (int i = 0; i < catchHandlers.getAllTargets().size(); i++) {
- if (successorsToRemove.contains(catchHandlers.getAllTargets().get(i))) {
- guards.addAll(catchHandlers.getGuards().subList(current, i));
- targets.addAll(catchHandlers.getAllTargets().subList(current, i));
- current = i + 1;
+ List<DexType> newGuards = new ArrayList<>(size);
+ List<Integer> newTargets = new ArrayList<>(size);
+
+ // Since targets represent indices in the list of successors, we
+ // need to remove targets/indices included in successorsToRemove,
+ // and decrease the rest of targets/indices to reflect removed successors.
+ outer:
+ for (int i = 0; i < currentTargets.size(); i++) {
+ int index = currentTargets.get(i);
+ int decreaseBy = 0;
+ for (int removedIndex : successorsToRemove) {
+ if (index == removedIndex) {
+ continue outer; // target was removed
+ }
+ if (index < removedIndex) {
+ break;
+ }
+ decreaseBy++;
}
+ newTargets.add(index - decreaseBy);
+ newGuards.add(currentGuards.get(i));
}
- if (guards.isEmpty()) {
+
+ if (newTargets.isEmpty()) {
catchHandlers = CatchHandlers.EMPTY_INDICES;
} else {
- catchHandlers = new CatchHandlers<>(guards, targets);
+ catchHandlers = new CatchHandlers<>(newGuards, newTargets);
}
}
}
@@ -1372,7 +1384,7 @@
ArrayDeque<BasicBlock> blocks = new ArrayDeque<>();
blocks.push(this);
- while(!blocks.isEmpty()) {
+ while (!blocks.isEmpty()) {
BasicBlock block = blocks.pop();
if (block == target) {
return true;
diff --git a/src/main/java/com/android/tools/r8/utils/ListUtils.java b/src/main/java/com/android/tools/r8/utils/ListUtils.java
index a2ea508..a9c3f98 100644
--- a/src/main/java/com/android/tools/r8/utils/ListUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ListUtils.java
@@ -18,4 +18,13 @@
}
return result;
}
+
+ public static <T extends Comparable<T>> boolean verifyListIsOrdered(List<T> list) {
+ for (int i = list.size() - 1; i > 0; i--) {
+ if (list.get(i).compareTo(list.get(i - 1)) < 0) {
+ return false;
+ }
+ }
+ return true;
+ }
}