Introduce common super type for IntSwitch and StringSwitch
Change-Id: I877916417bc992882b4ac7b17f1818aa332db61d
diff --git a/src/main/java/com/android/tools/r8/ir/code/Goto.java b/src/main/java/com/android/tools/r8/ir/code/Goto.java
index a6f906c..826c75b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Goto.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Goto.java
@@ -14,7 +14,7 @@
public class Goto extends JumpInstruction {
public Goto() {
- super(null);
+ super();
}
public Goto(BasicBlock block) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/If.java b/src/main/java/com/android/tools/r8/ir/code/If.java
index 40d3c72..539ecdd 100644
--- a/src/main/java/com/android/tools/r8/ir/code/If.java
+++ b/src/main/java/com/android/tools/r8/ir/code/If.java
@@ -70,12 +70,12 @@
private Type type;
public If(Type type, Value value) {
- super(null, value);
+ super(value);
this.type = type;
}
public If(Type type, List<Value> values) {
- super(null, values);
+ super(values);
this.type = type;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 16f9a11..9c94730 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -780,6 +780,14 @@
return null;
}
+ public boolean isSwitch() {
+ return false;
+ }
+
+ public Switch asSwitch() {
+ return null;
+ }
+
public boolean isIntSwitch() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/IntSwitch.java b/src/main/java/com/android/tools/r8/ir/code/IntSwitch.java
index 8ce8fde..8f1b7f4 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IntSwitch.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IntSwitch.java
@@ -24,17 +24,13 @@
import java.util.ArrayList;
import java.util.List;
-public class IntSwitch extends JumpInstruction {
+public class IntSwitch extends Switch {
private final int[] keys;
- private final int[] targetBlockIndices;
- private int fallthroughBlockIndex;
public IntSwitch(Value value, int[] keys, int[] targetBlockIndices, int fallthroughBlockIndex) {
- super(null, value);
+ super(value, targetBlockIndices, fallthroughBlockIndex);
this.keys = keys;
- this.targetBlockIndices = targetBlockIndices;
- this.fallthroughBlockIndex = fallthroughBlockIndex;
assert valid();
}
@@ -49,29 +45,25 @@
}
}
- private boolean valid() {
+ @Override
+ public boolean valid() {
+ assert super.valid();
assert keys.length >= 1;
assert keys.length <= Constants.U16BIT_MAX;
// Keys must be acceding, and cannot target the fallthrough.
- assert keys.length == targetBlockIndices.length;
+ assert keys.length == numberOfKeys();
for (int i = 1; i < keys.length - 1; i++) {
assert keys[i - 1] < keys[i];
- assert targetBlockIndices[i] != fallthroughBlockIndex;
}
- assert targetBlockIndices[keys.length - 1] != fallthroughBlockIndex;
return true;
}
- public Value value() {
- return inValues.get(0);
- }
-
// Number of targets if this switch is emitted as a packed switch.
- private static long numberOfTargetsIfPacked(int keys[]) {
+ private static long numberOfTargetsIfPacked(int[] keys) {
return ((long) keys[keys.length - 1]) - ((long) keys[0]) + 1;
}
- public static boolean canBePacked(InternalOutputMode mode, int keys[]) {
+ public static boolean canBePacked(InternalOutputMode mode, int[] keys) {
// The size of a switch payload is stored in an ushort in the Dex file.
return canBePacked(mode, numberOfTargetsIfPacked(keys));
}
@@ -135,7 +127,7 @@
}
// Size of the switch payload if emitted as packed in code units (bytes in CF, 16-bit in Dex).
- public static long packedPayloadSize(InternalOutputMode mode, int keys[]) {
+ public static long packedPayloadSize(InternalOutputMode mode, int[] keys) {
assert canBePacked(mode, keys);
long numberOfTargets = numberOfTargetsIfPacked(keys);
return packedPayloadSize(mode, numberOfTargets);
@@ -205,27 +197,14 @@
}
}
-
- public int numberOfKeys() {
- return keys.length;
- }
-
public int getKey(int index) {
return keys[index];
}
- public int getTargetBlockIndex(int index) {
- return targetBlockIndices[index];
- }
-
public int[] getKeys() {
return keys;
}
- public int[] targetBlockIndices() {
- return targetBlockIndices;
- }
-
public Int2ReferenceSortedMap<BasicBlock> getKeyToTargetMap() {
Int2ReferenceSortedMap<BasicBlock> result = new Int2ReferenceAVLTreeMap<>();
for (int i = 0; i < keys.length; i++) {
@@ -234,28 +213,6 @@
return result;
}
- @Override
- public BasicBlock fallthroughBlock() {
- return getBlock().getSuccessors().get(fallthroughBlockIndex);
- }
-
- public int getFallthroughBlockIndex() {
- return fallthroughBlockIndex;
- }
-
- public void setFallthroughBlockIndex(int i) {
- fallthroughBlockIndex = i;
- }
-
- public BasicBlock targetBlock(int index) {
- return getBlock().getSuccessors().get(targetBlockIndices()[index]);
- }
-
- @Override
- public void setFallthroughBlock(BasicBlock block) {
- getBlock().getMutableSuccessors().set(fallthroughBlockIndex, block);
- }
-
public Nop buildPayload(int[] targets, int fallthroughTarget, InternalOutputMode mode) {
assert keys.length == targets.length;
assert mode.isGeneratingDex();
@@ -299,23 +256,22 @@
@Override
public String toString() {
- StringBuilder builder = new StringBuilder(super.toString()+ "\n");
+ StringBuilder builder = new StringBuilder(super.toString()).append(System.lineSeparator());
for (int i = 0; i < numberOfKeys(); i++) {
- builder.append(" ");
- builder.append(getKey(i));
- builder.append(" -> ");
- builder.append(targetBlock(i).getNumberAsString());
- builder.append("\n");
+ builder
+ .append(" ")
+ .append(getKey(i))
+ .append(" -> ")
+ .append(targetBlock(i).getNumberAsString())
+ .append(System.lineSeparator());
}
- builder.append(" F -> ");
- builder.append(fallthroughBlock().getNumber());
- return builder.toString();
+ return builder.append(" F -> ").append(fallthroughBlock().getNumber()).toString();
}
@Override
public void print(CfgPrinter printer) {
super.print(printer);
- for (int index : targetBlockIndices) {
+ for (int index : targetBlockIndices()) {
BasicBlock target = getBlock().getSuccessors().get(index);
printer.append(" B").append(target.getNumber());
}
@@ -337,16 +293,16 @@
int index = 0;
for (long i = min; i <= max; i++) {
if (i == keys[index]) {
- labels.add(builder.getLabel(successors.get(targetBlockIndices[index])));
+ labels.add(builder.getLabel(successors.get(getTargetBlockIndex(index))));
index++;
} else {
labels.add(fallthroughLabel);
}
}
- assert index == targetBlockIndices.length;
- builder.add(new CfSwitch(Kind.TABLE, fallthroughLabel, new int[] { min }, labels));
+ assert index == numberOfKeys();
+ builder.add(new CfSwitch(Kind.TABLE, fallthroughLabel, new int[] {min}, labels));
} else {
- for (int index : targetBlockIndices) {
+ for (int index : targetBlockIndices()) {
labels.add(builder.getLabel(successors.get(index)));
}
builder.add(new CfSwitch(Kind.LOOKUP, fallthroughLabel, this.keys, labels));
diff --git a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
index 4fca114..cf049a4 100644
--- a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
@@ -11,16 +11,16 @@
public abstract class JumpInstruction extends Instruction {
- public JumpInstruction(Value out) {
+ public JumpInstruction() {
super(null);
}
- public JumpInstruction(Value out, Value in) {
- super(out, in);
+ public JumpInstruction(Value in) {
+ super(null, in);
}
- public JumpInstruction(Value out, List<? extends Value> ins) {
- super(out, ins);
+ public JumpInstruction(List<? extends Value> ins) {
+ super(null, ins);
}
public BasicBlock fallthroughBlock() {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Return.java b/src/main/java/com/android/tools/r8/ir/code/Return.java
index d1073bc..163b27a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Return.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Return.java
@@ -21,11 +21,11 @@
public class Return extends JumpInstruction {
public Return() {
- super(null);
+ super();
}
public Return(Value value) {
- super(null, value);
+ super(value);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/StringSwitch.java b/src/main/java/com/android/tools/r8/ir/code/StringSwitch.java
index e481ece..6538363 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StringSwitch.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StringSwitch.java
@@ -14,11 +14,9 @@
import java.util.function.BiConsumer;
import java.util.function.Consumer;
-public class StringSwitch extends JumpInstruction {
+public class StringSwitch extends Switch {
private final DexString[] keys;
- private final int[] targetBlockIndices;
- private final int fallthroughBlockIndex;
// Temporary value that will be given a register that we can use for storing a single-width value.
private final Value temporaryValue;
@@ -29,10 +27,8 @@
int[] targetBlockIndices,
int fallthroughBlockIndex,
ValueNumberGenerator valueNumberGenerator) {
- super(null, value);
+ super(value, targetBlockIndices, fallthroughBlockIndex);
this.keys = keys;
- this.targetBlockIndices = targetBlockIndices;
- this.fallthroughBlockIndex = fallthroughBlockIndex;
this.temporaryValue =
new TemporaryValue(this, valueNumberGenerator.next(), TypeLatticeElement.INT)
.setMaxRegister(Constants.U8BIT_MAX);
@@ -60,25 +56,15 @@
}
}
- private boolean valid() {
+ @Override
+ public boolean valid() {
+ assert super.valid();
assert keys.length >= 1;
assert keys.length <= Constants.U16BIT_MAX;
- assert keys.length == targetBlockIndices.length;
- for (int i = 1; i < keys.length - 1; i++) {
- assert targetBlockIndices[i] != fallthroughBlockIndex;
- }
- assert targetBlockIndices[keys.length - 1] != fallthroughBlockIndex;
+ assert keys.length == numberOfKeys();
return true;
}
- public int size() {
- return keys.length;
- }
-
- public Value value() {
- return inValues.get(0);
- }
-
@Override
public boolean isStringSwitch() {
return true;
@@ -93,24 +79,10 @@
return keys[index];
}
- public BasicBlock targetBlock(int index) {
- return getBlock().getSuccessors().get(targetBlockIndices[index]);
- }
-
- @Override
- public BasicBlock fallthroughBlock() {
- return getBlock().getSuccessors().get(fallthroughBlockIndex);
- }
-
- @Override
- public void setFallthroughBlock(BasicBlock block) {
- getBlock().getMutableSuccessors().set(fallthroughBlockIndex, block);
- }
-
@Override
public String toString() {
StringBuilder builder = new StringBuilder(super.toString()).append(System.lineSeparator());
- for (int i = 0; i < size(); i++) {
+ for (int i = 0; i < numberOfKeys(); i++) {
builder
.append(" \"")
.append(getKey(i))
diff --git a/src/main/java/com/android/tools/r8/ir/code/Switch.java b/src/main/java/com/android/tools/r8/ir/code/Switch.java
new file mode 100644
index 0000000..8dcb6a4
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/code/Switch.java
@@ -0,0 +1,80 @@
+// 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.ir.code;
+
+import java.util.function.Consumer;
+
+public abstract class Switch extends JumpInstruction {
+
+ private final int[] targetBlockIndices;
+ private int fallthroughBlockIndex;
+
+ public Switch(Value in, int[] targetBlockIndices, int fallthroughBlockIndex) {
+ super(in);
+ this.targetBlockIndices = targetBlockIndices;
+ this.fallthroughBlockIndex = fallthroughBlockIndex;
+ }
+
+ public Value value() {
+ return inValues.get(0);
+ }
+
+ public boolean valid() {
+ for (int i = 0; i < numberOfKeys(); i++) {
+ assert getTargetBlockIndex(i) != getFallthroughBlockIndex();
+ }
+ return true;
+ }
+
+ public BasicBlock targetBlock(int index) {
+ return getBlock().getSuccessors().get(targetBlockIndices()[index]);
+ }
+
+ public int getTargetBlockIndex(int index) {
+ return targetBlockIndices[index];
+ }
+
+ public int[] targetBlockIndices() {
+ return targetBlockIndices;
+ }
+
+ public void forEachTarget(Consumer<BasicBlock> fn) {
+ for (int i = 0; i < targetBlockIndices.length; i++) {
+ fn.accept(targetBlock(i));
+ }
+ }
+
+ @Override
+ public BasicBlock fallthroughBlock() {
+ return getBlock().getSuccessors().get(fallthroughBlockIndex);
+ }
+
+ public int getFallthroughBlockIndex() {
+ return fallthroughBlockIndex;
+ }
+
+ public void setFallthroughBlockIndex(int i) {
+ fallthroughBlockIndex = i;
+ }
+
+ @Override
+ public void setFallthroughBlock(BasicBlock block) {
+ getBlock().getMutableSuccessors().set(fallthroughBlockIndex, block);
+ }
+
+ public int numberOfKeys() {
+ return targetBlockIndices.length;
+ }
+
+ @Override
+ public boolean isSwitch() {
+ return true;
+ }
+
+ @Override
+ public Switch asSwitch() {
+ return this;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/Throw.java b/src/main/java/com/android/tools/r8/ir/code/Throw.java
index 6c91191..7d2a9d5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Throw.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Throw.java
@@ -17,7 +17,7 @@
public class Throw extends JumpInstruction {
public Throw(Value exception) {
- super(null, exception);
+ super(exception);
}
@Override