Merge commit 'edb9c27116bd338ec6c12064b2a5dbe8cea88308' into dev-release
diff --git a/src/main/java/com/android/tools/r8/D8Command.java b/src/main/java/com/android/tools/r8/D8Command.java
index 501d4ae..e9dbc44 100644
--- a/src/main/java/com/android/tools/r8/D8Command.java
+++ b/src/main/java/com/android/tools/r8/D8Command.java
@@ -393,7 +393,7 @@
assert !internal.debug;
internal.debug = getMode() == CompilationMode.DEBUG;
internal.programConsumer = getProgramConsumer();
- if (internal.programConsumer instanceof ClassFileConsumer) {
+ if (internal.isGeneratingClassFiles()) {
internal.cfToCfDesugar = true;
}
internal.mainDexListConsumer = getMainDexListConsumer();
diff --git a/src/main/java/com/android/tools/r8/cf/CfVersion.java b/src/main/java/com/android/tools/r8/cf/CfVersion.java
index f606b93..100656f 100644
--- a/src/main/java/com/android/tools/r8/cf/CfVersion.java
+++ b/src/main/java/com/android/tools/r8/cf/CfVersion.java
@@ -5,8 +5,8 @@
import com.android.tools.r8.utils.structural.Equatable;
import com.android.tools.r8.utils.structural.HashCodeVisitor;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import org.objectweb.asm.Opcodes;
@@ -57,7 +57,7 @@
}
@Override
- public StructuralAccept<CfVersion> getStructuralAccept() {
+ public StructuralMapping<CfVersion> getStructuralMapping() {
return CfVersion::specify;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
index 7cfcf5b..e102cf7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
@@ -52,9 +52,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
public Opcode getOpcode() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
index 44699bf..22421de 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLength.java
@@ -44,9 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
index a8d3546..c82e53e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayLoad.java
@@ -42,9 +42,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
public MemberType getType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
index fa27c39..5d64188 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArrayStore.java
@@ -44,9 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
private int getStoreType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
index b4b33b1..721f3f7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
@@ -44,9 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- type.acceptCompareTo(((CfCheckCast) other).type, visitor);
+ return type.acceptCompareTo(((CfCheckCast) other).type, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
index d1d4bb9..9572e12 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCmp.java
@@ -49,9 +49,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
public Bias getBias() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
index 7931528..863dce0 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
@@ -40,9 +40,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- type.acceptCompareTo(((CfConstClass) other).type, visitor);
+ return type.acceptCompareTo(((CfConstClass) other).type, visitor);
}
public DexType getType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
index 17c2abe..16f5e9a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodHandle.java
@@ -44,9 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- handle.acceptCompareTo(((CfConstMethodHandle) other).handle, visitor);
+ return handle.acceptCompareTo(((CfConstMethodHandle) other).handle, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
index 85f125e..5bb9849 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstMethodType.java
@@ -44,9 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- type.acceptCompareTo(((CfConstMethodType) other).type, visitor);
+ return type.acceptCompareTo(((CfConstMethodType) other).type, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
index 7575c49..185981e 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNull.java
@@ -44,9 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
index 23f3a2d..7484e80 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstNumber.java
@@ -21,6 +21,7 @@
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.structural.CompareToVisitor;
+import com.android.tools.r8.utils.structural.StructuralSpecification;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -29,6 +30,10 @@
private final long value;
private final ValueType type;
+ private static void specify(StructuralSpecification<CfConstNumber, ?> spec) {
+ spec.withLong(CfConstNumber::getRawValue).withItem(CfConstNumber::getType);
+ }
+
public CfConstNumber(long value, ValueType type) {
this.value = value;
this.type = type;
@@ -40,12 +45,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visit(
- this,
- (CfConstNumber) other,
- spec -> spec.withLong(CfConstNumber::getRawValue).withItem(CfConstNumber::getType));
+ return visitor.visit(this, (CfConstNumber) other, CfConstNumber::specify);
}
public ValueType getType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
index 827e77e..376edfe 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstString.java
@@ -36,9 +36,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- string.acceptCompareTo(other.asConstString().string, visitor);
+ return string.acceptCompareTo(other.asConstString().string, visitor);
}
public DexString getString() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
index e880a23..75c5eda 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfDexItemBasedConstString.java
@@ -43,9 +43,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visitDexReference(item, ((CfDexItemBasedConstString) other).item);
+ return visitor.visitDexReference(item, ((CfDexItemBasedConstString) other).item);
}
public DexReference getItem() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
index 978a43d..6176b49 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFieldInstruction.java
@@ -60,9 +60,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visit(this, other.asFieldInstruction(), CfFieldInstruction::specify);
+ return visitor.visit(this, other.asFieldInstruction(), CfFieldInstruction::specify);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index d89ef90..713d764 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -153,11 +153,11 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
// The frame should be determined by the code so it should for equal iff the code is equal.
// Thus we just require the frame to be in place.
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
private static class InitializedType extends FrameType {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
index 7b3ccf8..2f4a549 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfGoto.java
@@ -36,9 +36,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- helper.compareLabels(target, ((CfGoto) other).target, visitor);
+ return helper.compareLabels(target, ((CfGoto) other).target, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIf.java b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
index 6e00da7..b331673 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
@@ -44,12 +44,12 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
CfIf otherIf = (CfIf) other;
assert kind == otherIf.kind;
assert type == otherIf.type;
- helper.compareLabels(target, otherIf.target, visitor);
+ return helper.compareLabels(target, otherIf.target, visitor);
}
public ValueType getType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
index 35f9af3..45b426b 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
@@ -44,12 +44,12 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
CfIfCmp otherIf = (CfIfCmp) other;
assert kind == otherIf.kind;
assert type == otherIf.type;
- helper.compareLabels(target, otherIf.target, visitor);
+ return helper.compareLabels(target, otherIf.target, visitor);
}
public Type getKind() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
index 04a7599..933dfcd 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIinc.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.structural.CompareToVisitor;
+import com.android.tools.r8.utils.structural.StructuralSpecification;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -28,6 +29,10 @@
private final int var;
private final int increment;
+ private static void specify(StructuralSpecification<CfIinc, ?> spec) {
+ spec.withInt(CfIinc::getLocalIndex).withInt(CfIinc::getIncrement);
+ }
+
public CfIinc(int var, int increment) {
this.var = var;
this.increment = increment;
@@ -39,12 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visit(
- this,
- (CfIinc) other,
- spec -> spec.withInt(CfIinc::getLocalIndex).withInt(CfIinc::getIncrement));
+ return visitor.visit(this, (CfIinc) other, CfIinc::specify);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
index 4d311fe..815500d 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInitClass.java
@@ -49,9 +49,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- clazz.acceptCompareTo(((CfInitClass) other).clazz, visitor);
+ return clazz.acceptCompareTo(((CfInitClass) other).clazz, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
index 85d9b59..c18eb57 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstanceOf.java
@@ -43,9 +43,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- type.acceptCompareTo(other.asInstanceOf().type, visitor);
+ return type.acceptCompareTo(other.asInstanceOf().type, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
index d4986b3..e7ae429 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstruction.java
@@ -61,17 +61,16 @@
* <p>If an instruction is uniquely determined by the "compare id" then the override should simply
* call '{@code CfCompareHelper::compareIdUniquelyDeterminesEquality}'.
*/
- public abstract void internalAcceptCompareTo(
+ public abstract int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper);
- public final void acceptCompareTo(
+ public final int acceptCompareTo(
CfInstruction o, CompareToVisitor visitor, CfCompareHelper helper) {
- int diff = getCompareToId() - o.getCompareToId();
- if (diff == 0) {
- internalAcceptCompareTo(o, visitor, helper);
- } else {
- visitor.visitInt(getCompareToId(), o.getCompareToId());
+ int diff = visitor.visitInt(getCompareToId(), o.getCompareToId());
+ if (diff != 0) {
+ return diff;
}
+ return internalAcceptCompareTo(o, visitor, helper);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index 4d1af96..07b0e0c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -34,6 +34,7 @@
import com.android.tools.r8.ir.optimize.InliningConstraints;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.structural.CompareToVisitor;
+import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.Arrays;
import java.util.ListIterator;
import org.objectweb.asm.MethodVisitor;
@@ -45,6 +46,10 @@
private final int opcode;
private final boolean itf;
+ private static void specify(StructuralSpecification<CfInvoke, ?> spec) {
+ spec.withBool(CfInvoke::isInterface).withItem(CfInvoke::getMethod);
+ }
+
public CfInvoke(int opcode, DexMethod method, boolean itf) {
assert Opcodes.INVOKEVIRTUAL <= opcode && opcode <= Opcodes.INVOKEINTERFACE;
assert !(opcode == Opcodes.INVOKEVIRTUAL && itf) : "InvokeVirtual on interface type";
@@ -60,13 +65,10 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
CfInvoke otherInvoke = other.asInvoke();
- visitor.visit(
- this,
- otherInvoke,
- spec -> spec.withBool(CfInvoke::isInterface).withItem(CfInvoke::getMethod));
+ return visitor.visit(this, otherInvoke, CfInvoke::specify);
}
public DexMethod getMethod() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index fc1f3e5..e65d095 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -49,9 +49,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- callSite.acceptCompareTo(((CfInvokeDynamic) other).callSite, visitor);
+ return callSite.acceptCompareTo(((CfInvokeDynamic) other).callSite, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
index d8cd219..812a17c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfJsrRet.java
@@ -42,7 +42,7 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
throw error();
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
index dc6d863..5a3e4e7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLabel.java
@@ -39,9 +39,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- helper.compareLabels(this, other.asLabel(), visitor);
+ return helper.compareLabels(this, other.asLabel(), visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
index 4e48880..96a6d11 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLoad.java
@@ -41,9 +41,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visitInt(var, other.asLoad().var);
+ return visitor.visitInt(var, other.asLoad().var);
}
private int getLoadType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
index d6264f7..19e5dd9 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfLogicalBinop.java
@@ -54,9 +54,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
public NumericType getType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
index 520c168..3286da2 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMonitor.java
@@ -43,9 +43,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
index ff9ea71..9180511 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfMultiANewArray.java
@@ -22,6 +22,7 @@
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.structural.CompareToVisitor;
+import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.ListIterator;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -31,6 +32,10 @@
private final DexType type;
private final int dimensions;
+ private static void specify(StructuralSpecification<CfMultiANewArray, ?> spec) {
+ spec.withInt(CfMultiANewArray::getDimensions).withItem(CfMultiANewArray::getType);
+ }
+
public CfMultiANewArray(DexType type, int dimensions) {
this.type = type;
this.dimensions = dimensions;
@@ -50,12 +55,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visit(
- this,
- (CfMultiANewArray) other,
- spec -> spec.withInt(CfMultiANewArray::getDimensions).withItem(CfMultiANewArray::getType));
+ return visitor.visit(this, (CfMultiANewArray) other, CfMultiANewArray::specify);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
index dce1028..5de3787 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNeg.java
@@ -44,9 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNew.java b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
index 87a407d..7140404 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNew.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNew.java
@@ -44,9 +44,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- type.acceptCompareTo(((CfNew) other).type, visitor);
+ return type.acceptCompareTo(((CfNew) other).type, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
index 0dbf78e..bd36756 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewArray.java
@@ -47,9 +47,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- type.acceptCompareTo(((CfNewArray) other).type, visitor);
+ return type.acceptCompareTo(((CfNewArray) other).type, visitor);
}
private int getPrimitiveTypeCode() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNop.java b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
index 0a69673b..974d928 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNop.java
@@ -30,9 +30,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
index 35c78a7..dc1bc2c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNumberConversion.java
@@ -46,9 +46,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
public NumericType getFromType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
index df8612e..f524bab 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfPosition.java
@@ -27,6 +27,8 @@
private final CfLabel label;
private final Position position;
+
+
public CfPosition(CfLabel label, Position position) {
this.label = label;
this.position = position;
@@ -38,9 +40,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visit(
+ return visitor.visit(
this,
(CfPosition) other,
spec ->
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
index b09fbea..51d1283 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
@@ -43,9 +43,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
private int getOpcode() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
index c52efe3..08de455 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
@@ -35,9 +35,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
index c6c39be..bfdbe0a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStackInstruction.java
@@ -88,9 +88,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStore.java b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
index e424474..d74eb39 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStore.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStore.java
@@ -42,9 +42,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visitInt(var, other.asStore().var);
+ return visitor.visitInt(var, other.asStore().var);
}
private int getStoreType() {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
index 86abb2e..cb915ff 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfSwitch.java
@@ -51,11 +51,10 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
assert kind == ((CfSwitch) other).kind;
-
- visitor.visit(
+ return visitor.visit(
this,
(CfSwitch) other,
spec ->
@@ -156,5 +155,6 @@
for (CfLabel target : targets) {
frameBuilder.verifyTarget(target);
}
+ frameBuilder.setNoFrame();
}
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
index 7243175..aad20a8 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfThrow.java
@@ -36,9 +36,9 @@
}
@Override
- public void internalAcceptCompareTo(
+ public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfTryCatch.java b/src/main/java/com/android/tools/r8/cf/code/CfTryCatch.java
index 6cc3b13..2f821be 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfTryCatch.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfTryCatch.java
@@ -48,8 +48,8 @@
return new CfTryCatch(start, end, guards, targets);
}
- public void acceptCompareTo(CfTryCatch other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visit(
+ public int acceptCompareTo(CfTryCatch other, CompareToVisitor visitor, CfCompareHelper helper) {
+ return visitor.visit(
this,
other,
spec ->
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index c07e0f5..6f2f904 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -133,7 +133,7 @@
Log.verbose(FileWriter.class, "Writing encoded annotation @ %08x", dest.position());
}
List<DexAnnotationElement> elements = new ArrayList<>(Arrays.asList(annotation.elements));
- elements.sort((a, b) -> a.name.compareToWithNamingLens(b.name, mapping.getNamingLens()));
+ elements.sort((a, b) -> a.name.acceptCompareTo(b.name, mapping.getCompareToVisitor()));
dest.putUleb128(mapping.getOffsetFor(annotation.type));
dest.putUleb128(elements.size());
for (DexAnnotationElement element : elements) {
@@ -351,6 +351,7 @@
}
private static String getKeyForDexCodeSorting(ProgramMethod method, ClassNameMapper proguardMap) {
+ // TODO(b/173999869): Could this instead compute sorting using dex items?
Signature signature;
String originalClassName;
if (proguardMap != null) {
@@ -580,7 +581,8 @@
}
List<DexAnnotation> annotations = new ArrayList<>(Arrays.asList(set.annotations));
annotations.sort(
- (a, b) -> a.annotation.type.compareToWithNamingLens(b.annotation.type, namingLens));
+ (a, b) ->
+ a.annotation.type.acceptCompareTo(b.annotation.type, mapping.getCompareToVisitor()));
dest.putInt(annotations.size());
for (DexAnnotation annotation : annotations) {
dest.putInt(mixedSectionOffsets.getOffsetFor(annotation));
@@ -613,10 +615,11 @@
mixedSectionOffsets.setOffsetForAnnotationsDirectory(annotationDirectory, dest.align(4));
dest.putInt(mixedSectionOffsets.getOffsetFor(annotationDirectory.getClazzAnnotations()));
List<DexEncodedMethod> methodAnnotations =
- annotationDirectory.sortMethodAnnotations(namingLens);
+ annotationDirectory.sortMethodAnnotations(mapping.getCompareToVisitor());
List<DexEncodedMethod> parameterAnnotations =
- annotationDirectory.sortParameterAnnotations(namingLens);
- List<DexEncodedField> fieldAnnotations = annotationDirectory.sortFieldAnnotations(namingLens);
+ annotationDirectory.sortParameterAnnotations(mapping.getCompareToVisitor());
+ List<DexEncodedField> fieldAnnotations =
+ annotationDirectory.sortFieldAnnotations(mapping.getCompareToVisitor());
dest.putInt(fieldAnnotations.size());
dest.putInt(methodAnnotations.size());
dest.putInt(parameterAnnotations.size());
@@ -630,7 +633,7 @@
private void writeEncodedFields(List<DexEncodedField> unsortedFields) {
List<DexEncodedField> fields = new ArrayList<>(unsortedFields);
- fields.sort((a, b) -> a.field.compareToWithNamingLens(b.field, namingLens));
+ fields.sort((a, b) -> a.field.acceptCompareTo(b.field, mapping.getCompareToVisitor()));
int currentOffset = 0;
for (DexEncodedField field : fields) {
assert field.validateDexValue(application.dexItemFactory);
@@ -646,7 +649,7 @@
private void writeEncodedMethods(
Iterable<DexEncodedMethod> unsortedMethods, boolean isSharedSynthetic) {
List<DexEncodedMethod> methods = IterableUtils.toNewArrayList(unsortedMethods);
- methods.sort((a, b) -> a.method.compareToWithNamingLens(b.method, namingLens));
+ methods.sort((a, b) -> a.method.acceptCompareTo(b.method, mapping.getCompareToVisitor()));
int currentOffset = 0;
for (DexEncodedMethod method : methods) {
int nextOffset = mapping.getOffsetFor(method.method);
diff --git a/src/main/java/com/android/tools/r8/graph/AccessFlags.java b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
index 910153a..e47b428 100644
--- a/src/main/java/com/android/tools/r8/graph/AccessFlags.java
+++ b/src/main/java/com/android/tools/r8/graph/AccessFlags.java
@@ -4,8 +4,8 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.dex.Constants;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.collect.ImmutableList;
import java.util.List;
@@ -61,7 +61,7 @@
}
@Override
- public StructuralAccept<T> getStructuralAccept() {
+ public StructuralMapping<T> getStructuralMapping() {
return AccessFlags::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index 1e7ec9c..ce2d937 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -9,7 +9,6 @@
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.analysis.InitializedClassesInInstanceMethodsAnalysis.InitializedClassesInInstanceMethods;
import com.android.tools.r8.graph.classmerging.HorizontallyMergedLambdaClasses;
-import com.android.tools.r8.graph.classmerging.MergedClasses;
import com.android.tools.r8.graph.classmerging.MergedClassesCollection;
import com.android.tools.r8.graph.classmerging.StaticallyMergedClasses;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
@@ -455,12 +454,6 @@
return collection;
}
- public boolean hasBeenMerged(DexProgramClass clazz) {
- return MergedClasses.hasBeenMerged(horizontallyMergedClasses, clazz)
- || MergedClasses.hasBeenMerged(horizontallyMergedLambdaClasses, clazz)
- || MergedClasses.hasBeenMerged(verticallyMergedClasses, clazz);
- }
-
/**
* Get the result of horizontal lambda class merging. Returns null if horizontal lambda class
* merging has not been run.
@@ -636,7 +629,7 @@
boolean changed = appView.setGraphLens(lens);
assert changed;
- assert application.verifyWithLens(lens);
+ assert application.verifyWithLens(appView.appInfo().app().asDirect(), lens);
// The application has already been rewritten with the given applied lens. Therefore, we
// temporarily replace that lens with a lens that does not have any rewritings to avoid the
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 6d3cedc..2e1eeb6 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -43,8 +43,8 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.HashingVisitor;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.google.common.base.Strings;
import it.unimi.dsi.fastutil.ints.Int2IntArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
@@ -112,9 +112,9 @@
return end;
}
- public void acceptCompareTo(
+ public int acceptCompareTo(
LocalVariableInfo other, CompareToVisitor visitor, CfCompareHelper helper) {
- visitor.visit(
+ return visitor.visit(
this,
other,
spec ->
@@ -164,7 +164,7 @@
}
@Override
- public StructuralAccept<CfCode> getStructuralAccept() {
+ public StructuralMapping<CfCode> getStructuralMapping() {
throw new Unreachable();
}
@@ -254,9 +254,9 @@
}
@Override
- public void acceptCompareTo(CfCode other, CompareToVisitor visitor) {
+ public int acceptCompareTo(CfCode other, CompareToVisitor visitor) {
CfCompareHelper helper = new CfCompareHelper(this, other);
- visitor.visit(
+ return visitor.visit(
this,
other,
spec ->
@@ -695,7 +695,7 @@
public boolean verifyFrames(
DexEncodedMethod method, AppView<?> appView, Origin origin, boolean applyProtoTypeChanges) {
- if (!appView.options().testing.readInputStackMaps
+ if (!appView.options().canUseInputStackMaps()
|| appView.options().testing.disableStackMapVerification) {
stackMapStatus = StackMapStatus.INVALID_OR_NOT_PRESENT;
return true;
diff --git a/src/main/java/com/android/tools/r8/graph/CfCompareHelper.java b/src/main/java/com/android/tools/r8/graph/CfCompareHelper.java
index 0203b0c..1108c72 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCompareHelper.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCompareHelper.java
@@ -45,11 +45,12 @@
}
// Helper to signal that the concrete instruction is uniquely determined by its ID/opcode.
- public static void compareIdUniquelyDeterminesEquality(
+ public static int compareIdUniquelyDeterminesEquality(
CfInstruction instruction1, CfInstruction instruction2) {
assert instruction1.getClass() == instruction2.getClass();
assert instruction1.getCompareToId() == instruction2.getCompareToId();
assert instruction1.toString().equals(instruction2.toString());
+ return 0;
}
private static Reference2IntMap<CfLabel> getLabelOrdering(CfCode code) {
@@ -71,8 +72,8 @@
this.code2 = code2;
}
- public void compareLabels(CfLabel label1, CfLabel label2, CompareToVisitor visitor) {
- labelAcceptor().acceptCompareTo(label1, label2, visitor);
+ public int compareLabels(CfLabel label1, CfLabel label2, CompareToVisitor visitor) {
+ return labelAcceptor().acceptCompareTo(label1, label2, visitor);
}
public StructuralAcceptor<CfLabel> labelAcceptor() {
@@ -83,8 +84,8 @@
private final Reference2IntMap<CfLabel> labels2 = getLabelOrdering(code2);
@Override
- public void acceptCompareTo(CfLabel item1, CfLabel item2, CompareToVisitor visitor) {
- visitor.visitInt(labels1.getInt(item1), labels2.getInt(item2));
+ public int acceptCompareTo(CfLabel item1, CfLabel item2, CompareToVisitor visitor) {
+ return visitor.visitInt(labels1.getInt(item1), labels2.getInt(item2));
}
@Override
@@ -100,9 +101,9 @@
CfCompareHelper helper = this;
return new StructuralAcceptor<CfInstruction>() {
@Override
- public void acceptCompareTo(
+ public int acceptCompareTo(
CfInstruction item1, CfInstruction item2, CompareToVisitor visitor) {
- item1.acceptCompareTo(item2, visitor, helper);
+ return item1.acceptCompareTo(item2, visitor, helper);
}
@Override
@@ -116,8 +117,8 @@
CfCompareHelper helper = this;
return new StructuralAcceptor<CfTryCatch>() {
@Override
- public void acceptCompareTo(CfTryCatch item1, CfTryCatch item2, CompareToVisitor visitor) {
- item1.acceptCompareTo(item2, visitor, helper);
+ public int acceptCompareTo(CfTryCatch item1, CfTryCatch item2, CompareToVisitor visitor) {
+ return item1.acceptCompareTo(item2, visitor, helper);
}
@Override
@@ -131,9 +132,9 @@
CfCompareHelper helper = this;
return new StructuralAcceptor<LocalVariableInfo>() {
@Override
- public void acceptCompareTo(
+ public int acceptCompareTo(
LocalVariableInfo item1, LocalVariableInfo item2, CompareToVisitor visitor) {
- item1.acceptCompareTo(item2, visitor, helper);
+ return item1.acceptCompareTo(item2, visitor, helper);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DebugLocalInfo.java b/src/main/java/com/android/tools/r8/graph/DebugLocalInfo.java
index 56027f2..67a8eab 100644
--- a/src/main/java/com/android/tools/r8/graph/DebugLocalInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/DebugLocalInfo.java
@@ -5,8 +5,8 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.DescriptorUtils;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
@@ -45,7 +45,7 @@
}
@Override
- public StructuralAccept<DebugLocalInfo> getStructuralAccept() {
+ public StructuralMapping<DebugLocalInfo> getStructuralMapping() {
return DebugLocalInfo::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
index 5f223f8..bcb7974 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
@@ -16,8 +16,8 @@
import com.android.tools.r8.ir.desugar.CovariantReturnTypeAnnotationTransformer;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Pair;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.ArrayList;
import java.util.Collection;
@@ -35,7 +35,7 @@
public final DexEncodedAnnotation annotation;
private static void specify(StructuralSpecification<DexAnnotation, ?> spec) {
- spec.withInt(a -> a.visibility).withItem(a -> a.annotation);
+ spec.withItem(a -> a.annotation).withInt(a -> a.visibility);
}
public DexAnnotation(int visibility, DexEncodedAnnotation annotation) {
@@ -49,7 +49,7 @@
}
@Override
- public StructuralAccept<DexAnnotation> getStructuralAccept() {
+ public StructuralMapping<DexAnnotation> getStructuralMapping() {
return DexAnnotation::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
index 2ee613c..ad9bf23 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationDirectory.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
-import com.android.tools.r8.naming.NamingLens;
+import com.android.tools.r8.utils.structural.CompareToVisitor;
import java.util.ArrayList;
import java.util.List;
@@ -45,18 +45,18 @@
return clazz.annotations();
}
- public List<DexEncodedMethod> sortMethodAnnotations(NamingLens namingLens) {
- methodAnnotations.sort((a, b) -> a.method.compareToWithNamingLens(b.method, namingLens));
+ public List<DexEncodedMethod> sortMethodAnnotations(CompareToVisitor visitor) {
+ methodAnnotations.sort((a, b) -> a.method.acceptCompareTo(b.method, visitor));
return methodAnnotations;
}
- public List<DexEncodedMethod> sortParameterAnnotations(NamingLens namingLens) {
- parameterAnnotations.sort((a, b) -> a.method.compareToWithNamingLens(b.method, namingLens));
+ public List<DexEncodedMethod> sortParameterAnnotations(CompareToVisitor visitor) {
+ parameterAnnotations.sort((a, b) -> a.method.acceptCompareTo(b.method, visitor));
return parameterAnnotations;
}
- public List<DexEncodedField> sortFieldAnnotations(NamingLens namingLens) {
- fieldAnnotations.sort((a, b) -> a.field.compareToWithNamingLens(b.field, namingLens));
+ public List<DexEncodedField> sortFieldAnnotations(CompareToVisitor visitor) {
+ fieldAnnotations.sort((a, b) -> a.field.acceptCompareTo(b.field, visitor));
return fieldAnnotations;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
index fc764ff..f351642 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationElement.java
@@ -5,8 +5,8 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
public class DexAnnotationElement extends DexItem implements StructuralItem<DexAnnotationElement> {
@@ -30,7 +30,7 @@
}
@Override
- public StructuralAccept<DexAnnotationElement> getStructuralAccept() {
+ public StructuralMapping<DexAnnotationElement> getStructuralMapping() {
return DexAnnotationElement::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
index 86188d6..e1a64b1 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotationSet.java
@@ -9,8 +9,8 @@
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.ArrayUtils;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.collect.Sets;
import java.util.Arrays;
@@ -47,7 +47,7 @@
}
@Override
- public StructuralAccept<DexAnnotationSet> getStructuralAccept() {
+ public StructuralMapping<DexAnnotationSet> getStructuralMapping() {
return DexAnnotationSet::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index 5d521bc..9cb4704 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -10,8 +10,8 @@
import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
import com.android.tools.r8.graph.DexValue.DexValueMethodType;
import com.android.tools.r8.graph.DexValue.DexValueString;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.io.BaseEncoding;
import java.io.ByteArrayOutputStream;
@@ -108,7 +108,7 @@
}
@Override
- public StructuralAccept<DexCallSite> getStructuralAccept() {
+ public StructuralMapping<DexCallSite> getStructuralMapping() {
return DexCallSite::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDefinition.java b/src/main/java/com/android/tools/r8/graph/DexDefinition.java
index 0153cd2..c3e6998 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDefinition.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDefinition.java
@@ -104,4 +104,16 @@
public abstract boolean isStatic();
public abstract boolean isStaticMember();
+
+ public boolean isNotProgramDefinition(AppView<?> appView) {
+ if (isDexClass()) {
+ return asDexClass().isNotProgramClass();
+ }
+ DexClass clazz = appView.definitionFor(asDexEncodedMember().getHolderType());
+ return clazz == null || clazz.isNotProgramClass();
+ }
+
+ public DexType getContextType() {
+ return isDexClass() ? asDexClass().type : asDexEncodedMember().getHolderType();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexEncodedAnnotation.java
index bcefcd2..98df8c7 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedAnnotation.java
@@ -6,8 +6,8 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.utils.ArrayUtils;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.Arrays;
import java.util.function.Consumer;
@@ -37,7 +37,7 @@
}
@Override
- public StructuralAccept<DexEncodedAnnotation> getStructuralAccept() {
+ public StructuralMapping<DexEncodedAnnotation> getStructuralMapping() {
return DexEncodedAnnotation::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
index 133ebe5..6839371 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedField.java
@@ -20,8 +20,8 @@
import com.android.tools.r8.ir.optimize.info.MutableFieldOptimizationInfo;
import com.android.tools.r8.kotlin.KotlinFieldLevelInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
public class DexEncodedField extends DexEncodedMember<DexEncodedField, DexField>
@@ -75,7 +75,7 @@
}
@Override
- public StructuralAccept<DexEncodedField> getStructuralAccept() {
+ public StructuralMapping<DexEncodedField> getStructuralMapping() {
return DexEncodedField::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 6fbb596..7d807e9 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -358,18 +358,15 @@
this, other, map, DexEncodedMethod::syntheticSpecify);
}
- private static void compareCodeObject(Code code1, Code code2, CompareToVisitor visitor) {
+ private static int compareCodeObject(Code code1, Code code2, CompareToVisitor visitor) {
if (code1.isCfCode() && code2.isCfCode()) {
- code1.asCfCode().acceptCompareTo(code2.asCfCode(), visitor);
- } else if (code1.isDexCode() && code2.isDexCode()) {
- visitor.visit(code1.asDexCode(), code2.asDexCode(), DexCode::compareTo);
- } else {
- throw new Unreachable(
- "Unexpected attempt to compare incompatible synthetic objects: "
- + code1
- + " and "
- + code2);
+ return code1.asCfCode().acceptCompareTo(code2.asCfCode(), visitor);
}
+ if (code1.isDexCode() && code2.isDexCode()) {
+ return visitor.visit(code1.asDexCode(), code2.asDexCode(), DexCode::compareTo);
+ }
+ throw new Unreachable(
+ "Unexpected attempt to compare incompatible synthetic objects: " + code1 + " and " + code2);
}
private static void hashCodeObject(Code code, HashingVisitor visitor) {
@@ -846,6 +843,12 @@
classFileVersion = Ordered.maxIgnoreNull(classFileVersion, version);
}
+ public void downgradeClassFileVersion(CfVersion version) {
+ checkIfObsolete();
+ assert version != null;
+ classFileVersion = Ordered.minIgnoreNull(classFileVersion, version);
+ }
+
public String qualifiedName() {
checkIfObsolete();
return method.qualifiedName();
diff --git a/src/main/java/com/android/tools/r8/graph/DexField.java b/src/main/java/com/android/tools/r8/graph/DexField.java
index dbb2d08..70bb89b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexField.java
+++ b/src/main/java/com/android/tools/r8/graph/DexField.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.structural.CompareToVisitor;
-import com.android.tools.r8.utils.structural.StructuralAccept;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.Collections;
import java.util.function.BiConsumer;
@@ -28,7 +28,7 @@
}
}
- private static void accept(StructuralSpecification<DexField, ?> spec) {
+ private static void specify(StructuralSpecification<DexField, ?> spec) {
spec.withItem(DexField::getHolderType).withItem(DexField::getName).withItem(DexField::getType);
}
@@ -38,8 +38,8 @@
}
@Override
- public StructuralAccept<DexField> getStructuralAccept() {
- return DexField::accept;
+ public StructuralMapping<DexField> getStructuralMapping() {
+ return DexField::specify;
}
public DexType getType() {
@@ -134,8 +134,8 @@
}
@Override
- public void acceptCompareTo(DexField other, CompareToVisitor visitor) {
- visitor.visitDexField(this, other);
+ public int acceptCompareTo(DexField other, CompareToVisitor visitor) {
+ return visitor.visitDexField(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethod.java b/src/main/java/com/android/tools/r8/graph/DexMethod.java
index 97f9b6d..c91ffdf 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethod.java
@@ -9,7 +9,7 @@
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.utils.structural.CompareToVisitor;
-import com.android.tools.r8.utils.structural.StructuralAccept;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.ArrayList;
import java.util.List;
@@ -31,13 +31,13 @@
}
}
- private static void accept(StructuralSpecification<DexMethod, ?> spec) {
+ private static void specify(StructuralSpecification<DexMethod, ?> spec) {
spec.withItem(DexMethod::getHolderType).withItem(DexMethod::getName).withItem(m -> m.proto);
}
@Override
- public StructuralAccept<DexMethod> getStructuralAccept() {
- return DexMethod::accept;
+ public StructuralMapping<DexMethod> getStructuralMapping() {
+ return DexMethod::specify;
}
@Override
@@ -46,8 +46,8 @@
}
@Override
- public void acceptCompareTo(DexMethod other, CompareToVisitor visitor) {
- visitor.visitDexMethod(this, other);
+ public int acceptCompareTo(DexMethod other, CompareToVisitor visitor) {
+ return visitor.visitDexMethod(this, other);
}
public DexType getParameter(int index) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
index 5ee9c8f..b369871 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.utils.structural.StructuralAccept;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.Objects;
import org.objectweb.asm.Handle;
@@ -320,7 +320,7 @@
}
@Override
- public StructuralAccept<DexMethodHandle> getStructuralAccept() {
+ public StructuralMapping<DexMethodHandle> getStructuralMapping() {
return DexMethodHandle::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index ee32f8a..3e92e74 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.TraversalContinuation;
+import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
@@ -669,12 +670,16 @@
this.initialClassFileVersion = initialClassFileVersion;
}
+ public void downgradeInitialClassFileVersion(CfVersion version) {
+ assert version != null;
+ this.initialClassFileVersion = Ordered.minIgnoreNull(this.initialClassFileVersion, version);
+ }
+
public boolean hasClassFileVersion() {
return initialClassFileVersion != null;
}
public CfVersion getInitialClassFileVersion() {
- assert initialClassFileVersion != null;
return initialClassFileVersion;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexProto.java b/src/main/java/com/android/tools/r8/graph/DexProto.java
index 3855408..36ad355 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProto.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProto.java
@@ -5,7 +5,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.naming.NamingLens;
-import com.android.tools.r8.utils.structural.StructuralAccept;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.collect.Iterables;
import java.util.Collections;
@@ -25,7 +25,7 @@
this.parameters = parameters;
}
- private static void accept(StructuralSpecification<DexProto, ?> spec) {
+ private static void specify(StructuralSpecification<DexProto, ?> spec) {
spec.withItem(DexProto::getReturnType)
.withItem(p -> p.parameters)
// TODO(b/172206529): Consider removing shorty.
@@ -33,8 +33,8 @@
}
@Override
- public StructuralAccept<DexProto> getStructuralAccept() {
- return DexProto::accept;
+ public StructuralMapping<DexProto> getStructuralMapping() {
+ return DexProto::specify;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexString.java b/src/main/java/com/android/tools/r8/graph/DexString.java
index 264a7aa..031ee9d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexString.java
+++ b/src/main/java/com/android/tools/r8/graph/DexString.java
@@ -12,7 +12,7 @@
import com.android.tools.r8.utils.ThrowingCharIterator;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.HashingVisitor;
-import com.android.tools.r8.utils.structural.StructuralAccept;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import java.io.UTFDataFormatException;
import java.util.Arrays;
import java.util.NoSuchElementException;
@@ -41,7 +41,7 @@
}
@Override
- public StructuralAccept<DexString> getStructuralAccept() {
+ public StructuralMapping<DexString> getStructuralMapping() {
// Structural accept is never accessed as all accept methods are defined directly.
throw new Unreachable();
}
@@ -53,8 +53,8 @@
}
@Override
- public void acceptCompareTo(DexString other, CompareToVisitor visitor) {
- visitor.visitDexString(this, other);
+ public int acceptCompareTo(DexString other, CompareToVisitor visitor) {
+ return visitor.visitDexString(this, other);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index 0b13d80..249439c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -26,7 +26,7 @@
import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.HashingVisitor;
-import com.android.tools.r8.utils.structural.StructuralAccept;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.google.common.collect.ImmutableList;
import java.util.Arrays;
import java.util.List;
@@ -58,15 +58,15 @@
}
@Override
- public StructuralAccept<DexType> getStructuralAccept() {
+ public StructuralMapping<DexType> getStructuralMapping() {
// Structural accept is never accessed as all accept methods are defined directly.
throw new Unreachable();
}
// DexType overrides accept to ensure the visitors always gets a visitDexType callback.
@Override
- public void acceptCompareTo(DexType other, CompareToVisitor visitor) {
- visitor.visitDexType(this, other);
+ public int acceptCompareTo(DexType other, CompareToVisitor visitor) {
+ return visitor.visitDexType(this, other);
}
// DexType overrides accept to ensure the visitors always gets a visitDexType callback.
diff --git a/src/main/java/com/android/tools/r8/graph/DexTypeList.java b/src/main/java/com/android/tools/r8/graph/DexTypeList.java
index 595c5dd..076322a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexTypeList.java
+++ b/src/main/java/com/android/tools/r8/graph/DexTypeList.java
@@ -8,8 +8,8 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.utils.ArrayUtils;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.collect.Iterators;
import java.util.Arrays;
@@ -72,7 +72,7 @@
}
@Override
- public StructuralAccept<DexTypeList> getStructuralAccept() {
+ public StructuralMapping<DexTypeList> getStructuralMapping() {
return DexTypeList::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexValue.java b/src/main/java/com/android/tools/r8/graph/DexValue.java
index a54daf8..97d304b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexValue.java
+++ b/src/main/java/com/android/tools/r8/graph/DexValue.java
@@ -25,8 +25,8 @@
import com.android.tools.r8.utils.EncodedValueUtils;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.HashingVisitor;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import java.util.Arrays;
import java.util.function.Consumer;
import org.objectweb.asm.Handle;
@@ -114,7 +114,7 @@
}
@Override
- public final StructuralAccept<DexValue> getStructuralAccept() {
+ public final StructuralMapping<DexValue> getStructuralMapping() {
// DexValue is not generic at its base type (and can't as we use it as a polymorphic value),
// so each concrete value must implement polymorphic accept functions. This base class
// implements (most of) the polymorphic checks and concrete types implement the internal
@@ -123,12 +123,12 @@
}
@Override
- public final void acceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ public final int acceptCompareTo(DexValue other, CompareToVisitor visitor) {
// Order first on 'kind', only equal kinds then forward to the 'kind' specific internal compare.
if (getValueKind() != other.getValueKind()) {
- visitor.visitInt(getValueKind().toByte(), other.getValueKind().toByte());
+ return visitor.visitInt(getValueKind().toByte(), other.getValueKind().toByte());
} else {
- internalAcceptCompareTo(other, visitor);
+ return internalAcceptCompareTo(other, visitor);
}
}
@@ -139,7 +139,7 @@
internalAcceptHashing(visitor);
}
- abstract void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor);
+ abstract int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor);
abstract void internalAcceptHashing(HashingVisitor visitor);
@@ -478,8 +478,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitInt(value, other.asDexValueByte().value);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitInt(value, other.asDexValueByte().value);
}
@Override
@@ -576,8 +576,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitInt(value, other.asDexValueShort().getValue());
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitInt(value, other.asDexValueShort().getValue());
}
public short getValue() {
@@ -663,8 +663,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitInt(value, other.asDexValueChar().value);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitInt(value, other.asDexValueChar().value);
}
@Override
@@ -764,8 +764,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitInt(value, other.asDexValueInt().value);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitInt(value, other.asDexValueInt().value);
}
public int getValue() {
@@ -851,8 +851,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitLong(value, other.asDexValueLong().value);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitLong(value, other.asDexValueLong().value);
}
@Override
@@ -948,8 +948,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitFloat(value, other.asDexValueFloat().value);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitFloat(value, other.asDexValueFloat().value);
}
public float getValue() {
@@ -1041,8 +1041,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitDouble(value, other.asDexValueDouble().value);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitDouble(value, other.asDexValueDouble().value);
}
@Override
@@ -1201,10 +1201,12 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- if (DexItemBasedValueString.compareAndCheckValueStrings(this, other, visitor)) {
- value.acceptCompareTo(other.asDexValueString().value, visitor);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ int order = DexItemBasedValueString.compareAndCheckValueStrings(this, other, visitor);
+ if (order != 0) {
+ return order;
}
+ return value.acceptCompareTo(other.asDexValueString().value, visitor);
}
@Override
@@ -1266,16 +1268,12 @@
// Helper to ensure a consistent order on DexValueString and DexItemBasedValueString which are
// both defined to have kind 'string'.
- static boolean compareAndCheckValueStrings(DexValue v1, DexValue v2, CompareToVisitor visitor) {
+ static int compareAndCheckValueStrings(DexValue v1, DexValue v2, CompareToVisitor visitor) {
assert v1.getValueKind() == DexValueKind.STRING;
assert v2.getValueKind() == DexValueKind.STRING;
int order1 = v1.isDexItemBasedValueString() ? 1 : 0;
int order2 = v2.isDexItemBasedValueString() ? 1 : 0;
- boolean equal = order1 == order2;
- if (!equal) {
- visitor.visitInt(order1, order2);
- }
- return equal;
+ return visitor.visitInt(order1, order2);
}
private final NameComputationInfo<?> nameComputationInfo;
@@ -1291,10 +1289,12 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- if (compareAndCheckValueStrings(this, other, visitor)) {
- visitor.visitDexReference(value, other.asDexItemBasedValueString().value);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ int order = compareAndCheckValueStrings(this, other, visitor);
+ if (order != 0) {
+ return order;
}
+ return visitor.visitDexReference(value, other.asDexItemBasedValueString().value);
}
@Override
@@ -1368,8 +1368,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- value.acceptCompareTo(other.asDexValueType().value, visitor);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return value.acceptCompareTo(other.asDexValueType().value, visitor);
}
@Override
@@ -1410,8 +1410,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- value.acceptCompareTo(other.asDexValueField().value, visitor);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return value.acceptCompareTo(other.asDexValueField().value, visitor);
}
@Override
@@ -1452,8 +1452,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- value.acceptCompareTo(other.asDexValueMethod().value, visitor);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return value.acceptCompareTo(other.asDexValueMethod().value, visitor);
}
@Override
@@ -1494,8 +1494,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- value.acceptCompareTo(other.asDexValueEnum().value, visitor);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return value.acceptCompareTo(other.asDexValueEnum().value, visitor);
}
@Override
@@ -1536,8 +1536,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- value.acceptCompareTo(other.asDexValueMethodType().value, visitor);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return value.acceptCompareTo(other.asDexValueMethodType().value, visitor);
}
@Override
@@ -1580,8 +1580,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitItemArray(values, other.asDexValueArray().values);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitItemArray(values, other.asDexValueArray().values);
}
@Override
@@ -1689,8 +1689,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- value.acceptCompareTo(other.asDexValueAnnotation().value, visitor);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return value.acceptCompareTo(other.asDexValueAnnotation().value, visitor);
}
@Override
@@ -1790,9 +1790,10 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
assert this == NULL;
assert other == NULL;
+ return 0;
}
public Object getValue() {
@@ -1882,8 +1883,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- visitor.visitBool(value, other.asDexValueBoolean().value);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return visitor.visitBool(value, other.asDexValueBoolean().value);
}
@Override
@@ -1967,8 +1968,8 @@
}
@Override
- void internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
- value.acceptCompareTo(other.asDexValueMethodHandle().value, visitor);
+ int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
+ return value.acceptCompareTo(other.asDexValueMethodHandle().value, visitor);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
index 54d6795..5a7d18f 100644
--- a/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
+++ b/src/main/java/com/android/tools/r8/graph/DirectMappedDexApplication.java
@@ -108,8 +108,8 @@
return "DexApplication (direct)";
}
- public boolean verifyWithLens(GraphLens lens) {
- assert mappingIsValid(lens, allClasses.keySet());
+ public boolean verifyWithLens(DirectMappedDexApplication beforeLensApplication, GraphLens lens) {
+ assert mappingIsValid(beforeLensApplication.programClasses(), lens);
assert verifyCodeObjectsOwners();
return true;
}
@@ -119,18 +119,22 @@
.allMatch(
type ->
lens.lookupType(type) == type
- || MergedClasses.hasBeenMerged(appView.verticallyMergedClasses(), type)
- || MergedClasses.hasBeenMerged(appView.horizontallyMergedClasses(), type));
+ || MergedClasses.hasBeenMergedIntoDifferentType(
+ appView.verticallyMergedClasses(), type)
+ || MergedClasses.hasBeenMergedIntoDifferentType(
+ appView.horizontallyMergedClasses(), type));
assert verifyCodeObjectsOwners();
return true;
}
- private boolean mappingIsValid(GraphLens graphLens, Iterable<DexType> types) {
+ private boolean mappingIsValid(
+ List<DexProgramClass> classesBeforeLensApplication, GraphLens lens) {
// The lens might either map to a different type that is already present in the application
// (e.g. relinking a type) or it might encode a type that was renamed, in which case the
// original type will point to a definition that was renamed.
- for (DexType type : types) {
- DexType renamed = graphLens.lookupType(type);
+ for (DexProgramClass clazz : classesBeforeLensApplication) {
+ DexType type = clazz.getType();
+ DexType renamed = lens.lookupType(type);
if (renamed.isIntType()) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
index cdafe4e..6a70cdd 100644
--- a/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/LazyCfCode.java
@@ -998,7 +998,7 @@
JarApplicationReader application, boolean reachabilitySensitive) {
// TODO(b/166841731): We should compute our own from the compressed format.
int parsingOptions =
- application.options.testing.readInputStackMaps
+ application.options.canUseInputStackMaps()
? ClassReader.EXPAND_FRAMES
: ClassReader.SKIP_FRAMES;
ProguardConfiguration configuration = application.options.getProguardConfiguration();
diff --git a/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java b/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
index 61d9439..f315247 100644
--- a/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
+++ b/src/main/java/com/android/tools/r8/graph/ObjectToOffsetMapping.java
@@ -8,8 +8,10 @@
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.CompareToVisitorWithStringTable;
import com.android.tools.r8.utils.structural.CompareToVisitorWithTypeTable;
+import com.android.tools.r8.utils.structural.StructuralItem;
import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap.Entry;
@@ -20,7 +22,6 @@
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
-import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
public class ObjectToOffsetMapping {
@@ -45,6 +46,8 @@
private DexString firstJumboString;
+ private final CompareToVisitor compareToVisitor;
+
public ObjectToOffsetMapping(
AppView<?> appView,
GraphLens graphLens,
@@ -76,40 +79,56 @@
this.lensCodeRewriter = new LensCodeRewriterUtils(appView);
timing.begin("Sort strings");
this.strings = createSortedMap(strings, DexString::compareTo, this::setFirstJumboString);
+ CompareToVisitor visitor =
+ new CompareToVisitorWithStringTable(namingLens, this.strings::getInt);
timing.end();
timing.begin("Sort types");
- this.types = createSortedMap(types, compareWithStringTable(), this::failOnOverflow);
+ this.types = createSortedMap(types, compare(visitor), this::failOnOverflow);
+ visitor =
+ new CompareToVisitorWithTypeTable(namingLens, this.strings::getInt, this.types::getInt);
timing.end();
timing.begin("Sort classes");
this.classes = sortClasses(appView.appInfo(), classes, namingLens);
timing.end();
timing.begin("Sort protos");
- this.protos = createSortedMap(protos, compareWithTypeTable(), this::failOnOverflow);
+ this.protos = createSortedMap(protos, compare(visitor), this::failOnOverflow);
timing.end();
timing.begin("Sort methods");
- this.methods = createSortedMap(methods, compareWithTypeTable(), this::failOnOverflow);
+ this.methods = createSortedMap(methods, compare(visitor), this::failOnOverflow);
timing.end();
timing.begin("Sort fields");
- this.fields = createSortedMap(fields, compareWithTypeTable(), this::failOnOverflow);
+ this.fields = createSortedMap(fields, compare(visitor), this::failOnOverflow);
timing.end();
timing.begin("Sort call-sites");
- this.callSites = createSortedMap(callSites, DexCallSite::compareTo, this::failOnOverflow);
+ this.callSites = createSortedMap(callSites, compare(visitor), this::failOnOverflow);
timing.end();
timing.begin("Sort method handles");
- this.methodHandles =
- createSortedMap(methodHandles, compareWithTypeTable(), this::failOnOverflow);
+ this.methodHandles = createSortedMap(methodHandles, compare(visitor), this::failOnOverflow);
timing.end();
+
+ ObjectToOffsetMapping mapping = this;
+ compareToVisitor =
+ new CompareToVisitorWithTypeTable(namingLens, this.strings::getInt, this.types::getInt) {
+
+ @Override
+ public int visitDexField(DexField field1, DexField field2) {
+ return Integer.compare(mapping.fields.getInt(field1), mapping.fields.getInt(field2));
+ }
+
+ @Override
+ public int visitDexMethod(DexMethod method1, DexMethod method2) {
+ return Integer.compare(
+ mapping.methods.getInt(method1), mapping.methods.getInt(method2));
+ }
+ };
}
- private <T extends NamingLensComparable<T>> Comparator<T> compareWithStringTable() {
- return (a, b) ->
- CompareToVisitorWithStringTable.run(
- a, b, namingLens, (ToIntFunction<DexString>) strings::getInt);
+ public CompareToVisitor getCompareToVisitor() {
+ return compareToVisitor;
}
- private <T extends NamingLensComparable<T>> Comparator<T> compareWithTypeTable() {
- return (a, b) ->
- CompareToVisitorWithTypeTable.run(a, b, namingLens, strings::getInt, types::getInt);
+ private <T extends StructuralItem<T>> Comparator<T> compare(CompareToVisitor visitor) {
+ return (a, b) -> a.acceptCompareTo(b, visitor);
}
private void setFirstJumboString(DexString string) {
diff --git a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
index fb642d6..7628702 100644
--- a/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
+++ b/src/main/java/com/android/tools/r8/graph/ParameterAnnotationsList.java
@@ -6,8 +6,8 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.utils.ArrayUtils;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.Arrays;
import java.util.function.Consumer;
@@ -76,7 +76,7 @@
}
@Override
- public StructuralAccept<ParameterAnnotationsList> getStructuralAccept() {
+ public StructuralMapping<ParameterAnnotationsList> getStructuralMapping() {
return ParameterAnnotationsList::specify;
}
diff --git a/src/main/java/com/android/tools/r8/graph/classmerging/HorizontallyMergedLambdaClasses.java b/src/main/java/com/android/tools/r8/graph/classmerging/HorizontallyMergedLambdaClasses.java
index d0948bf..0b5bc41 100644
--- a/src/main/java/com/android/tools/r8/graph/classmerging/HorizontallyMergedLambdaClasses.java
+++ b/src/main/java/com/android/tools/r8/graph/classmerging/HorizontallyMergedLambdaClasses.java
@@ -33,7 +33,7 @@
}
@Override
- public boolean hasBeenMerged(DexType type) {
+ public boolean hasBeenMergedIntoDifferentType(DexType type) {
return mergedClasses.containsKey(type);
}
diff --git a/src/main/java/com/android/tools/r8/graph/classmerging/MergedClasses.java b/src/main/java/com/android/tools/r8/graph/classmerging/MergedClasses.java
index 8fa6995..25879f1 100644
--- a/src/main/java/com/android/tools/r8/graph/classmerging/MergedClasses.java
+++ b/src/main/java/com/android/tools/r8/graph/classmerging/MergedClasses.java
@@ -15,7 +15,7 @@
void forEachMergeGroup(BiConsumer<Set<DexType>, DexType> consumer);
- boolean hasBeenMerged(DexType type);
+ boolean hasBeenMergedIntoDifferentType(DexType type);
boolean verifyAllSourcesPruned(AppView<AppInfoWithLiveness> appView);
@@ -23,17 +23,18 @@
* Determine if the class has been merged by the merged classes object. If the merged classes is
* null then return false.
*/
- static boolean hasBeenMerged(MergedClasses mergedClasses, DexProgramClass clazz) {
- return hasBeenMerged(mergedClasses, clazz.type);
+ static boolean hasBeenMergedIntoDifferentType(
+ MergedClasses mergedClasses, DexProgramClass clazz) {
+ return hasBeenMergedIntoDifferentType(mergedClasses, clazz.getType());
}
/**
* Determine if the class has been merged by the merged classes object. If the merged classes is
* null then return false.
*/
- static boolean hasBeenMerged(MergedClasses mergedClasses, DexType type) {
+ static boolean hasBeenMergedIntoDifferentType(MergedClasses mergedClasses, DexType type) {
if (mergedClasses != null) {
- return mergedClasses.hasBeenMerged(type);
+ return mergedClasses.hasBeenMergedIntoDifferentType(type);
}
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/classmerging/MergedClassesCollection.java b/src/main/java/com/android/tools/r8/graph/classmerging/MergedClassesCollection.java
index 1225127..5875506 100644
--- a/src/main/java/com/android/tools/r8/graph/classmerging/MergedClassesCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/classmerging/MergedClassesCollection.java
@@ -28,9 +28,9 @@
}
@Override
- public boolean hasBeenMerged(DexType type) {
+ public boolean hasBeenMergedIntoDifferentType(DexType type) {
for (MergedClasses mergedClasses : collection) {
- if (mergedClasses.hasBeenMerged(type)) {
+ if (mergedClasses.hasBeenMergedIntoDifferentType(type)) {
return true;
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/classmerging/StaticallyMergedClasses.java b/src/main/java/com/android/tools/r8/graph/classmerging/StaticallyMergedClasses.java
index 7046e80..79e4ef7 100644
--- a/src/main/java/com/android/tools/r8/graph/classmerging/StaticallyMergedClasses.java
+++ b/src/main/java/com/android/tools/r8/graph/classmerging/StaticallyMergedClasses.java
@@ -34,7 +34,7 @@
}
@Override
- public boolean hasBeenMerged(DexType type) {
+ public boolean hasBeenMergedIntoDifferentType(DexType type) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/classmerging/VerticallyMergedClasses.java b/src/main/java/com/android/tools/r8/graph/classmerging/VerticallyMergedClasses.java
index 4b25311..6ba32e9 100644
--- a/src/main/java/com/android/tools/r8/graph/classmerging/VerticallyMergedClasses.java
+++ b/src/main/java/com/android/tools/r8/graph/classmerging/VerticallyMergedClasses.java
@@ -60,7 +60,7 @@
}
@Override
- public boolean hasBeenMerged(DexType type) {
+ public boolean hasBeenMergedIntoDifferentType(DexType type) {
return hasBeenMergedIntoSubtype(type);
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
index 76ab41a..4d6d93f 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontallyMergedClasses.java
@@ -42,21 +42,17 @@
return mergedClasses.getKeys(type);
}
+ @Override
public boolean hasBeenMergedIntoDifferentType(DexType type) {
return mergedClasses.hasKey(type);
}
- @Override
- public boolean hasBeenMerged(DexType type) {
- return hasBeenMergedIntoDifferentType(type);
- }
-
public boolean isMergeTarget(DexType type) {
return mergedClasses.hasValue(type);
}
public boolean hasBeenMergedOrIsMergeTarget(DexType type) {
- return hasBeenMerged(type) || isMergeTarget(type);
+ return this.hasBeenMergedIntoDifferentType(type) || isMergeTarget(type);
}
Map<DexType, DexType> getForwardMap() {
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontInlinePolicy.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontInlinePolicy.java
index 0fb2284..9612f98 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontInlinePolicy.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/DontInlinePolicy.java
@@ -29,6 +29,10 @@
private boolean disallowInlining(ProgramMethod method) {
Code code = method.getDefinition().getCode();
+ if (appView.appInfo().isNeverInlineMethod(method.getReference())) {
+ return true;
+ }
+
// For non-jar/cf code we currently cannot guarantee that markForceInline() will succeed.
if (code == null || !code.isCfCode()) {
return true;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
index fd8dbf7..8e52af1 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.DominatorTree;
@@ -85,6 +86,10 @@
return null;
}
+ StaticFieldValueAnalysis asStaticFieldValueAnalysis() {
+ return null;
+ }
+
abstract boolean isSubjectToOptimization(DexEncodedField field);
void recordFieldPut(DexEncodedField field, Instruction instruction) {
@@ -148,6 +153,16 @@
boolean priorReadsWillReadSameValue =
!classInitializerDefaultsResult.hasStaticValue(field) && fieldPut.value().isZero();
if (!priorReadsWillReadSameValue && fieldMaybeReadBeforeInstruction(field, fieldPut)) {
+ if (!isInstanceFieldValueAnalysis()) {
+ // At this point the value read in the field can be only the default static value, if read
+ // prior to the put, or the value put, if read after the put. We still want to record it
+ // because the default static value is typically null/0, so code present after a null/0
+ // check can take advantage of the optimization.
+ DexValue valueBeforePut = classInitializerDefaultsResult.getStaticValue(field);
+ asStaticFieldValueAnalysis()
+ .updateFieldOptimizationInfoWith2Values(
+ field, fieldPut, fieldPut.value(), valueBeforePut);
+ }
continue;
}
updateFieldOptimizationInfo(field, fieldPut, fieldPut.value());
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
index 443ac30..cc607ac 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/InstanceFieldValueAnalysis.java
@@ -149,8 +149,8 @@
.getOptimizationInfo()
.getInstanceInitializerInfo(invoke)
.fieldInitializationInfos();
- for (DexEncodedField field : singleTarget.getHolder().instanceFields()) {
- assert isSubjectToOptimization(field);
+ for (DexEncodedField field :
+ singleTarget.getHolder().getDirectAndIndirectInstanceFields(appView)) {
InstanceFieldInitializationInfo info = infos.get(field);
if (info.isArgumentInitializationInfo()) {
int argumentIndex = info.asArgumentInitializationInfo().getArgumentIndex();
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
index 9be6c55..3ab1305 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -9,16 +9,20 @@
import static com.android.tools.r8.ir.code.Opcodes.STATIC_PUT;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.graph.DexValue.DexValueNull;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
import com.android.tools.r8.ir.analysis.value.EnumValuesObjectState;
+import com.android.tools.r8.ir.analysis.value.NullOrAbstractValue;
import com.android.tools.r8.ir.analysis.value.ObjectState;
import com.android.tools.r8.ir.analysis.value.SingleFieldValue;
import com.android.tools.r8.ir.code.ArrayPut;
@@ -59,6 +63,11 @@
}
@Override
+ StaticFieldValueAnalysis asStaticFieldValueAnalysis() {
+ return this;
+ }
+
+ @Override
void computeFieldOptimizationInfo(ClassInitializerDefaultsResult classInitializerDefaultsResult) {
super.computeFieldOptimizationInfo(classInitializerDefaultsResult);
@@ -98,19 +107,21 @@
@Override
void updateFieldOptimizationInfo(DexEncodedField field, FieldInstruction fieldPut, Value value) {
// Abstract value.
- Value root = value.getAliasedValue();
- AbstractValue abstractValue = root.getAbstractValue(appView, context);
- if (abstractValue.isUnknown()) {
- feedback.recordFieldHasAbstractValue(field, appView, computeSingleFieldValue(field, root));
- } else {
- feedback.recordFieldHasAbstractValue(field, appView, abstractValue);
- }
+ feedback.recordFieldHasAbstractValue(field, appView, getOrComputeAbstractValue(value, field));
+ setDynamicType(field, value, false);
+ }
+
+ private void setDynamicType(DexEncodedField field, Value value, boolean maybeNull) {
// Dynamic upper bound type.
TypeElement fieldType =
TypeElement.fromDexType(field.field.type, Nullability.maybeNull(), appView);
TypeElement dynamicUpperBoundType = value.getDynamicUpperBoundType(appView);
if (dynamicUpperBoundType.strictlyLessThan(fieldType, appView)) {
+ if (maybeNull && dynamicUpperBoundType.isDefinitelyNotNull()) {
+ assert dynamicUpperBoundType.isReferenceType();
+ dynamicUpperBoundType = dynamicUpperBoundType.asReferenceType().asMaybeNull();
+ }
feedback.markFieldHasDynamicUpperBoundType(field, dynamicUpperBoundType);
}
@@ -118,10 +129,35 @@
ClassTypeElement dynamicLowerBoundType = value.getDynamicLowerBoundType(appView);
if (dynamicLowerBoundType != null) {
assert dynamicLowerBoundType.lessThanOrEqual(dynamicUpperBoundType, appView);
+ if (maybeNull && dynamicLowerBoundType.isDefinitelyNotNull()) {
+ dynamicLowerBoundType = dynamicLowerBoundType.asMaybeNull().asClassType();
+ }
feedback.markFieldHasDynamicLowerBoundType(field, dynamicLowerBoundType);
}
}
+ public void updateFieldOptimizationInfoWith2Values(
+ DexEncodedField field, FieldInstruction fieldPut, Value valuePut, DexValue valueBeforePut) {
+ // We are interested in the AbstractValue only if it's null or a value, so we can use the value
+ // if the code is protected by a null check.
+ if (valueBeforePut != DexValueNull.NULL) {
+ return;
+ }
+ feedback.recordFieldHasAbstractValue(
+ field, appView, NullOrAbstractValue.create(getOrComputeAbstractValue(valuePut, field)));
+
+ setDynamicType(field, valuePut, true);
+ }
+
+ private AbstractValue getOrComputeAbstractValue(Value value, DexEncodedField field) {
+ Value root = value.getAliasedValue();
+ AbstractValue abstractValue = root.getAbstractValue(appView, context);
+ if (abstractValue.isUnknown()) {
+ return computeSingleFieldValue(field, root);
+ }
+ return abstractValue;
+ }
+
private SingleFieldValue computeSingleFieldValue(DexEncodedField field, Value value) {
assert !value.hasAliasedValue();
SingleFieldValue result = computeSingleEnumFieldValue(value);
@@ -273,8 +309,12 @@
}
NewInstance newInstance = value.definition.asNewInstance();
+ // Some enums have direct subclasses, and the subclass is instantiated here.
if (newInstance.clazz != context.getHolderType()) {
- return null;
+ DexClass dexClass = appView.definitionFor(newInstance.clazz);
+ if (dexClass == null || dexClass.superType != context.getHolderType()) {
+ return null;
+ }
}
if (value.hasDebugUsers() || value.hasPhiUsers()) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
index 41a0192..e53f27b 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
@@ -88,6 +88,14 @@
return false;
}
+ public boolean isNullOrAbstractValue() {
+ return false;
+ }
+
+ public NullOrAbstractValue asNullOrAbstractValue() {
+ return null;
+ }
+
public AbstractValue join(AbstractValue other) {
if (isBottom() || other.isUnknown()) {
return other;
@@ -98,6 +106,12 @@
if (equals(other)) {
return this;
}
+ if (isNull()) {
+ return NullOrAbstractValue.create(other);
+ }
+ if (other.isNull()) {
+ return NullOrAbstractValue.create(this);
+ }
return UnknownValue.getInstance();
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/NullOrAbstractValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/NullOrAbstractValue.java
new file mode 100644
index 0000000..2bf329d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/NullOrAbstractValue.java
@@ -0,0 +1,68 @@
+// 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.analysis.value;
+
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLens;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
+public class NullOrAbstractValue extends AbstractValue {
+
+ private final AbstractValue value;
+
+ private NullOrAbstractValue(AbstractValue value) {
+ this.value = value;
+ }
+
+ public static AbstractValue create(AbstractValue value) {
+ if (value.isBottom() || value.isUnknown() || value.isNull() || value.isNullOrAbstractValue()) {
+ return value;
+ }
+ return new NullOrAbstractValue(value);
+ }
+
+ @Override
+ public boolean isNonTrivial() {
+ return true;
+ }
+
+ @Override
+ public boolean isNullOrAbstractValue() {
+ return true;
+ }
+
+ @Override
+ public NullOrAbstractValue asNullOrAbstractValue() {
+ return this;
+ }
+
+ public AbstractValue getNonNullValue() {
+ return value;
+ }
+
+ @Override
+ public NullOrAbstractValue rewrittenWithLens(
+ AppView<AppInfoWithLiveness> appView, GraphLens lens) {
+ return new NullOrAbstractValue(value.rewrittenWithLens(appView, lens));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ return this.getClass() == o.getClass() && value.equals(((NullOrAbstractValue) o).value);
+ }
+
+ @Override
+ public int hashCode() {
+ return value.hashCode() * 7;
+ }
+
+ @Override
+ public String toString() {
+ return "Null or " + value.toString();
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ValueType.java b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
index 8b06849..0ae9459 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ValueType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
@@ -9,8 +9,9 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
-import com.android.tools.r8.utils.structural.StructuralAccept;
import com.android.tools.r8.utils.structural.StructuralItem;
+import com.android.tools.r8.utils.structural.StructuralMapping;
+import com.android.tools.r8.utils.structural.StructuralSpecification;
public enum ValueType implements StructuralItem<ValueType> {
OBJECT,
@@ -19,14 +20,18 @@
LONG,
DOUBLE;
+ private static void specify(StructuralSpecification<ValueType, ?> spec) {
+ spec.withInt(Enum::ordinal);
+ }
+
@Override
public ValueType self() {
return this;
}
@Override
- public StructuralAccept<ValueType> getStructuralAccept() {
- return spec -> spec.withInt(Enum::ordinal);
+ public StructuralMapping<ValueType> getStructuralMapping() {
+ return ValueType::specify;
}
public boolean isObject() {
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 0974715..2ef58cd 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
@@ -550,10 +550,20 @@
definition.getMutableOptimizationInfo().setReachabilitySensitive(isReachabilitySensitive);
convertMethod(method);
});
+ // The class file version is downgraded after compilation. Some of the desugaring might need
+ // the initial class file version to determine how far a method can be downgraded.
+ if (clazz.hasClassFileVersion()) {
+ clazz.downgradeInitialClassFileVersion(
+ appView.options().classFileVersionAfterDesugaring(clazz.getInitialClassFileVersion()));
+ }
}
private void convertMethod(ProgramMethod method) {
DexEncodedMethod definition = method.getDefinition();
+ if (definition.hasClassFileVersion()) {
+ definition.downgradeClassFileVersion(
+ appView.options().classFileVersionAfterDesugaring(definition.getClassFileVersion()));
+ }
if (definition.getCode() == null) {
return;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
index 6c1c172..bff68b1 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceMethodRewriter.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.ir.desugar;
import com.android.tools.r8.DesugarGraphConsumer;
+import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unimplemented;
@@ -54,6 +55,7 @@
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.collections.SortedProgramMethodSet;
+import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
@@ -214,6 +216,21 @@
return emulatedInterfaces.get(itf);
}
+ private void leavingStaticInvokeToInterface(
+ DexProgramClass holder, DexEncodedMethod encodedMethod) {
+ // When leaving static interface method invokes possibly upgrade the class file
+ // version, but don't go above the initial class file version. If the input was
+ // 1.7 or below, this will make a VerificationError on the input a VerificationError
+ // on the output. If the input was 1.8 or above the runtime behaviour (potential ICCE)
+ // will remain the same.
+ if (holder.hasClassFileVersion()) {
+ encodedMethod.upgradeClassFileVersion(
+ Ordered.min(CfVersion.V1_8, holder.getInitialClassFileVersion()));
+ } else {
+ encodedMethod.upgradeClassFileVersion(CfVersion.V1_8);
+ }
+ }
+
// Rewrites the references to static and default interface methods.
// NOTE: can be called for different methods concurrently.
public void rewriteMethodReferences(IRCode code) {
@@ -257,6 +274,9 @@
// NOTE: leave unchanged those calls to undefined targets. This may lead to runtime
// exception but we can not report it as error since it can also be the intended
// behavior.
+ if (invokeStatic.getInterfaceBit()) {
+ leavingStaticInvokeToInterface(context.getHolder(), encodedMethod);
+ }
warnMissingType(encodedMethod.method, method.holder);
} else if (clazz.isInterface()) {
if (isNonDesugaredLibraryClass(clazz)) {
@@ -304,14 +324,25 @@
invokeStatic.outValue(),
invokeStatic.arguments()));
synchronized (synthesizedMethods) {
+ // The synthetic dispatch class has static interface method invokes, so set
+ // the class file version accordingly.
+ newProgramMethod.getDefinition().upgradeClassFileVersion(CfVersion.V1_8);
synthesizedMethods.add(newProgramMethod);
}
+ } else {
+ // When leaving static interface method invokes upgrade the class file version.
+ encodedMethod.upgradeClassFileVersion(CfVersion.V1_8);
}
} else {
instructions.replaceCurrentInstruction(
new InvokeStatic(staticAsMethodOfCompanionClass(method),
invokeStatic.outValue(), invokeStatic.arguments()));
}
+ } else {
+ assert !clazz.isInterface();
+ if (invokeStatic.getInterfaceBit()) {
+ leavingStaticInvokeToInterface(context.getHolder(), encodedMethod);
+ }
}
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index 88e1200..abe232f 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -213,7 +213,7 @@
ParameterAnnotationsList.empty(),
code,
true,
- iface.hasClassFileVersion() ? iface.getInitialClassFileVersion() : null);
+ iface.getInitialClassFileVersion());
}
private void processVirtualInterfaceMethods(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index b1d8880..23342df 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -89,6 +89,15 @@
}
return false;
}
+
+ public DexValue getStaticValue(DexEncodedField field) {
+ assert hasStaticValue(field);
+ assert field.isStatic();
+ if (fieldsWithStaticValues != null && fieldsWithStaticValues.containsKey(field)) {
+ return fieldsWithStaticValues.get(field);
+ }
+ return field.getStaticValue();
+ }
}
private static class WaveDoneAction implements Action {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
index 033a233..b7addaa 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
@@ -14,13 +14,10 @@
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfo;
-import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
import com.android.tools.r8.ir.analysis.type.ClassTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
-import com.android.tools.r8.ir.analysis.value.ObjectState;
import com.android.tools.r8.ir.analysis.value.SingleNumberValue;
import com.android.tools.r8.ir.analysis.value.SingleStringValue;
import com.android.tools.r8.ir.code.ArrayGet;
@@ -37,7 +34,6 @@
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.StaticGet;
import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.optimize.SwitchMapCollector;
import com.android.tools.r8.ir.optimize.info.FieldOptimizationInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.ArrayUtils;
@@ -103,40 +99,20 @@
FieldOptimizationInfo optimizationInfo = definition.getOptimizationInfo();
AbstractValue abstractValue = optimizationInfo.getAbstractValue();
- if (!abstractValue.isSingleFieldValue()) {
- continue;
- }
-
- ObjectState objectState = abstractValue.asSingleFieldValue().getState();
- if (objectState.isEmpty()) {
- continue;
- }
Value outValue = methodWithReceiver.outValue();
if (isOrdinalInvoke) {
- DexField ordinalField = appView.dexItemFactory().enumMembers.ordinalField;
- DexEncodedField ordinalDefinition =
- ordinalField.lookupOnClass(appView.definitionForHolder(ordinalField));
- if (ordinalDefinition != null) {
- SingleNumberValue ordinalValue =
- objectState.getAbstractFieldValue(ordinalDefinition).asSingleNumberValue();
+ SingleNumberValue ordinalValue =
+ getOrdinalValue(code, abstractValue, methodWithReceiver.getReceiver().isNeverNull());
if (ordinalValue != null) {
iterator.replaceCurrentInstruction(
new ConstNumber(outValue, ordinalValue.getValue()));
- }
}
continue;
}
- DexField nameField = appView.dexItemFactory().enumMembers.nameField;
- DexEncodedField nameDefinition =
- nameField.lookupOnClass(appView.definitionForHolder(nameField));
- if (nameField == null) {
- continue;
- }
-
SingleStringValue nameValue =
- objectState.getAbstractFieldValue(nameDefinition).asSingleStringValue();
+ getNameValue(code, abstractValue, methodWithReceiver.getReceiver().isNeverNull());
if (nameValue == null) {
continue;
}
@@ -228,7 +204,7 @@
continue;
}
- Int2IntMap ordinalToTargetMap = computeOrdinalToTargetMap(switchInsn, info);
+ Int2IntMap ordinalToTargetMap = computeOrdinalToTargetMap(code, switchInsn, info);
if (ordinalToTargetMap == null) {
continue;
}
@@ -315,24 +291,62 @@
}
}
- private Int2IntMap computeOrdinalToTargetMap(IntSwitch switchInsn, EnumSwitchInfo info) {
- Int2IntMap ordinalToTargetMap = new Int2IntArrayMap(switchInsn.numberOfKeys());
+ private Int2IntArrayMap computeOrdinalToTargetMap(
+ IRCode code, IntSwitch switchInsn, EnumSwitchInfo info) {
+ Int2IntArrayMap ordinalToTargetMap = new Int2IntArrayMap(switchInsn.numberOfKeys());
for (int i = 0; i < switchInsn.numberOfKeys(); i++) {
assert switchInsn.targetBlockIndices()[i] != switchInsn.getFallthroughBlockIndex();
DexField field = info.indexMap.get(switchInsn.getKey(i));
- EnumValueInfo valueInfo = info.valueInfoMap.getEnumValueInfo(field);
- if (valueInfo != null) {
- if (appView.appInfo().isPinned(field)) {
+ DexEncodedField enumInstanceField =
+ appView.appInfo().resolveField(field, code.context()).getResolvedField();
+ if (enumInstanceField == null) {
+ // The switch map refers to a field on the enum that does not exist in this compilation.
+ } else {
+ AbstractValue abstractValue = enumInstanceField.getOptimizationInfo().getAbstractValue();
+ // The rewriting effectively leaves in place the myEnum.ordinal() call, so if the value
+ // is null, the same NPE happens at runtime, we can assume the value is non null in the
+ // switch map after the ordinal call.
+ SingleNumberValue ordinalValue = getOrdinalValue(code, abstractValue, true);
+ if (ordinalValue == null) {
return null;
}
- ordinalToTargetMap.put(valueInfo.ordinal, switchInsn.targetBlockIndices()[i]);
- } else {
- // The switch map refers to a field on the enum that does not exist in this compilation.
+ ordinalToTargetMap.put(
+ ordinalValue.asSingleNumberValue().getIntValue(), switchInsn.targetBlockIndices()[i]);
}
}
return ordinalToTargetMap;
}
+ private SingleStringValue getNameValue(
+ IRCode code, AbstractValue abstractValue, boolean neverNull) {
+ AbstractValue ordinalValue =
+ getEnumFieldValue(code, abstractValue, factory.enumMembers.nameField, neverNull);
+ return ordinalValue == null ? null : ordinalValue.asSingleStringValue();
+ }
+
+ private SingleNumberValue getOrdinalValue(
+ IRCode code, AbstractValue abstractValue, boolean neverNull) {
+ AbstractValue ordinalValue =
+ getEnumFieldValue(code, abstractValue, factory.enumMembers.ordinalField, neverNull);
+ return ordinalValue == null ? null : ordinalValue.asSingleNumberValue();
+ }
+
+ private AbstractValue getEnumFieldValue(
+ IRCode code, AbstractValue abstractValue, DexField field, boolean neverNull) {
+ if (neverNull && abstractValue.isNullOrAbstractValue()) {
+ abstractValue = abstractValue.asNullOrAbstractValue().getNonNullValue();
+ }
+ if (!abstractValue.isSingleFieldValue()) {
+ return null;
+ }
+ DexEncodedField encodedField =
+ appView.appInfo().resolveField(field, code.context()).getResolvedField();
+ if (encodedField == null) {
+ return null;
+ }
+ return abstractValue.asSingleFieldValue().getState().getAbstractFieldValue(encodedField);
+ }
+
private static final class EnumSwitchInfo {
final DexType enumClass;
@@ -340,21 +354,18 @@
final Instruction arrayGet;
public final Instruction staticGet;
final Int2ReferenceMap<DexField> indexMap;
- final EnumValueInfoMap valueInfoMap;
private EnumSwitchInfo(
DexType enumClass,
Instruction ordinalInvoke,
Instruction arrayGet,
Instruction staticGet,
- Int2ReferenceMap<DexField> indexMap,
- EnumValueInfoMap valueInfoMap) {
+ Int2ReferenceMap<DexField> indexMap) {
this.enumClass = enumClass;
this.ordinalInvoke = ordinalInvoke;
this.arrayGet = arrayGet;
this.staticGet = staticGet;
this.indexMap = indexMap;
- this.valueInfoMap = valueInfoMap;
}
}
@@ -371,8 +382,7 @@
*
* </blockquote>
*
- * and extracts the components and the index and ordinal maps. See {@link
- * EnumValueInfoMapCollector} and {@link SwitchMapCollector} for details.
+ * and extracts the components and the index and ordinal maps.
*/
private EnumSwitchInfo analyzeSwitchOverEnum(IntSwitch switchInsn) {
Instruction input = switchInsn.inValues().get(0).definition;
@@ -412,10 +422,6 @@
}
// Due to member rebinding, only the fields are certain to provide the actual enums class.
DexType enumType = indexMap.values().iterator().next().holder;
- EnumValueInfoMap valueInfoMap = appView.appInfo().getEnumValueInfoMap(enumType);
- if (valueInfoMap == null) {
- return null;
- }
- return new EnumSwitchInfo(enumType, ordinalInvoke, arrayGet, staticGet, indexMap, valueInfoMap);
+ return new EnumSwitchInfo(enumType, ordinalInvoke, arrayGet, staticGet, indexMap);
}
}
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index 58c9f2d..25688ce 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -263,10 +263,13 @@
|| options.isDesugaredLibraryCompilation()
|| options.cfToCfDesugar
: "Expected class file version for " + method.method.toSourceString();
- // TODO(b/146424042): We may call static methods on interface classes so we have to go for
- // Java 8.
- assert MIN_VERSION_FOR_COMPILER_GENERATED_CODE.isLessThan(CfVersion.V1_8);
- return options.cfToCfDesugar ? CfVersion.V1_8 : MIN_VERSION_FOR_COMPILER_GENERATED_CODE;
+ assert MIN_VERSION_FOR_COMPILER_GENERATED_CODE.isLessThan(
+ options.classFileVersionAfterDesugaring(InternalOptions.SUPPORTED_CF_VERSION));
+ // Any desugaring rewrites which cannot meet the default class file version after
+ // desugaring must upgrade the class file version during desugaring.
+ return options.cfToCfDesugar
+ ? options.classFileVersionAfterDesugaring(InternalOptions.SUPPORTED_CF_VERSION)
+ : MIN_VERSION_FOR_COMPILER_GENERATED_CODE;
}
return method.getClassFileVersion();
}
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
index b4760c1..bcbba53 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.repackaging;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -41,10 +42,13 @@
private final ProgramPackage pkg;
private final Map<DexDefinition, Node> nodes = new IdentityHashMap<>();
private final Set<Node> pinnedNodes = Sets.newIdentityHashSet();
+ private final Node libraryBoundaryNode;
public RepackagingConstraintGraph(AppView<AppInfoWithLiveness> appView, ProgramPackage pkg) {
this.appView = appView;
this.pkg = pkg;
+ libraryBoundaryNode = createNode(appView.definitionFor(appView.dexItemFactory().objectType));
+ pinnedNodes.add(libraryBoundaryNode);
}
/** Returns true if all classes in the package can be repackaged. */
@@ -75,6 +79,13 @@
}
Node getNode(DexDefinition definition) {
+ if (definition.isNotProgramDefinition(appView)) {
+ String packageDescriptor = definition.getContextType().getPackageDescriptor();
+ if (packageDescriptor.equals(pkg.getPackageDescriptor())) {
+ return libraryBoundaryNode;
+ }
+ return null;
+ }
return nodes.get(definition);
}
@@ -110,7 +121,11 @@
}
// Trace the references to the inner and outer classes.
- clazz.getInnerClasses().forEach(registry::registerInnerClassAttribute);
+ clazz
+ .getInnerClasses()
+ .forEach(
+ innerClassAttribute ->
+ registry.registerInnerClassAttribute(clazz, innerClassAttribute));
// Trace the references from the enclosing method attribute.
EnclosingMethodAttribute attr = clazz.getEnclosingMethodAttribute();
@@ -137,8 +152,8 @@
definition.getProto().forEachType(registry::registerTypeReference);
// Check if this overrides a package-private method.
- DexProgramClass superClass =
- appView.programDefinitionFor(method.getHolder().getSuperType(), method.getHolder());
+ DexClass superClass =
+ appView.definitionFor(method.getHolder().getSuperType(), method.getHolder());
if (superClass != null) {
registry.registerMemberAccess(
appView.appInfo().resolveMethodOn(superClass, method.getReference()));
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
index 57361d3..91484f7 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexClassAndMember;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
@@ -19,7 +20,6 @@
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.MemberResolutionResult;
import com.android.tools.r8.graph.ProgramDefinition;
-import com.android.tools.r8.graph.ProgramMember;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.ResolutionResult;
import com.android.tools.r8.graph.SuccessfulMemberResolutionResult;
@@ -48,7 +48,7 @@
this.node = constraintGraph.getNode(context.getDefinition());
}
- private boolean isOnlyAccessibleFromSamePackage(DexProgramClass referencedClass) {
+ private boolean isOnlyAccessibleFromSamePackage(DexClass referencedClass) {
ClassAccessFlags accessFlags = referencedClass.getAccessFlags();
if (accessFlags.isPackagePrivate()) {
return true;
@@ -60,8 +60,8 @@
return false;
}
- private boolean isOnlyAccessibleFromSamePackage(ProgramMember<?, ?> member) {
- AccessFlags<?> accessFlags = member.getDefinition().getAccessFlags();
+ private boolean isOnlyAccessibleFromSamePackage(DexClassAndMember<?, ?> member) {
+ AccessFlags<?> accessFlags = member.getAccessFlags();
if (accessFlags.isPackagePrivate()) {
return true;
}
@@ -96,22 +96,21 @@
}
// Check access to the initial resolution holder.
- registerTypeAccess(successfulResolutionResult.getInitialResolutionHolder());
+ registerClassTypeAccess(successfulResolutionResult.getInitialResolutionHolder());
// Similarly, check access to the resolved member.
- ProgramMember<?, ?> resolvedMember =
- successfulResolutionResult.getResolvedMember().asProgramMember(appInfo);
- if (resolvedMember != null) {
+ DexClassAndMember<?, ?> resolutionPair = successfulResolutionResult.getResolutionPair();
+ if (resolutionPair != null) {
RepackagingConstraintGraph.Node resolvedMemberNode =
- constraintGraph.getNode(resolvedMember.getDefinition());
- if (resolvedMemberNode != null && isOnlyAccessibleFromSamePackage(resolvedMember)) {
+ constraintGraph.getNode(resolutionPair.getDefinition());
+ if (resolvedMemberNode != null && isOnlyAccessibleFromSamePackage(resolutionPair)) {
node.addNeighbor(resolvedMemberNode);
}
}
}
private void registerTypeAccess(DexType type) {
- registerTypeAccess(type, this::registerTypeAccess);
+ registerTypeAccess(type, this::registerClassTypeAccess);
}
private void registerTypeAccess(DexType type, Consumer<DexClass> consumer) {
@@ -129,20 +128,17 @@
}
}
- private void registerTypeAccess(DexClass clazz) {
- registerTypeAccess(clazz, this::isOnlyAccessibleFromSamePackage);
+ private void registerClassTypeAccess(DexClass clazz) {
+ registerClassTypeAccess(clazz, this::isOnlyAccessibleFromSamePackage);
}
- private void registerTypeAccess(DexClass clazz, Predicate<DexProgramClass> predicate) {
+ private void registerClassTypeAccess(DexClass clazz, Predicate<DexClass> predicate) {
// We only want to connect the current method node to the class node if the access requires the
- // two nodes to be in the same package. Therefore, we ignore accesses to non-program classes
- // and program classes outside the current package.
- DexProgramClass programClass = clazz.asProgramClass();
- if (programClass != null) {
- RepackagingConstraintGraph.Node classNode = constraintGraph.getNode(programClass);
- if (classNode != null && predicate.test(programClass)) {
- node.addNeighbor(classNode);
- }
+ // two nodes to be in the same package. Therefore, we ignore accesses to program classes outside
+ // the current package.
+ RepackagingConstraintGraph.Node classNode = constraintGraph.getNode(clazz);
+ if (classNode != null && predicate.test(clazz)) {
+ node.addNeighbor(classNode);
}
}
@@ -218,21 +214,22 @@
if (enclosingMethodAttribute.getEnclosingClass() != null) {
registerTypeAccess(
enclosingMethodAttribute.getEnclosingClass(),
- clazz -> registerTypeAccess(clazz, alwaysTrue()));
+ clazz -> registerClassTypeAccess(clazz, alwaysTrue()));
}
if (enclosingMethodAttribute.getEnclosingMethod() != null) {
ProgramMethod method = registerMethodReference(enclosingMethodAttribute.getEnclosingMethod());
if (method != null) {
- registerTypeAccess(method.getHolder(), alwaysTrue());
+ registerClassTypeAccess(method.getHolder(), alwaysTrue());
}
}
}
- public void registerInnerClassAttribute(InnerClassAttribute innerClassAttribute) {
+ public void registerInnerClassAttribute(
+ DexProgramClass outer, InnerClassAttribute innerClassAttribute) {
// For references in inner class attributes we add an edge from the context to the referenced
// class even if the referenced class would be accessible from another package, to make sure
// that we don't split such classes into different packages.
innerClassAttribute.forEachType(
- type -> registerTypeAccess(type, clazz -> registerTypeAccess(clazz, alwaysTrue())));
+ type -> registerTypeAccess(type, clazz -> registerClassTypeAccess(clazz, alwaysTrue())));
}
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index 4d621a3..6fa737b 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -282,6 +282,8 @@
methodBuilder
.setAccessFlags(definition.accessFlags)
.setProto(definition.getProto())
+ .setClassFileVersion(
+ definition.hasClassFileVersion() ? definition.getClassFileVersion() : null)
.setCode(m -> definition.getCode());
});
DexProgramClass externalSyntheticClass = builder.build();
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
index ee17db8..9fcc7d9 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.synthesis;
+import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -21,6 +22,7 @@
private final SyntheticClassBuilder parent;
private final String name;
private DexProto proto = null;
+ private CfVersion classFileVersion;
private SyntheticCodeGenerator codeGenerator = null;
private MethodAccessFlags accessFlags = null;
@@ -34,6 +36,11 @@
return this;
}
+ public SyntheticMethodBuilder setClassFileVersion(CfVersion classFileVersion) {
+ this.classFileVersion = classFileVersion;
+ return this;
+ }
+
public SyntheticMethodBuilder setCode(SyntheticCodeGenerator codeGenerator) {
this.codeGenerator = codeGenerator;
return this;
@@ -55,7 +62,8 @@
DexAnnotationSet.empty(),
ParameterAnnotationsList.empty(),
getCodeObject(methodSignature),
- isCompilerSynthesized);
+ isCompilerSynthesized,
+ classFileVersion);
assert isValidSyntheticMethod(method);
return method;
}
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 f4cdbaa..cd3a2db 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -63,6 +63,7 @@
import com.android.tools.r8.utils.IROrdering.IdentityIROrdering;
import com.android.tools.r8.utils.IROrdering.NondeterministicIROrdering;
import com.android.tools.r8.utils.collections.SortedProgramMethodSet;
+import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
@@ -595,6 +596,10 @@
|| getProguardConfiguration().getKeepAttributes().innerClasses;
}
+ public boolean canUseInputStackMaps() {
+ return testing.readInputStackMaps ? testing.readInputStackMaps : isGeneratingClassFiles();
+ }
+
public boolean printCfg = false;
public String printCfgFile;
public boolean ignoreMissingClasses = false;
@@ -1529,6 +1534,15 @@
return (isGeneratingClassFiles() && !cfToCfDesugar) || hasMinApi(AndroidApiLevel.K);
}
+ public CfVersion classFileVersionAfterDesugaring(CfVersion version) {
+ if (!isDesugaring()) {
+ return version;
+ }
+ CfVersion maxVersionAfterDesugar =
+ canUseDefaultAndStaticInterfaceMethods() ? CfVersion.V1_8 : CfVersion.V1_7;
+ return Ordered.min(maxVersionAfterDesugar, version);
+ }
+
// The Apache Harmony-based AssertionError constructor which takes an Object on API 15 and older
// calls the Error supertype constructor with null as the exception cause. This prevents
// subsequent calls to initCause() because its implementation checks that cause==this before
diff --git a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitor.java b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitor.java
index 32221a0..a0b2104 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitor.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitor.java
@@ -17,45 +17,48 @@
/** Base class for a visitor implementing compareTo on a structural item. */
public abstract class CompareToVisitor {
- public abstract void visitBool(boolean value1, boolean value2);
+ public abstract int visitBool(boolean value1, boolean value2);
- public abstract void visitInt(int value1, int value2);
+ public abstract int visitInt(int value1, int value2);
- public abstract void visitLong(long value1, long value2);
+ public abstract int visitLong(long value1, long value2);
- public abstract void visitFloat(float value1, float value2);
+ public abstract int visitFloat(float value1, float value2);
- public abstract void visitDouble(double value1, double value2);
+ public abstract int visitDouble(double value1, double value2);
/** Base for visiting an enumeration of items. */
- public abstract <S> void visitItemIterator(
+ public abstract <S> int visitItemIterator(
Iterator<S> it1, Iterator<S> it2, CompareToAccept<S> compareToAccept);
- public final <S extends StructuralItem<S>> void visitItemArray(S[] items1, S[] items2) {
- visitItemCollection(Arrays.asList(items1), Arrays.asList(items2));
+ public final <S extends StructuralItem<S>> int visitItemArray(S[] items1, S[] items2) {
+ return visitItemCollection(Arrays.asList(items1), Arrays.asList(items2));
}
- public final <S extends StructuralItem<S>> void visitItemCollection(
+ public final <S extends StructuralItem<S>> int visitItemCollection(
Collection<S> items1, Collection<S> items2) {
- visitItemIterator(items1.iterator(), items2.iterator(), S::acceptCompareTo);
+ return visitItemIterator(
+ items1.iterator(),
+ items2.iterator(),
+ (s, other, visitor) -> s.acceptCompareTo(other, visitor));
}
- public abstract void visitDexString(DexString string1, DexString string2);
+ public abstract int visitDexString(DexString string1, DexString string2);
- public abstract void visitDexType(DexType type1, DexType type2);
+ public abstract int visitDexType(DexType type1, DexType type2);
- public void visitDexField(DexField field1, DexField field2) {
- visit(field1, field2, field1.getStructuralAccept());
+ public int visitDexField(DexField field1, DexField field2) {
+ return visit(field1, field2, field1.getStructuralMapping());
}
- public void visitDexMethod(DexMethod method1, DexMethod method2) {
- visit(method1, method2, method1.getStructuralAccept());
+ public int visitDexMethod(DexMethod method1, DexMethod method2) {
+ return visit(method1, method2, method1.getStructuralMapping());
}
- public abstract void visitDexReference(DexReference reference1, DexReference reference2);
+ public abstract int visitDexReference(DexReference reference1, DexReference reference2);
- public abstract <S> void visit(S item1, S item2, StructuralAccept<S> accept);
+ public abstract <S> int visit(S item1, S item2, StructuralMapping<S> accept);
@Deprecated
- public abstract <S> void visit(S item1, S item2, Comparator<S> comparator);
+ public abstract <S> int visit(S item1, S item2, Comparator<S> comparator);
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorBase.java b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorBase.java
index 1f517d0..ee264cc 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorBase.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorBase.java
@@ -18,102 +18,75 @@
/** Base class to share most visiting methods */
public abstract class CompareToVisitorBase extends CompareToVisitor {
- private int order = 0;
-
- public final boolean stillEqual() {
- return order == 0;
+ @Override
+ public final int visitBool(boolean value1, boolean value2) {
+ return Boolean.compare(value1, value2);
}
- public final int getOrder() {
+ @Override
+ public final int visitInt(int value1, int value2) {
+ return Integer.compare(value1, value2);
+ }
+
+ @Override
+ public int visitLong(long value1, long value2) {
+ return Long.compare(value1, value2);
+ }
+
+ @Override
+ public int visitFloat(float value1, float value2) {
+ return Float.compare(value1, value2);
+ }
+
+ @Override
+ public int visitDouble(double value1, double value2) {
+ return Double.compare(value1, value2);
+ }
+
+ @Override
+ public <S> int visitItemIterator(
+ Iterator<S> it1, Iterator<S> it2, CompareToAccept<S> compareToAccept) {
+ int order = 0;
+ while (order == 0 && it1.hasNext() && it2.hasNext()) {
+ order = compareToAccept.acceptCompareTo(it1.next(), it2.next(), this);
+ }
+ if (order == 0) {
+ order = visitBool(it1.hasNext(), it2.hasNext());
+ }
return order;
}
- public final void setOrder(int order) {
- this.order = order;
+ @Override
+ public int visitDexString(DexString string1, DexString string2) {
+ return string1.compareTo(string2);
}
@Override
- public final void visitBool(boolean value1, boolean value2) {
- if (stillEqual()) {
- setOrder(Boolean.compare(value1, value2));
- }
- }
-
- @Override
- public final void visitInt(int value1, int value2) {
- if (stillEqual()) {
- setOrder(Integer.compare(value1, value2));
- }
- }
-
- @Override
- public void visitLong(long value1, long value2) {
- if (stillEqual()) {
- setOrder(Long.compare(value1, value2));
- }
- }
-
- @Override
- public void visitFloat(float value1, float value2) {
- if (stillEqual()) {
- setOrder(Float.compare(value1, value2));
- }
- }
-
- @Override
- public void visitDouble(double value1, double value2) {
- if (stillEqual()) {
- setOrder(Double.compare(value1, value2));
- }
- }
-
- @Override
- public <S> void visitItemIterator(
- Iterator<S> it1, Iterator<S> it2, CompareToAccept<S> compareToAccept) {
- while (stillEqual() && it1.hasNext() && it2.hasNext()) {
- compareToAccept.acceptCompareTo(it1.next(), it2.next(), this);
- }
- if (stillEqual()) {
- visitBool(it1.hasNext(), it2.hasNext());
- }
- }
-
- @Override
- public void visitDexString(DexString string1, DexString string2) {
- if (stillEqual()) {
- setOrder(string1.compareTo(string2));
- }
- }
-
- @Override
- public void visitDexReference(DexReference reference1, DexReference reference2) {
- if (stillEqual()) {
- visitInt(reference1.referenceTypeOrder(), reference2.referenceTypeOrder());
- if (stillEqual()) {
- assert reference1.getClass() == reference2.getClass();
- if (reference1.isDexType()) {
- visitDexType(reference1.asDexType(), reference2.asDexType());
- } else if (reference1.isDexField()) {
- visitDexField(reference1.asDexField(), reference2.asDexField());
- } else {
- visitDexMethod(reference1.asDexMethod(), reference2.asDexMethod());
- }
+ public int visitDexReference(DexReference reference1, DexReference reference2) {
+ int order = visitInt(reference1.referenceTypeOrder(), reference2.referenceTypeOrder());
+ if (order == 0) {
+ assert reference1.getClass() == reference2.getClass();
+ if (reference1.isDexType()) {
+ order = visitDexType(reference1.asDexType(), reference2.asDexType());
+ } else if (reference1.isDexField()) {
+ order = visitDexField(reference1.asDexField(), reference2.asDexField());
+ } else {
+ order = visitDexMethod(reference1.asDexMethod(), reference2.asDexMethod());
}
}
+ return order;
}
@Override
- public final <S> void visit(S item1, S item2, Comparator<S> comparator) {
- if (stillEqual()) {
- setOrder(comparator.compare(item1, item2));
- }
+ public final <S> int visit(S item1, S item2, Comparator<S> comparator) {
+ return comparator.compare(item1, item2);
}
@Override
- public final <S> void visit(S item1, S item2, StructuralAccept<S> accept) {
- if (stillEqual()) {
- accept.apply(new ItemSpecification<>(item1, item2, this));
- }
+ public final <S> int visit(S item1, S item2, StructuralMapping<S> accept) {
+ ItemSpecification<S> itemVisitor = new ItemSpecification<>(item1, item2, this);
+ accept.apply(itemVisitor);
+ return itemVisitor.order;
}
private static class ItemSpecification<T>
@@ -122,6 +95,7 @@
private final CompareToVisitorBase parent;
private final T item1;
private final T item2;
+ private int order = 0;
private ItemSpecification(T item1, T item2, CompareToVisitorBase parent) {
this.item1 = item1;
@@ -138,47 +112,47 @@
@Override
public ItemSpecification<T> withBool(Predicate<T> getter) {
- if (parent.stillEqual()) {
- parent.visitBool(getter.test(item1), getter.test(item2));
+ if (order == 0) {
+ order = parent.visitBool(getter.test(item1), getter.test(item2));
}
return this;
}
@Override
public ItemSpecification<T> withInt(ToIntFunction<T> getter) {
- if (parent.stillEqual()) {
- parent.visitInt(getter.applyAsInt(item1), getter.applyAsInt(item2));
+ if (order == 0) {
+ order = parent.visitInt(getter.applyAsInt(item1), getter.applyAsInt(item2));
}
return this;
}
@Override
public ItemSpecification<T> withLong(ToLongFunction<T> getter) {
- if (parent.stillEqual()) {
- parent.visitLong(getter.applyAsLong(item1), getter.applyAsLong(item2));
+ if (order == 0) {
+ order = parent.visitLong(getter.applyAsLong(item1), getter.applyAsLong(item2));
}
return this;
}
@Override
public ItemSpecification<T> withDouble(ToDoubleFunction<T> getter) {
- if (parent.stillEqual()) {
- parent.visitDouble(getter.applyAsDouble(item1), getter.applyAsDouble(item2));
+ if (order == 0) {
+ order = parent.visitDouble(getter.applyAsDouble(item1), getter.applyAsDouble(item2));
}
return this;
}
@Override
public ItemSpecification<T> withIntArray(Function<T, int[]> getter) {
- if (parent.stillEqual()) {
+ if (order == 0) {
int[] is1 = getter.apply(item1);
int[] is2 = getter.apply(item2);
int minLength = Math.min(is1.length, is2.length);
- for (int i = 0; i < minLength && parent.stillEqual(); i++) {
- parent.visitInt(is1[i], is2[i]);
+ for (int i = 0; i < minLength && order == 0; i++) {
+ order = parent.visitInt(is1[i], is2[i]);
}
- if (parent.stillEqual()) {
- parent.visitInt(is1.length, is2.length);
+ if (order == 0) {
+ order = parent.visitInt(is1.length, is2.length);
}
}
return this;
@@ -190,13 +164,13 @@
Function<T, S> getter,
CompareToAccept<S> compare,
HashingAccept<S> hasher) {
- if (parent.stillEqual()) {
+ if (order == 0) {
boolean test1 = predicate.test(item1);
boolean test2 = predicate.test(item2);
if (test1 && test2) {
- compare.acceptCompareTo(getter.apply(item1), getter.apply(item2), parent);
+ order = compare.acceptCompareTo(getter.apply(item1), getter.apply(item2), parent);
} else {
- parent.visitBool(test1, test2);
+ order = parent.visitBool(test1, test2);
}
}
return this;
@@ -205,8 +179,8 @@
@Override
protected <S> ItemSpecification<T> withItemIterator(
Function<T, Iterator<S>> getter, CompareToAccept<S> compare, HashingAccept<S> hasher) {
- if (parent.stillEqual()) {
- parent.visitItemIterator(getter.apply(item1), getter.apply(item2), compare);
+ if (order == 0) {
+ order = parent.visitItemIterator(getter.apply(item1), getter.apply(item2), compare);
}
return this;
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithNamingLens.java b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithNamingLens.java
index 5295766..f581065 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithNamingLens.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithNamingLens.java
@@ -11,15 +11,14 @@
public class CompareToVisitorWithNamingLens extends CompareToVisitorBase {
- public static <T> int run(T item1, T item2, NamingLens namingLens, StructuralAccept<T> visit) {
+ public static <T> int run(T item1, T item2, NamingLens namingLens, StructuralMapping<T> visit) {
return run(item1, item2, namingLens, (i1, i2, visitor) -> visitor.visit(i1, i2, visit));
}
public static <T> int run(
T item1, T item2, NamingLens namingLens, CompareToAccept<T> compareToAccept) {
CompareToVisitorWithNamingLens state = new CompareToVisitorWithNamingLens(namingLens);
- compareToAccept.acceptCompareTo(item1, item2, state);
- return state.getOrder();
+ return compareToAccept.acceptCompareTo(item1, item2, state);
}
private final NamingLens namingLens;
@@ -29,35 +28,35 @@
}
@Override
- public void visitDexType(DexType type1, DexType type2) {
- if (stillEqual()) {
- namingLens.lookupDescriptor(type1).acceptCompareTo(namingLens.lookupDescriptor(type2), this);
- }
+ public int visitDexType(DexType type1, DexType type2) {
+ return namingLens
+ .lookupDescriptor(type1)
+ .acceptCompareTo(namingLens.lookupDescriptor(type2), this);
}
@Override
- public void visitDexField(DexField field1, DexField field2) {
- if (stillEqual()) {
- field1.holder.acceptCompareTo(field2.holder, this);
- if (stillEqual()) {
- namingLens.lookupName(field1).acceptCompareTo(namingLens.lookupName(field2), this);
- if (stillEqual()) {
- field1.type.acceptCompareTo(field2.type, this);
- }
- }
+ public int visitDexField(DexField field1, DexField field2) {
+ int order = field1.holder.acceptCompareTo(field2.holder, this);
+ if (order != 0) {
+ return order;
}
+ order = namingLens.lookupName(field1).acceptCompareTo(namingLens.lookupName(field2), this);
+ if (order != 0) {
+ return order;
+ }
+ return field1.type.acceptCompareTo(field2.type, this);
}
@Override
- public void visitDexMethod(DexMethod method1, DexMethod method2) {
- if (stillEqual()) {
- method1.holder.acceptCompareTo(method2.holder, this);
- if (stillEqual()) {
- namingLens.lookupName(method1).acceptCompareTo(namingLens.lookupName(method2), this);
- if (stillEqual()) {
- method1.proto.acceptCompareTo(method2.proto, this);
- }
- }
+ public int visitDexMethod(DexMethod method1, DexMethod method2) {
+ int order = method1.holder.acceptCompareTo(method2.holder, this);
+ if (order != 0) {
+ return order;
}
+ order = namingLens.lookupName(method1).acceptCompareTo(namingLens.lookupName(method2), this);
+ if (order != 0) {
+ return order;
+ }
+ return method1.proto.acceptCompareTo(method2.proto, this);
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithStringTable.java b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithStringTable.java
index dfd9fa0..78fb663 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithStringTable.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithStringTable.java
@@ -4,20 +4,11 @@
package com.android.tools.r8.utils.structural;
import com.android.tools.r8.graph.DexString;
-import com.android.tools.r8.graph.NamingLensComparable;
import com.android.tools.r8.naming.NamingLens;
import java.util.function.ToIntFunction;
public class CompareToVisitorWithStringTable extends CompareToVisitorWithNamingLens {
- public static <T extends NamingLensComparable<T>> int run(
- T item1, T item2, NamingLens namingLens, ToIntFunction<DexString> stringTable) {
- CompareToVisitorWithNamingLens state =
- new CompareToVisitorWithStringTable(namingLens, stringTable);
- item1.acceptCompareTo(item2, state);
- return state.getOrder();
- }
-
private final ToIntFunction<DexString> stringTable;
public CompareToVisitorWithStringTable(
@@ -27,9 +18,7 @@
}
@Override
- public void visitDexString(DexString string1, DexString string2) {
- if (stillEqual()) {
- visitInt(stringTable.applyAsInt(string1), stringTable.applyAsInt(string2));
- }
+ public int visitDexString(DexString string1, DexString string2) {
+ return visitInt(stringTable.applyAsInt(string1), stringTable.applyAsInt(string2));
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithTypeEquivalence.java b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithTypeEquivalence.java
index 62b1942..89bd02b 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithTypeEquivalence.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithTypeEquivalence.java
@@ -8,15 +8,14 @@
public class CompareToVisitorWithTypeEquivalence extends CompareToVisitorBase {
- public static <T> int run(T item1, T item2, RepresentativeMap map, StructuralAccept<T> visit) {
+ public static <T> int run(T item1, T item2, RepresentativeMap map, StructuralMapping<T> visit) {
return run(item1, item2, map, (i1, i2, visitor) -> visitor.visit(i1, i2, visit));
}
public static <T> int run(
T item1, T item2, RepresentativeMap map, CompareToAccept<T> compareToAccept) {
CompareToVisitorWithTypeEquivalence state = new CompareToVisitorWithTypeEquivalence(map);
- compareToAccept.acceptCompareTo(item1, item2, state);
- return state.getOrder();
+ return compareToAccept.acceptCompareTo(item1, item2, state);
}
private final RepresentativeMap representatives;
@@ -26,11 +25,9 @@
}
@Override
- public void visitDexType(DexType type1, DexType type2) {
- if (stillEqual()) {
- DexType repr1 = representatives.getRepresentative(type1);
- DexType repr2 = representatives.getRepresentative(type2);
- repr1.getDescriptor().acceptCompareTo(repr2.getDescriptor(), this);
- }
+ public int visitDexType(DexType type1, DexType type2) {
+ DexType repr1 = representatives.getRepresentative(type1);
+ DexType repr2 = representatives.getRepresentative(type2);
+ return repr1.getDescriptor().acceptCompareTo(repr2.getDescriptor(), this);
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithTypeTable.java b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithTypeTable.java
index 94fb1f9..52a718a 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithTypeTable.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/CompareToVisitorWithTypeTable.java
@@ -5,24 +5,11 @@
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.NamingLensComparable;
import com.android.tools.r8.naming.NamingLens;
import java.util.function.ToIntFunction;
public class CompareToVisitorWithTypeTable extends CompareToVisitorWithStringTable {
- public static <T extends NamingLensComparable<T>> int run(
- T item1,
- T item2,
- NamingLens namingLens,
- ToIntFunction<DexString> stringTable,
- ToIntFunction<DexType> typeTable) {
- CompareToVisitorWithNamingLens state =
- new CompareToVisitorWithTypeTable(namingLens, stringTable, typeTable);
- item1.acceptCompareTo(item2, state);
- return state.getOrder();
- }
-
private final ToIntFunction<DexType> typeTable;
public CompareToVisitorWithTypeTable(
@@ -34,9 +21,7 @@
}
@Override
- public void visitDexType(DexType type1, DexType type2) {
- if (stillEqual()) {
- visitInt(typeTable.applyAsInt(type1), typeTable.applyAsInt(type2));
- }
+ public int visitDexType(DexType type1, DexType type2) {
+ return visitInt(typeTable.applyAsInt(type1), typeTable.applyAsInt(type2));
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/DefaultCompareToVisitor.java b/src/main/java/com/android/tools/r8/utils/structural/DefaultCompareToVisitor.java
index 9f91d19..aa3fd96 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/DefaultCompareToVisitor.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/DefaultCompareToVisitor.java
@@ -13,7 +13,7 @@
*/
public class DefaultCompareToVisitor {
- public static <T> int run(T item1, T item2, StructuralAccept<T> visit) {
+ public static <T> int run(T item1, T item2, StructuralMapping<T> visit) {
return run(item1, item2, (i1, i2, visitor) -> visitor.visit(i1, i2, visit));
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/DefaultHashingVisitor.java b/src/main/java/com/android/tools/r8/utils/structural/DefaultHashingVisitor.java
index 2ec503c..d1b6653 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/DefaultHashingVisitor.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/DefaultHashingVisitor.java
@@ -14,7 +14,7 @@
*/
public class DefaultHashingVisitor {
- public static <T> void run(T item, Hasher hasher, StructuralAccept<T> accept) {
+ public static <T> void run(T item, Hasher hasher, StructuralMapping<T> accept) {
run(item, hasher, (i, visitor) -> visitor.visit(i, accept));
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/HashCodeVisitor.java b/src/main/java/com/android/tools/r8/utils/structural/HashCodeVisitor.java
index 1b5b400..c64e0b8 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/HashCodeVisitor.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/HashCodeVisitor.java
@@ -23,7 +23,7 @@
*/
public class HashCodeVisitor<T> extends StructuralSpecification<T, HashCodeVisitor<T>> {
- public static <T> int run(T item, StructuralAccept<T> visit) {
+ public static <T> int run(T item, StructuralMapping<T> visit) {
HashCodeVisitor<T> visitor = new HashCodeVisitor<>(item);
visit.apply(visitor);
return visitor.hashCode;
diff --git a/src/main/java/com/android/tools/r8/utils/structural/HashingVisitor.java b/src/main/java/com/android/tools/r8/utils/structural/HashingVisitor.java
index ed0f61e..696c454 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/HashingVisitor.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/HashingVisitor.java
@@ -43,18 +43,18 @@
public abstract void visitDexType(DexType type);
public void visitDexField(DexField field) {
- visit(field, field.getStructuralAccept());
+ visit(field, field.getStructuralMapping());
}
public void visitDexMethod(DexMethod method) {
- visit(method, method.getStructuralAccept());
+ visit(method, method.getStructuralMapping());
}
public void visitDexReference(DexReference reference) {
reference.accept(this::visitDexType, this::visitDexField, this::visitDexMethod);
}
- public abstract <S> void visit(S item, StructuralAccept<S> accept);
+ public abstract <S> void visit(S item, StructuralMapping<S> accept);
@Deprecated
public abstract <S> void visit(S item, BiConsumer<S, Hasher> hasher);
diff --git a/src/main/java/com/android/tools/r8/utils/structural/HashingVisitorWithTypeEquivalence.java b/src/main/java/com/android/tools/r8/utils/structural/HashingVisitorWithTypeEquivalence.java
index 63989f5..ba499a3 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/HashingVisitorWithTypeEquivalence.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/HashingVisitorWithTypeEquivalence.java
@@ -20,7 +20,7 @@
public class HashingVisitorWithTypeEquivalence extends HashingVisitor {
public static <T> void run(
- T item, Hasher hasher, RepresentativeMap map, StructuralAccept<T> accept) {
+ T item, Hasher hasher, RepresentativeMap map, StructuralMapping<T> accept) {
run(item, hasher, map, (i, visitor) -> visitor.visit(i, accept));
}
@@ -73,7 +73,7 @@
}
@Override
- public <S> void visit(S item, StructuralAccept<S> accept) {
+ public <S> void visit(S item, StructuralMapping<S> accept) {
accept.apply(new ItemSpecification<>(item, this));
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/StructuralItem.java b/src/main/java/com/android/tools/r8/utils/structural/StructuralItem.java
index 92542f2..8740299 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/StructuralItem.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/StructuralItem.java
@@ -11,13 +11,13 @@
T self();
- StructuralAccept<T> getStructuralAccept();
+ StructuralMapping<T> getStructuralMapping();
// CompareTo implementation and callbacks.
@FunctionalInterface
interface CompareToAccept<T> {
- void acceptCompareTo(T item1, T item2, CompareToVisitor visitor);
+ int acceptCompareTo(T item1, T item2, CompareToVisitor visitor);
}
/**
@@ -43,8 +43,8 @@
}
/** Default accept for compareTo visitors. Override to change behavior. */
- default void acceptCompareTo(T other, CompareToVisitor visitor) {
- visitor.visit(self(), other, self().getStructuralAccept());
+ default int acceptCompareTo(T other, CompareToVisitor visitor) {
+ return visitor.visit(self(), other, self().getStructuralMapping());
}
// Hashing implemenation and callbacks.
@@ -61,7 +61,7 @@
* ensure that the effect is in place for any HashingVisitor.
*/
default void hash(Hasher hasher) {
- DefaultHashingVisitor.run(self(), hasher, self().getStructuralAccept());
+ DefaultHashingVisitor.run(self(), hasher, StructuralItem::acceptHashing);
}
/** Hashing method to use from tests to avoid having guava types shared between R8 and tests. */
@@ -78,11 +78,11 @@
* ensure that the effect is in place for any HashingVisitor.
*/
default void hashWithTypeEquivalence(Hasher hasher, RepresentativeMap map) {
- HashingVisitorWithTypeEquivalence.run(self(), hasher, map, self().getStructuralAccept());
+ HashingVisitorWithTypeEquivalence.run(self(), hasher, map, StructuralItem::acceptHashing);
}
/** Default accept for hashing visitors. Override to change behavior. */
default void acceptHashing(HashingVisitor visitor) {
- visitor.visit(self(), self().getStructuralAccept());
+ visitor.visit(self(), self().getStructuralMapping());
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/StructuralAccept.java b/src/main/java/com/android/tools/r8/utils/structural/StructuralMapping.java
similarity index 71%
rename from src/main/java/com/android/tools/r8/utils/structural/StructuralAccept.java
rename to src/main/java/com/android/tools/r8/utils/structural/StructuralMapping.java
index ede348f..b9e6bc2 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/StructuralAccept.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/StructuralMapping.java
@@ -4,9 +4,7 @@
package com.android.tools.r8.utils.structural;
/** Mapping of a specification over an item. */
-// TODO(b/171867022): Rename this to StructuralMapping to avoid confusion with the Acceptor and
-// accept classes.
@FunctionalInterface
-public interface StructuralAccept<T> {
+public interface StructuralMapping<T> {
void apply(StructuralSpecification<T, ?> spec);
}
diff --git a/src/main/java/com/android/tools/r8/utils/structural/StructuralSpecification.java b/src/main/java/com/android/tools/r8/utils/structural/StructuralSpecification.java
index ff74111..891fbd7 100644
--- a/src/main/java/com/android/tools/r8/utils/structural/StructuralSpecification.java
+++ b/src/main/java/com/android/tools/r8/utils/structural/StructuralSpecification.java
@@ -66,18 +66,23 @@
public final <S extends StructuralItem<S>> V withConditionalItem(
Predicate<T> predicate, Function<T, S> getter) {
- return withConditionalCustomItem(predicate, getter, S::acceptCompareTo, S::acceptHashing);
+ return withConditionalCustomItem(
+ predicate, getter, StructuralItem::acceptCompareTo, StructuralItem::acceptHashing);
}
public final <S extends StructuralItem<S>> V withItemCollection(
Function<T, Collection<S>> getter) {
return withItemIterator(
- getter.andThen(Collection::iterator), S::acceptCompareTo, S::acceptHashing);
+ getter.andThen(Collection::iterator),
+ StructuralItem::acceptCompareTo,
+ StructuralItem::acceptHashing);
}
public final <S extends StructuralItem<S>> V withItemArray(Function<T, S[]> getter) {
return withItemIterator(
- getter.andThen(a -> Arrays.asList(a).iterator()), S::acceptCompareTo, S::acceptHashing);
+ getter.andThen(a -> Arrays.asList(a).iterator()),
+ StructuralItem::acceptCompareTo,
+ StructuralItem::acceptHashing);
}
/**
diff --git a/src/test/java/com/android/tools/r8/TestBase.java b/src/test/java/com/android/tools/r8/TestBase.java
index a8b5af7..5669af0 100644
--- a/src/test/java/com/android/tools/r8/TestBase.java
+++ b/src/test/java/com/android/tools/r8/TestBase.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.code.Instruction;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.errors.Unreachable;
@@ -1724,4 +1725,35 @@
.compile()
.writeToZip();
}
+
+ protected static CfVersion extractClassFileVersion(byte[] classFileBytes) {
+ class ClassFileVersionExtractor extends ClassVisitor {
+ private int version;
+
+ private ClassFileVersionExtractor() {
+ super(ASM_VERSION);
+ }
+
+ @Override
+ public void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ this.version = version;
+ }
+
+ CfVersion getClassFileVersion() {
+ return CfVersion.fromRaw(version);
+ }
+ }
+
+ ClassReader reader = new ClassReader(classFileBytes);
+ ClassFileVersionExtractor extractor = new ClassFileVersionExtractor();
+ reader.accept(
+ extractor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
+ return extractor.getClassFileVersion();
+ }
}
diff --git a/src/test/java/com/android/tools/r8/cf/stackmap/StackMapVerificationNoFrameForHandlerTest.java b/src/test/java/com/android/tools/r8/cf/stackmap/StackMapVerificationNoFrameForHandlerTest.java
index 625a3dc..7e8c85c 100644
--- a/src/test/java/com/android/tools/r8/cf/stackmap/StackMapVerificationNoFrameForHandlerTest.java
+++ b/src/test/java/com/android/tools/r8/cf/stackmap/StackMapVerificationNoFrameForHandlerTest.java
@@ -76,6 +76,7 @@
: transformer(MainDump.dump(), Reference.classFromClass(Main.class))
.stripFrames("main")
.transform())
+ .addOptionsModification(options -> options.testing.readInputStackMaps = true)
.setMinApi(parameters.getApiLevel())
.compileWithExpectedDiagnostics(this::verifyWarningsRegardingStackMap)
.run(parameters.getRuntime(), Main.class)
@@ -94,6 +95,7 @@
.addKeepMainRule(Main.class)
.setMinApi(parameters.getApiLevel())
.allowDiagnosticWarningMessages(!includeFrameInHandler)
+ .addOptionsModification(options -> options.testing.readInputStackMaps = true)
.compileWithExpectedDiagnostics(this::verifyWarningsRegardingStackMap)
.run(parameters.getRuntime(), Main.class)
.assertSuccessWithOutputLines(EXPECTED_OUTPUT);
diff --git a/src/test/java/com/android/tools/r8/cf/stackmap/SwitchStackFrameFallThroughTest.java b/src/test/java/com/android/tools/r8/cf/stackmap/SwitchStackFrameFallThroughTest.java
new file mode 100644
index 0000000..e552c0a
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/stackmap/SwitchStackFrameFallThroughTest.java
@@ -0,0 +1,177 @@
+// Copyright (c) 2020, 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.cf.stackmap;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import java.io.IOException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+@RunWith(Parameterized.class)
+public class SwitchStackFrameFallThroughTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public SwitchStackFrameFallThroughTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testJvm() throws Exception {
+ assumeTrue(parameters.isCfRuntime());
+ testForJvm()
+ .addProgramClassFileData(SwitchStackFrameFallThroughTest$MainDump.dump())
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("java.io.IOException");
+ }
+
+ @Test
+ public void testD8() throws Exception {
+ assumeTrue(parameters.isDexRuntime());
+ testForD8(parameters.getBackend())
+ .addProgramClassFileData(SwitchStackFrameFallThroughTest$MainDump.dump())
+ .setMinApi(parameters.getApiLevel())
+ .addOptionsModification(options -> options.testing.readInputStackMaps = true)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("java.io.IOException");
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ Throwable throwable = null;
+ switch (args.length) {
+ case 0:
+ throwable = new IOException();
+ break;
+ case 1:
+ throwable = new RuntimeException();
+ break;
+ }
+ System.out.println(throwable.toString());
+ }
+ }
+
+ // The above is roughly the code that below, except we move the switch targets above the switch
+ // and then jump over them. We do this to check the fall-through of the switch.
+ public static class SwitchStackFrameFallThroughTest$MainDump implements Opcodes {
+
+ public static byte[] dump() {
+
+ ClassWriter classWriter = new ClassWriter(0);
+ MethodVisitor methodVisitor;
+
+ classWriter.visit(
+ V1_8,
+ ACC_PUBLIC | ACC_SUPER,
+ "com/android/tools/r8/cf/stackmap/SwitchStackFrameFallThroughTest$Main",
+ null,
+ "java/lang/Object",
+ null);
+
+ classWriter.visitSource("SwitchStackFrameFallThroughTest.java", null);
+
+ classWriter.visitInnerClass(
+ "com/android/tools/r8/cf/stackmap/SwitchStackFrameFallThroughTest$Main",
+ "com/android/tools/r8/cf/stackmap/SwitchStackFrameFallThroughTest",
+ "Main",
+ ACC_PUBLIC | ACC_STATIC);
+
+ {
+ methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ methodVisitor.visitCode();
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ methodVisitor.visitInsn(RETURN);
+ methodVisitor.visitMaxs(1, 1);
+ methodVisitor.visitEnd();
+ }
+ {
+ methodVisitor =
+ classWriter.visitMethod(
+ ACC_PUBLIC | ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+ methodVisitor.visitCode();
+ // This is moved here without a jump.
+
+ Label label0 = new Label();
+ Label label1 = new Label();
+ Label label2 = new Label();
+ Label label3 = new Label();
+
+ methodVisitor.visitJumpInsn(GOTO, label2);
+
+ methodVisitor.visitLabel(label0);
+ methodVisitor.visitFrame(
+ Opcodes.F_FULL,
+ 1,
+ new Object[] {"[Ljava/lang/String;"},
+ 1,
+ new Object[] {Opcodes.NULL});
+ methodVisitor.visitInsn(POP);
+ methodVisitor.visitTypeInsn(NEW, "java/io/IOException");
+ methodVisitor.visitInsn(DUP);
+ methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/io/IOException", "<init>", "()V", false);
+ methodVisitor.visitVarInsn(ASTORE, 1);
+ methodVisitor.visitJumpInsn(GOTO, label3);
+
+ methodVisitor.visitLabel(label1);
+ methodVisitor.visitFrame(
+ Opcodes.F_FULL,
+ 1,
+ new Object[] {"[Ljava/lang/String;"},
+ 1,
+ new Object[] {Opcodes.NULL});
+ methodVisitor.visitInsn(POP);
+ methodVisitor.visitTypeInsn(NEW, "java/lang/RuntimeException");
+ methodVisitor.visitInsn(DUP);
+ methodVisitor.visitMethodInsn(
+ INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "()V", false);
+ methodVisitor.visitVarInsn(ASTORE, 1);
+ methodVisitor.visitJumpInsn(GOTO, label3);
+
+ methodVisitor.visitLabel(label2);
+ methodVisitor.visitFrame(Opcodes.F_FULL, 1, new Object[] {"[Ljava/lang/String;"}, 0, null);
+ methodVisitor.visitInsn(ACONST_NULL);
+ methodVisitor.visitVarInsn(ALOAD, 0);
+ methodVisitor.visitInsn(ARRAYLENGTH);
+ methodVisitor.visitLookupSwitchInsn(label1, new int[] {0, 1}, new Label[] {label0, label1});
+ methodVisitor.visitLabel(label3);
+ methodVisitor.visitFrame(
+ Opcodes.F_FULL,
+ 2,
+ new Object[] {"[Ljava/lang/String;", "java/lang/Throwable"},
+ 0,
+ null);
+ methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+ methodVisitor.visitVarInsn(ALOAD, 1);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/lang/Throwable", "toString", "()Ljava/lang/String;", false);
+ methodVisitor.visitMethodInsn(
+ INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
+ methodVisitor.visitInsn(RETURN);
+ methodVisitor.visitMaxs(4, 2);
+ methodVisitor.visitEnd();
+ }
+ classWriter.visitEnd();
+
+ return classWriter.toByteArray();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
index 3ae4175..c43c289 100644
--- a/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
+++ b/src/test/java/com/android/tools/r8/cfmethodgeneration/MethodGenerationBase.java
@@ -94,6 +94,7 @@
private void readMethodTemplatesInto(CfCodePrinter codePrinter) throws IOException {
InternalOptions options = new InternalOptions();
+ options.testing.readInputStackMaps = true;
JarClassFileReader reader =
new JarClassFileReader(
new JarApplicationReader(options),
diff --git a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileInputCfVersion.java b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileInputCfVersion.java
index 49437ff..6b50afe 100644
--- a/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileInputCfVersion.java
+++ b/src/test/java/com/android/tools/r8/desugar/DesugarToClassFileInputCfVersion.java
@@ -50,18 +50,11 @@
.writeToZip();
if (parameters.getRuntime().isCf()) {
- // Run on the JVM given that Cf version is supported.
- if (cfVersion <= parameters.getRuntime().asCf().getVm().getClassfileVersion()) {
- testForJvm()
- .addProgramFiles(jar)
- .run(parameters.getRuntime(), TestClass.class)
- .assertSuccessWithOutputLines("Hello, world!");
- } else {
- testForJvm()
- .addProgramFiles(jar)
- .run(parameters.getRuntime(), TestClass.class)
- .assertFailureWithErrorThatThrows(UnsupportedClassVersionError.class);
- }
+ // Run on the JVM given that Cf version is supported. When we desugar we now target 1.7 (51).
+ testForJvm()
+ .addProgramFiles(jar)
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines("Hello, world!");
} else {
assert parameters.getRuntime().isDex();
// Convert to DEX without desugaring.
diff --git a/src/test/java/com/android/tools/r8/desugaring/DesugarCfVersion.java b/src/test/java/com/android/tools/r8/desugaring/DesugarCfVersion.java
new file mode 100644
index 0000000..493fe3d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugaring/DesugarCfVersion.java
@@ -0,0 +1,256 @@
+// Copyright (c) 2020, 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.desugaring;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.cf.CfVersion;
+import com.android.tools.r8.utils.ZipUtils;
+import com.google.common.io.ByteStreams;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class DesugarCfVersion extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withCfRuntimes().withAllApiLevelsAlsoForCf().build();
+ }
+
+ public DesugarCfVersion(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ Path zip1 =
+ testForD8(parameters.getBackend())
+ .addProgramClassFileData(hide_1_8)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .writeToZip();
+
+ Path zip2 =
+ testForD8(parameters.getBackend())
+ .addProgramClassFileData(hide_1_7)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .writeToZip();
+
+ boolean canUseStaticAndDefaultInterfaceMethods =
+ parameters
+ .getApiLevel()
+ .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport());
+ byte[] bytes1 = ByteStreams.toByteArray(Files.newInputStream(zip1));
+ byte[] bytes2 = ByteStreams.toByteArray(Files.newInputStream(zip2));
+ if (!canUseStaticAndDefaultInterfaceMethods) {
+ assertArrayEquals(bytes1, bytes2);
+ }
+
+ assertEquals(CfVersion.V1_8, extractClassFileVersion(hide_1_8));
+ assertEquals(CfVersion.V1_7, extractClassFileVersion(hide_1_7));
+ assertEquals(
+ canUseStaticAndDefaultInterfaceMethods ? CfVersion.V1_8 : CfVersion.V1_7,
+ extractClassFileVersion(
+ ZipUtils.readSingleEntry(zip1, "com/google/android/gms/common/internal/Hide.class")));
+ assertEquals(
+ CfVersion.V1_7,
+ extractClassFileVersion(
+ ZipUtils.readSingleEntry(zip2, "com/google/android/gms/common/internal/Hide.class")));
+ }
+
+ /*
+ Class file bytes for:
+
+ public interface com.google.android.gms.common.internal.Hide extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 52
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #1 // com/google/android/gms/common/internal/Hide
+ super_class: #2 // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+ Constant pool:
+ #1 = Class #19 // com/google/android/gms/common/internal/Hide
+ #2 = Class #20 // java/lang/Object
+ #3 = Class #21 // java/lang/annotation/Annotation
+ #4 = Utf8 SourceFile
+ #5 = Utf8 Hide.java
+ #6 = Utf8 RuntimeVisibleAnnotations
+ #7 = Utf8 Ljava/lang/annotation/Target;
+ #8 = Utf8 value
+ #9 = Utf8 Ljava/lang/annotation/ElementType;
+ #10 = Utf8 TYPE
+ #11 = Utf8 FIELD
+ #12 = Utf8 METHOD
+ #13 = Utf8 CONSTRUCTOR
+ #14 = Utf8 PACKAGE
+ #15 = Utf8 Ljava/lang/annotation/Retention;
+ #16 = Utf8 Ljava/lang/annotation/RetentionPolicy;
+ #17 = Utf8 CLASS
+ #18 = Utf8 Ljava/lang/annotation/Documented;
+ #19 = Utf8 com/google/android/gms/common/internal/Hide
+ #20 = Utf8 java/lang/Object
+ #21 = Utf8 java/lang/annotation/Annotation
+ {
+ }
+ SourceFile: "Hide.java"
+ RuntimeVisibleAnnotations:
+ 0: #7(#8=[e#9.#10,e#9.#11,e#9.#12,e#9.#13,e#9.#14])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR,Ljava/lang/annotation/ElementType;.PACKAGE]
+ )
+ 1: #15(#8=e#16.#17)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+ 2: #18()
+ java.lang.annotation.Documented
+
+ */
+
+ private static byte[] hide_1_8 =
+ new byte[] {
+ -54, -2, -70, -66, 0, 0, 0, 52, 0, 22, 7, 0, 19, 7, 0, 20,
+ 7, 0, 21, 1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105, 108, 101,
+ 1, 0, 9, 72, 105, 100, 101, 46, 106, 97, 118, 97, 1, 0, 25, 82,
+ 117, 110, 116, 105, 109, 101, 86, 105, 115, 105, 98, 108, 101, 65, 110, 110,
+ 111, 116, 97, 116, 105, 111, 110, 115, 1, 0, 29, 76, 106, 97, 118, 97,
+ 47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110,
+ 47, 84, 97, 114, 103, 101, 116, 59, 1, 0, 5, 118, 97, 108, 117, 101,
+ 1, 0, 34, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 97, 110,
+ 110, 111, 116, 97, 116, 105, 111, 110, 47, 69, 108, 101, 109, 101, 110, 116,
+ 84, 121, 112, 101, 59, 1, 0, 4, 84, 89, 80, 69, 1, 0, 5, 70,
+ 73, 69, 76, 68, 1, 0, 6, 77, 69, 84, 72, 79, 68, 1, 0, 11,
+ 67, 79, 78, 83, 84, 82, 85, 67, 84, 79, 82, 1, 0, 7, 80, 65,
+ 67, 75, 65, 71, 69, 1, 0, 32, 76, 106, 97, 118, 97, 47, 108, 97,
+ 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 82, 101,
+ 116, 101, 110, 116, 105, 111, 110, 59, 1, 0, 38, 76, 106, 97, 118, 97,
+ 47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110,
+ 47, 82, 101, 116, 101, 110, 116, 105, 111, 110, 80, 111, 108, 105, 99, 121,
+ 59, 1, 0, 5, 67, 76, 65, 83, 83, 1, 0, 33, 76, 106, 97, 118,
+ 97, 47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105, 111,
+ 110, 47, 68, 111, 99, 117, 109, 101, 110, 116, 101, 100, 59, 1, 0, 43,
+ 99, 111, 109, 47, 103, 111, 111, 103, 108, 101, 47, 97, 110, 100, 114, 111,
+ 105, 100, 47, 103, 109, 115, 47, 99, 111, 109, 109, 111, 110, 47, 105, 110,
+ 116, 101, 114, 110, 97, 108, 47, 72, 105, 100, 101, 1, 0, 16, 106, 97,
+ 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 1, 0,
+ 31, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116,
+ 97, 116, 105, 111, 110, 47, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110,
+ 38, 1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 0, 0, 0, 0, 2,
+ 0, 4, 0, 0, 0, 2, 0, 5, 0, 6, 0, 0, 0, 51, 0, 3,
+ 0, 7, 0, 1, 0, 8, 91, 0, 5, 101, 0, 9, 0, 10, 101, 0,
+ 9, 0, 11, 101, 0, 9, 0, 12, 101, 0, 9, 0, 13, 101, 0, 9,
+ 0, 14, 0, 15, 0, 1, 0, 8, 101, 0, 16, 0, 17, 0, 18, 0,
+ 0
+ };
+
+ /*
+ Class file bytes for:
+
+ public interface com.google.android.gms.common.internal.Hide extends java.lang.annotation.Annotation
+ minor version: 0
+ major version: 51
+ flags: (0x2601) ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT, ACC_ANNOTATION
+ this_class: #2 // com/google/android/gms/common/internal/Hide
+ super_class: #4 // java/lang/Object
+ interfaces: 1, fields: 0, methods: 0, attributes: 2
+ Constant pool:
+ #1 = Utf8 com/google/android/gms/common/internal/Hide
+ #2 = Class #1 // com/google/android/gms/common/internal/Hide
+ #3 = Utf8 java/lang/Object
+ #4 = Class #3 // java/lang/Object
+ #5 = Utf8 java/lang/annotation/Annotation
+ #6 = Class #5 // java/lang/annotation/Annotation
+ #7 = Utf8 Hide.java
+ #8 = Utf8 Ljava/lang/annotation/Target;
+ #9 = Utf8 value
+ #10 = Utf8 Ljava/lang/annotation/ElementType;
+ #11 = Utf8 TYPE
+ #12 = Utf8 FIELD
+ #13 = Utf8 METHOD
+ #14 = Utf8 CONSTRUCTOR
+ #15 = Utf8 PACKAGE
+ #16 = Utf8 Ljava/lang/annotation/Retention;
+ #17 = Utf8 Ljava/lang/annotation/RetentionPolicy;
+ #18 = Utf8 CLASS
+ #19 = Utf8 Ljava/lang/annotation/Documented;
+ #20 = Utf8 SourceFile
+ #21 = Utf8 RuntimeVisibleAnnotations
+ {
+ }
+ SourceFile: "Hide.java"
+ RuntimeVisibleAnnotations:
+ 0: #8(#9=[e#10.#11,e#10.#12,e#10.#13,e#10.#14,e#10.#15])
+ java.lang.annotation.Target(
+ value=[Ljava/lang/annotation/ElementType;.TYPE,Ljava/lang/annotation/ElementType;.FIELD,Ljava/lang/annotation/ElementType;.METHOD,Ljava/lang/annotation/ElementType;.CONSTRUCTOR,Ljava/lang/annotation/ElementType;.PACKAGE]
+ )
+ 1: #16(#9=e#17.#18)
+ java.lang.annotation.Retention(
+ value=Ljava/lang/annotation/RetentionPolicy;.CLASS
+ )
+ 2: #19()
+ java.lang.annotation.Documented
+
+ */
+ private static byte[] hide_1_7 =
+ new byte[] {
+ -54, -2, -70, -66, 0, 0, 0, 51, 0, 22, 1, 0, 43, 99, 111, 109,
+ 47, 103, 111, 111, 103, 108, 101, 47, 97, 110, 100, 114, 111, 105, 100, 47,
+ 103, 109, 115, 47, 99, 111, 109, 109, 111, 110, 47, 105, 110, 116, 101, 114,
+ 110, 97, 108, 47, 72, 105, 100, 101, 7, 0, 1, 1, 0, 16, 106, 97,
+ 118, 97, 47, 108, 97, 110, 103, 47, 79, 98, 106, 101, 99, 116, 7, 0,
+ 3, 1, 0, 31, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 97, 110,
+ 110, 111, 116, 97, 116, 105, 111, 110, 47, 65, 110, 110, 111, 116, 97, 116,
+ 105, 111, 110, 7, 0, 5, 1, 0, 9, 72, 105, 100, 101, 46, 106, 97,
+ 118, 97, 1, 0, 29, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47,
+ 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 84, 97, 114, 103, 101,
+ 116, 59, 1, 0, 5, 118, 97, 108, 117, 101, 1, 0, 34, 76, 106, 97,
+ 118, 97, 47, 108, 97, 110, 103, 47, 97, 110, 110, 111, 116, 97, 116, 105,
+ 111, 110, 47, 69, 108, 101, 109, 101, 110, 116, 84, 121, 112, 101, 59, 1,
+ 0, 4, 84, 89, 80, 69, 1, 0, 5, 70, 73, 69, 76, 68, 1, 0,
+ 6, 77, 69, 84, 72, 79, 68, 1, 0, 11, 67, 79, 78, 83, 84, 82,
+ 85, 67, 84, 79, 82, 1, 0, 7, 80, 65, 67, 75, 65, 71, 69, 1,
+ 0, 32, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 97, 110, 110,
+ 111, 116, 97, 116, 105, 111, 110, 47, 82, 101, 116, 101, 110, 116, 105, 111,
+ 110, 59, 1, 0, 38, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47,
+ 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 82, 101, 116, 101, 110,
+ 116, 105, 111, 110, 80, 111, 108, 105, 99, 121, 59, 1, 0, 5, 67, 76,
+ 65, 83, 83, 1, 0, 33, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103,
+ 47, 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 47, 68, 111, 99, 117,
+ 109, 101, 110, 116, 101, 100, 59, 1, 0, 10, 83, 111, 117, 114, 99, 101,
+ 70, 105, 108, 101, 1, 0, 25, 82, 117, 110, 116, 105, 109, 101, 86, 105,
+ 115, 105, 98, 108, 101, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 115,
+ 38, 1, 0, 2, 0, 4, 0, 1, 0, 6, 0, 0, 0, 0, 0, 2,
+ 0, 20, 0, 0, 0, 2, 0, 7, 0, 21, 0, 0, 0, 51, 0, 3,
+ 0, 8, 0, 1, 0, 9, 91, 0, 5, 101, 0, 10, 0, 11, 101, 0,
+ 10, 0, 12, 101, 0, 10, 0, 13, 101, 0, 10, 0, 14, 101, 0, 10,
+ 0, 15, 0, 16, 0, 1, 0, 9, 101, 0, 17, 0, 18, 0, 19, 0,
+ 0
+ };
+
+ // Code for generating the lists above.
+ public static void main(String[] args) throws IOException {
+ Path file = Paths.get(args[0]);
+ byte[] content = ByteStreams.toByteArray(Files.newInputStream(file));
+ final int bytesPerLine = 16;
+ for (int i = 0; i < content.length; i += bytesPerLine) {
+ for (int j = 0; j < bytesPerLine && i + j < content.length; j++) {
+ System.out.print(content[i + j] + ", ");
+ }
+ System.out.println();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PrivateOverridePublicizerDevirtualizerTest.java b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PrivateOverridePublicizerDevirtualizerTest.java
new file mode 100644
index 0000000..bef0cd5
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/devirtualize/PrivateOverridePublicizerDevirtualizerTest.java
@@ -0,0 +1,116 @@
+// Copyright (c) 2020, 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.optimize.devirtualize;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.NoVerticalClassMerging;
+import com.android.tools.r8.R8TestRunResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+// This is a reproduction of b/173812804.
+@RunWith(Parameterized.class)
+public class PrivateOverridePublicizerDevirtualizerTest extends TestBase {
+
+ private final TestParameters parameters;
+ private final String[] EXPECTED = new String[] {"A::foo", "B::foo"};
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public PrivateOverridePublicizerDevirtualizerTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testRuntime() throws Exception {
+ testForRuntime(parameters)
+ .addInnerClasses(PrivateOverridePublicizerDevirtualizerTest.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ R8TestRunResult runResult =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(PrivateOverridePublicizerDevirtualizerTest.class)
+ .enableInliningAnnotations()
+ .enableNoVerticalClassMergingAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .addKeepMainRule(Main.class)
+ .allowAccessModification()
+ .noMinification()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(
+ inspector -> {
+ ClassSubject classA = inspector.clazz(A.class);
+ assertThat(classA, isPresent());
+ MethodSubject fooA = classA.uniqueMethodWithName("foo");
+ // TODO(b/173812804): This should not be removed.
+ assertThat(fooA, not(isPresent()));
+ })
+ .run(parameters.getRuntime(), Main.class);
+ if (parameters.isDexRuntime()) {
+ // TODO(b/173812804): This should not fail verification
+ runResult.assertFailureWithErrorThatThrows(VerifyError.class);
+ } else {
+ // TODO(b/173812804): This should have been A::foo, B::foo.
+ runResult.assertSuccessWithOutputLines("B::foo", "B::foo");
+ }
+ }
+
+ @NeverClassInline
+ @NoVerticalClassMerging
+ public static class A {
+ @NeverInline
+ private void foo() {
+ System.out.println("A::foo"); // <-- this is made public by the publicizer
+ }
+
+ public void callFoo() {
+ foo();
+ }
+ }
+
+ @NeverClassInline
+ public static class B extends A {
+ @NeverInline
+ private void foo() {
+ System.out.println("B::foo");
+ }
+
+ @Override
+ @NeverInline
+ public void callFoo() {
+ // We end up inlining A::callFoo, and then, because the call to A::foo is public, we end up
+ // target B::foo in the virtualizer.
+ super.callFoo();
+ foo();
+ }
+ }
+
+ public static class Main {
+
+ public static void main(String[] args) {
+ new B().callFoo();
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/fields/FieldAnalysisTest.java b/src/test/java/com/android/tools/r8/ir/optimize/fields/FieldAnalysisTest.java
new file mode 100644
index 0000000..4089f0e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/fields/FieldAnalysisTest.java
@@ -0,0 +1,118 @@
+// Copyright (c) 2020, 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.optimize.fields;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.StringUtils;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class FieldAnalysisTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<Object[]> data() {
+ return buildParameters(getTestParameters().withAllRuntimesAndApiLevels().build());
+ }
+
+ public FieldAnalysisTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ private static String EXPECTED_RESULT = StringUtils.lines("42", "7", "21", "42", "49", "28");
+
+ @Test
+ public void testD8AndJava() throws Exception {
+ testForRuntime(parameters.getRuntime(), parameters.getApiLevel())
+ .addInnerClasses(FieldAnalysisTest.class)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+
+ @Test
+ public void testR8() throws Exception {
+ testForR8(parameters.getBackend())
+ .setMinApi(parameters.getApiLevel())
+ .addInnerClasses(FieldAnalysisTest.class)
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .enableNeverClassInliningAnnotations()
+ .compile()
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutput(EXPECTED_RESULT);
+ }
+
+ @NeverClassInline
+ static class A {
+ int f = 42;
+
+ @NeverInline
+ A() {}
+
+ @NeverInline
+ A(int f) {
+ this.f = f;
+ }
+ }
+
+ @NeverClassInline
+ static class B extends A {
+ @NeverInline
+ B() {
+ super();
+ }
+
+ @NeverInline
+ B(int f) {
+ this();
+ this.f = f;
+ }
+
+ @NeverInline
+ B(int unused, int f) {
+ super(unused);
+ this.f = f;
+ }
+ }
+
+ @NeverClassInline
+ static class C extends A {
+ @NeverInline
+ C() {
+ super();
+ }
+
+ @NeverInline
+ C(int f) {
+ this();
+ this.f = f + this.f;
+ }
+
+ @NeverInline
+ C(int unused, int f) {
+ super(unused);
+ this.f = f + this.f;
+ }
+ }
+
+ static class Main {
+ public static void main(String[] args) {
+ System.out.println(new B().f);
+ System.out.println(new B(7).f);
+ System.out.println(new B(7, 21).f);
+
+ System.out.println(new C().f);
+ System.out.println(new C(7).f);
+ System.out.println(new C(7, 21).f);
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapInvalidInitTest.java b/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapInvalidInitTest.java
new file mode 100644
index 0000000..c8d8086
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapInvalidInitTest.java
@@ -0,0 +1,113 @@
+// Copyright (c) 2020, 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.optimize.switches;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.NeverClassInline;
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class SwitchMapInvalidInitTest extends TestBase {
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
+ public SwitchMapInvalidInitTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void testInvalidInitSwitchMap() throws Exception {
+ testForR8(parameters.getBackend())
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .addInnerClasses(SwitchMapInvalidInitTest.class)
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .inspect(this::assertNoSwitchMap)
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines("init", "init", "init", "a", "b", "a", "b");
+ }
+
+ private void assertNoSwitchMap(CodeInspector codeInspector) {
+ // Main and the 2 enum classes.
+ assertEquals(3, codeInspector.allClasses().size());
+ assertThat(codeInspector.clazz(Main.class), isPresent());
+ assertThat(codeInspector.clazz(MyEnum1.class), isPresent());
+ assertThat(codeInspector.clazz(MyEnum2.class), isPresent());
+ }
+
+ @NeverClassInline
+ enum MyEnum1 {
+ // The System call cannot be traced, therefore enum field can be read before being set.
+ A(System.currentTimeMillis()),
+ B(0),
+ C(1);
+ private final long time;
+
+ MyEnum1(long time) {
+ this.time = time;
+ }
+ }
+
+ @NeverClassInline
+ enum MyEnum2 {
+ A,
+ B,
+ C;
+
+ MyEnum2() {
+ // The System call cannot be traced, therefore any enum field can be read before being set.
+ System.out.println("init");
+ }
+ }
+
+ public static class Main {
+ public static void main(String[] args) {
+ switch2(MyEnum2.A);
+ switch2(MyEnum2.B);
+ switch2(MyEnum2.C);
+ switch1(MyEnum1.A);
+ switch1(MyEnum1.B);
+ switch1(MyEnum1.C);
+ }
+
+ @NeverInline
+ private static void switch1(MyEnum1 e) {
+ switch (e) {
+ case A:
+ System.out.println("a");
+ break;
+ case B:
+ System.out.println("b");
+ break;
+ }
+ }
+
+ @NeverInline
+ private static void switch2(MyEnum2 e) {
+ switch (e) {
+ case A:
+ System.out.println("a");
+ break;
+ case B:
+ System.out.println("b");
+ break;
+ }
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapWithEnumDependencyTest.java b/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapWithEnumDependencyTest.java
new file mode 100644
index 0000000..14d5f18
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapWithEnumDependencyTest.java
@@ -0,0 +1,89 @@
+// Copyright (c) 2020, 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.optimize.switches;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class SwitchMapWithEnumDependencyTest extends TestBase {
+
+ private final TestParameters parameters;
+ private static final String[] EXPECTED_RESULT = {"AD", "SB", "BE", "SC", "CF"};
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public SwitchMapWithEnumDependencyTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ R8TestCompileResult compile =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(SwitchMapWithEnumDependencyTest.class)
+ .addKeepMainRule(TestClass.class)
+ .noMinification()
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile();
+ compile
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines(EXPECTED_RESULT);
+ }
+
+ static class TestClass {
+ public static void main(String[] args) {
+ switchMethod();
+ }
+
+ @NeverInline
+ private static void switchMethod() {
+ for (MyEnum value : MyEnum.values()) {
+ switch (value) {
+ case B:
+ System.out.println("SB");
+ break;
+ case C:
+ System.out.println("SC");
+ break;
+ }
+ System.out.println(value.toString());
+ }
+ }
+ }
+
+ enum MyEnum {
+ A(MyEnumDependency.D),
+ B(MyEnumDependency.E),
+ C(MyEnumDependency.F);
+
+ final MyEnumDependency dependency;
+
+ MyEnum(MyEnumDependency dependency) {
+ this.dependency = dependency;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + dependency.toString();
+ }
+ }
+
+ enum MyEnumDependency {
+ D,
+ E,
+ F
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapWithSubtypesTest.java b/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapWithSubtypesTest.java
new file mode 100644
index 0000000..7bc82e8
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/switches/SwitchMapWithSubtypesTest.java
@@ -0,0 +1,124 @@
+// Copyright (c) 2020, 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.optimize.switches;
+
+import com.android.tools.r8.NeverInline;
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class SwitchMapWithSubtypesTest extends TestBase {
+
+ private final TestParameters parameters;
+ private static final String[] EXPECTED_RESULT = {
+ "ta", "SB", "tb", "SC", "C", "D", "tatrue", "SB", "tbtrue", "SC", "Cfalse", "Dfalse"
+ };
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withAllRuntimesAndApiLevels().build();
+ }
+
+ public SwitchMapWithSubtypesTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ @Test
+ public void test() throws Exception {
+ R8TestCompileResult compile =
+ testForR8(parameters.getBackend())
+ .addInnerClasses(SwitchMapWithSubtypesTest.class)
+ .addKeepMainRule(TestClass.class)
+ .noMinification()
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile();
+ compile
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertSuccessWithOutputLines(EXPECTED_RESULT);
+ }
+
+ static class TestClass {
+ public static void main(String[] args) {
+ switchMethod();
+ switchMethodSubtype();
+ }
+
+ @NeverInline
+ private static void switchMethod() {
+ for (MyEnum value : MyEnum.values()) {
+ switch (value) {
+ case B:
+ System.out.println("SB");
+ break;
+ case C:
+ System.out.println("SC");
+ break;
+ }
+ System.out.println(value.toString());
+ }
+ }
+
+ @NeverInline
+ private static void switchMethodSubtype() {
+ for (MyEnumSubtype value : MyEnumSubtype.values()) {
+ switch (value) {
+ case B:
+ System.out.println("SB");
+ break;
+ case C:
+ System.out.println("SC");
+ break;
+ }
+ System.out.println(value.toString() + value.subType);
+ }
+ }
+ }
+
+ enum MyEnum {
+ A {
+ @Override
+ public String toString() {
+ return "ta";
+ }
+ },
+ B {
+ @Override
+ public String toString() {
+ return "tb";
+ }
+ },
+ C,
+ D;
+ }
+
+ enum MyEnumSubtype {
+ A(true) {
+ @Override
+ public String toString() {
+ return "ta";
+ }
+ },
+ B(true) {
+ @Override
+ public String toString() {
+ return "tb";
+ }
+ },
+ C(false),
+ D(false);
+
+ final boolean subType;
+
+ MyEnumSubtype(boolean fieldSet) {
+ this.subType = fieldSet;
+ }
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryMethodTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryMethodTest.java
index 9eefd15..58155cc 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryMethodTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryMethodTest.java
@@ -4,10 +4,11 @@
package com.android.tools.r8.repackage;
+import static org.hamcrest.MatcherAssert.assertThat;
+
import com.android.tools.r8.NeverInline;
-import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
-import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -34,23 +35,23 @@
@Test
public void testR8() throws Exception {
- R8TestRunResult runResult =
- testForR8(parameters.getBackend())
- .addLibraryClasses(Library.class)
- .addDefaultRuntimeLibrary(parameters)
- .addProgramClasses(Program.class, Main.class)
- .apply(this::configureRepackaging)
- .addKeepMainRule(Main.class)
- .enableInliningAnnotations()
- .setMinApi(parameters.getApiLevel())
- .compile()
- .addRunClasspathFiles(buildOnDexRuntime(parameters, Library.class))
- .run(parameters.getRuntime(), Main.class);
- if (parameters.isDexRuntime() && parameters.getDexRuntimeVersion() == Version.V8_1_0) {
- runResult.assertSuccessWithOutputLines(EXPECTED);
- } else {
- runResult.assertFailureWithErrorThatThrows(IllegalAccessError.class);
- }
+ testForR8(parameters.getBackend())
+ .addLibraryClasses(Library.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .addProgramClasses(Program.class, Main.class)
+ .apply(this::configureRepackaging)
+ .addKeepMainRule(Main.class)
+ .enableInliningAnnotations()
+ .setMinApi(parameters.getApiLevel())
+ .compile()
+ .addRunClasspathFiles(buildOnDexRuntime(parameters, Library.class))
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED)
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ assertThat(Program.class, isNotRepackaged(inspector));
}
public static class Library {
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryOverrideTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryOverrideTest.java
index 7773fef..ce1c039 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryOverrideTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryOverrideTest.java
@@ -4,9 +4,11 @@
package com.android.tools.r8.repackage;
+import static org.hamcrest.MatcherAssert.assertThat;
+
import com.android.tools.r8.NeverClassInline;
-import com.android.tools.r8.R8TestRunResult;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -33,23 +35,23 @@
@Test
public void testR8() throws Exception {
- R8TestRunResult runResult =
- testForR8(parameters.getBackend())
- .addLibraryClasses(Library.class)
- .addDefaultRuntimeLibrary(parameters)
- .addProgramClasses(Program.class, Main.class)
- .apply(this::configureRepackaging)
- .addKeepMainRule(Main.class)
- .setMinApi(parameters.getApiLevel())
- .enableNeverClassInliningAnnotations()
- .compile()
- .addRunClasspathFiles(buildOnDexRuntime(parameters, Library.class))
- .run(parameters.getRuntime(), Main.class);
- if (parameters.isDexRuntime() && parameters.getDexRuntimeVersion().isDalvik()) {
- runResult.assertSuccessWithOutputLines(EXPECTED);
- } else {
- runResult.assertSuccessWithOutputLines("Library::foo");
- }
+ testForR8(parameters.getBackend())
+ .addLibraryClasses(Library.class)
+ .addDefaultRuntimeLibrary(parameters)
+ .addProgramClasses(Program.class, Main.class)
+ .apply(this::configureRepackaging)
+ .addKeepMainRule(Main.class)
+ .setMinApi(parameters.getApiLevel())
+ .enableNeverClassInliningAnnotations()
+ .compile()
+ .addRunClasspathFiles(buildOnDexRuntime(parameters, Library.class))
+ .run(parameters.getRuntime(), Main.class)
+ .assertSuccessWithOutputLines(EXPECTED)
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ assertThat(Program.class, isNotRepackaged(inspector));
}
public static class Library {
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryTypeTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryTypeTest.java
index 1a35ded..90939fb 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryTypeTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithPackagePrivateLibraryTypeTest.java
@@ -4,9 +4,12 @@
package com.android.tools.r8.repackage;
+import static org.hamcrest.MatcherAssert.assertThat;
+
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -49,7 +52,13 @@
.setMinApi(parameters.getApiLevel())
.addRunClasspathFiles(buildOnDexRuntime(parameters, Library.class, LibraryI.class))
.run(parameters.getRuntime(), Main.class)
- .assertFailureWithErrorThatThrows(IllegalAccessError.class);
+ .assertSuccessWithOutputLines(EXPECTED)
+ .inspect(this::inspect);
+ }
+
+ private void inspect(CodeInspector inspector) {
+ assertThat(Program.class, isNotRepackaged(inspector));
+ assertThat(ProgramSub.class, isNotRepackaged(inspector));
}
static class Library {}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/HorizontallyMergedClassesInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/HorizontallyMergedClassesInspector.java
index 0d99817..37dbe19 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/HorizontallyMergedClassesInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/HorizontallyMergedClassesInspector.java
@@ -47,7 +47,8 @@
}
public HorizontallyMergedClassesInspector assertClassNotMerged(Class<?> clazz) {
- assertFalse(horizontallyMergedClasses.hasBeenMerged(toDexType(clazz, dexItemFactory)));
+ assertFalse(
+ horizontallyMergedClasses.hasBeenMergedIntoDifferentType(toDexType(clazz, dexItemFactory)));
return this;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/HorizontallyMergedLambdaClassesInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/HorizontallyMergedLambdaClassesInspector.java
index 421b54a..619b415 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/HorizontallyMergedLambdaClassesInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/HorizontallyMergedLambdaClassesInspector.java
@@ -27,7 +27,9 @@
}
public HorizontallyMergedLambdaClassesInspector assertMerged(Class<?> clazz) {
- assertTrue(horizontallyMergedLambdaClasses.hasBeenMerged(toDexType(clazz, dexItemFactory)));
+ assertTrue(
+ horizontallyMergedLambdaClasses.hasBeenMergedIntoDifferentType(
+ toDexType(clazz, dexItemFactory)));
return this;
}
@@ -39,7 +41,9 @@
}
public HorizontallyMergedLambdaClassesInspector assertClassNotMerged(Class<?> clazz) {
- assertFalse(horizontallyMergedLambdaClasses.hasBeenMerged(toDexType(clazz, dexItemFactory)));
+ assertFalse(
+ horizontallyMergedLambdaClasses.hasBeenMergedIntoDifferentType(
+ toDexType(clazz, dexItemFactory)));
return this;
}
diff --git a/src/test/java/com/android/tools/r8/utils/structural/StructuralItemsCustomOrderTest.java b/src/test/java/com/android/tools/r8/utils/structural/StructuralItemsCustomOrderTest.java
index cfea69c..679200c 100644
--- a/src/test/java/com/android/tools/r8/utils/structural/StructuralItemsCustomOrderTest.java
+++ b/src/test/java/com/android/tools/r8/utils/structural/StructuralItemsCustomOrderTest.java
@@ -98,7 +98,7 @@
private final int x;
private final B b;
- private static void accept(StructuralSpecification<A, ?> spec) {
+ private static void specify(StructuralSpecification<A, ?> spec) {
spec.withInt(a -> a.x).withItem(a -> a.b);
}
@@ -108,8 +108,8 @@
}
@Override
- public StructuralAccept<A> getStructuralAccept() {
- return A::accept;
+ public StructuralMapping<A> getStructuralMapping() {
+ return A::specify;
}
@Override
@@ -124,7 +124,7 @@
@Override
public final int hashCode() {
- return HashCodeVisitor.run(this, A::accept);
+ return HashCodeVisitor.run(this, A::specify);
}
}
@@ -132,7 +132,7 @@
private final int y;
- private static void accept(StructuralSpecification<B, ?> spec) {
+ private static void specify(StructuralSpecification<B, ?> spec) {
spec.withInt(b -> b.y);
}
@@ -141,8 +141,8 @@
}
@Override
- public StructuralAccept<B> getStructuralAccept() {
- return B::accept;
+ public StructuralMapping<B> getStructuralMapping() {
+ return B::specify;
}
@Override
@@ -157,14 +157,14 @@
@Override
public final int hashCode() {
- return HashCodeVisitor.run(this, B::accept);
+ return HashCodeVisitor.run(this, B::specify);
}
// Override allowing a change to the order of any type of compare-to visitation, e.g., with
// and without a type equivalence map.
@Override
- public void acceptCompareTo(B other, CompareToVisitor visitor) {
- visitor.visit(other, this, B::accept);
+ public int acceptCompareTo(B other, CompareToVisitor visitor) {
+ return visitor.visit(other, this, B::specify);
}
}
}
diff --git a/src/test/java/com/android/tools/r8/utils/structural/StructuralItemsTest.java b/src/test/java/com/android/tools/r8/utils/structural/StructuralItemsTest.java
index 64481c3..b9580ed 100644
--- a/src/test/java/com/android/tools/r8/utils/structural/StructuralItemsTest.java
+++ b/src/test/java/com/android/tools/r8/utils/structural/StructuralItemsTest.java
@@ -117,7 +117,7 @@
private final int x;
private final B b;
- private static void accept(StructuralSpecification<A, ?> spec) {
+ private static void specify(StructuralSpecification<A, ?> spec) {
spec.withInt(a -> a.x).withItem(a -> a.b);
}
@@ -127,8 +127,8 @@
}
@Override
- public StructuralAccept<A> getStructuralAccept() {
- return A::accept;
+ public StructuralMapping<A> getStructuralMapping() {
+ return A::specify;
}
@Override
@@ -143,7 +143,7 @@
@Override
public int hashCode() {
- return HashCodeVisitor.run(this, A::accept);
+ return HashCodeVisitor.run(this, A::specify);
}
}
@@ -151,7 +151,7 @@
private final int y;
- private static void accept(StructuralSpecification<B, ?> spec) {
+ private static void specify(StructuralSpecification<B, ?> spec) {
spec.withInt(b -> b.y);
}
@@ -160,8 +160,8 @@
}
@Override
- public StructuralAccept<B> getStructuralAccept() {
- return B::accept;
+ public StructuralMapping<B> getStructuralMapping() {
+ return B::specify;
}
@Override
@@ -176,7 +176,7 @@
@Override
public int hashCode() {
- return HashCodeVisitor.run(this, B::accept);
+ return HashCodeVisitor.run(this, B::specify);
}
}
}
diff --git a/tools/compiledump.py b/tools/compiledump.py
index 5c818d6..ebf3371 100755
--- a/tools/compiledump.py
+++ b/tools/compiledump.py
@@ -47,6 +47,11 @@
help='Path to an R8 jar.',
default=None)
parser.add_argument(
+ '-override',
+ help='Do not override any extracted dump in temp-dir',
+ default=False,
+ action='store_true')
+ parser.add_argument(
'--nolib',
help='Use the non-lib distribution (default uses the lib distribution)',
default=False,
@@ -168,7 +173,13 @@
return Dump(args.dump)
dump_file = zipfile.ZipFile(os.path.abspath(args.dump), 'r')
with utils.ChangedWorkingDirectory(temp):
- dump_file.extractall()
+ if args.override or not os.path.isfile(
+ os.path.join(temp, 'proguard.config')):
+ print("Extracting into: %s" % temp)
+ dump_file.extractall()
+ if not os.path.isfile(os.path.join(temp, 'proguard.config')):
+ error("Did not extract into %s. Either the zip file is invalid or the "
+ "dump is missing files" % temp)
return Dump(temp)
def determine_build_properties(args, dump):
diff --git a/tools/run_on_app_dump.py b/tools/run_on_app_dump.py
index 0ceb3b0b..0d48887 100755
--- a/tools/run_on_app_dump.py
+++ b/tools/run_on_app_dump.py
@@ -319,8 +319,6 @@
'url': 'https://github.com/chrisbanes/tivi',
'revision': '8e2ddd8fe2d343264a66aa1ef8acbd4cc587e8ce',
'folder': 'tivi',
- # TODO(b/173974110): Enable recompilation.
- 'skip_recompilation': True,
}),
App({
'id': 'com.keylesspalace.tusky',