Only consider relevant instruction desugarings for given instruction opcode
This CL creates a dense array where the element at index i is an array containing all relevant CF instruction desugarings for instructions with opcode i.
Bug: b/378464445
Change-Id: I54b36eb428affff0a077078e29251ec6128e3cbe
diff --git a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
index e16115e..62256b5 100644
--- a/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfCodePrinter.java
@@ -588,7 +588,7 @@
@Override
public void print(CfFieldInstruction insn) {
- switch (insn.getOpcode()) {
+ switch (insn.getAsmOpcode()) {
case Opcodes.GETFIELD:
printNewInstruction("CfInstanceFieldRead", dexField(insn.getField()));
break;
diff --git a/src/main/java/com/android/tools/r8/cf/CfPrinter.java b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
index 6341c03..fac5344 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -505,7 +505,7 @@
public void print(CfFieldInstruction insn) {
indent();
- switch (insn.getOpcode()) {
+ switch (insn.getAsmOpcode()) {
case Opcodes.GETFIELD:
builder.append("getfield ");
break;
@@ -519,7 +519,7 @@
builder.append("putstatic ");
break;
default:
- throw new Unreachable("Unexpected field-instruction opcode " + insn.getOpcode());
+ throw new Unreachable("Unexpected field-instruction opcode " + insn.getAsmOpcode());
}
appendField(insn.getField());
builder.append(' ');
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 e9c6f6b..766926a 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
@@ -46,11 +46,6 @@
}
@Override
- public int getCompareToId() {
- return getAsmOpcode();
- }
-
- @Override
public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
@@ -116,6 +111,7 @@
}
}
+ @Override
public int getAsmOpcode() {
return getAsmOpcode(opcode, type);
}
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 fd9586f..c8a886d 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
@@ -45,7 +45,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.ARRAYLENGTH;
}
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 a0662ad..c7f5181 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
@@ -31,11 +31,7 @@
}
@Override
- public int getCompareToId() {
- return getLoadType();
- }
-
- private int getLoadType() {
+ public int getAsmOpcode() {
switch (getType()) {
case OBJECT:
return Opcodes.AALOAD;
@@ -69,7 +65,7 @@
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- visitor.visitInsn(getLoadType());
+ visitor.visitInsn(getAsmOpcode());
}
@Override
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 f7cb0c5..461c6fc 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
@@ -29,21 +29,7 @@
}
@Override
- public int getCompareToId() {
- return getStoreType();
- }
-
- @Override
- public boolean isArrayStore() {
- return true;
- }
-
- @Override
- public CfArrayStore asArrayStore() {
- return this;
- }
-
- private int getStoreType() {
+ public int getAsmOpcode() {
switch (getType()) {
case OBJECT:
return Opcodes.AASTORE;
@@ -67,6 +53,16 @@
}
@Override
+ public boolean isArrayStore() {
+ return true;
+ }
+
+ @Override
+ public CfArrayStore asArrayStore() {
+ return this;
+ }
+
+ @Override
public void write(
AppView<?> appView,
ProgramMethod context,
@@ -77,7 +73,7 @@
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- visitor.visitInsn(getStoreType());
+ visitor.visitInsn(getAsmOpcode());
}
@Override
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 9e23bd0..915e0e9 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
@@ -66,7 +66,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.CHECKCAST;
}
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 a18c05a..490b860 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
@@ -43,11 +43,6 @@
}
@Override
- public int getCompareToId() {
- return getAsmOpcode();
- }
-
- @Override
public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
@@ -83,6 +78,7 @@
}
}
+ @Override
public int getAsmOpcode() {
switch (type) {
case LONG:
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 0d0838e..1d89b7d 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
@@ -59,6 +59,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.CONST_CLASS_COMPARE_ID;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
index ed3a275..963df0f 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstDynamic.java
@@ -84,6 +84,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.CONST_DYNAMIC_COMPARE_ID;
}
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 25cb808..2379d5a 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
@@ -39,6 +39,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.CONST_METHOD_HANDLE_COMPARE_ID;
}
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 2f0fb30..17a2b28 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
@@ -39,6 +39,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.CONST_METHOD_TYPE_COMPARE_ID;
}
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 09d9f3c..1e999ca 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
@@ -45,7 +45,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.ACONST_NULL;
}
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 9246c77..2ea3658 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
@@ -41,6 +41,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.CONST_NUMBER_COMPARE_ID;
}
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 064ee4c..9f49657 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
@@ -31,6 +31,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.CONST_STRING_COMPARE_ID;
}
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 6280303..f4509ed 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
@@ -38,6 +38,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.CONST_STRING_DEX_ITEM_COMPARE_ID;
}
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 9d91db7..2ec5bab 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
@@ -27,7 +27,7 @@
private final DexField declaringField;
private static void specify(StructuralSpecification<CfFieldInstruction, ?> spec) {
- spec.withInt(CfFieldInstruction::getOpcode)
+ spec.withInt(CfFieldInstruction::getAsmOpcode)
.withItem(CfFieldInstruction::getField)
.withItem(CfFieldInstruction::getDeclaringField);
}
@@ -66,13 +66,6 @@
return declaringField;
}
- public abstract int getOpcode();
-
- @Override
- public int getCompareToId() {
- return getOpcode();
- }
-
@Override
public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
@@ -112,7 +105,7 @@
String owner = namingLens.lookupInternalName(rewrittenField.holder);
String name = namingLens.lookupName(rewrittenDeclaringField).toString();
String desc = namingLens.lookupDescriptor(rewrittenField.type).toString();
- visitor.visitFieldInsn(getOpcode(), owner, name, desc);
+ visitor.visitFieldInsn(getAsmOpcode(), owner, name, desc);
}
@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 0dedc1d..54347a9 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
@@ -60,6 +60,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.FRAME_COMPARE_ID;
}
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 cabbeeb..2921cd8 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
@@ -33,7 +33,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.GOTO;
}
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 0ac4689..3f52416 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
@@ -34,7 +34,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return getOpcode();
}
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 24fc552..2573b67 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
@@ -34,7 +34,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return getOpcode();
}
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 533657e..e5ac422 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
@@ -41,7 +41,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.IINC;
}
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 4fa09ff..c747f57 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
@@ -45,6 +45,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.CONST_CLASS_COMPARE_ID;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstanceFieldRead.java b/src/main/java/com/android/tools/r8/cf/code/CfInstanceFieldRead.java
index 1a7c2af..69a5090 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstanceFieldRead.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstanceFieldRead.java
@@ -29,7 +29,7 @@
}
@Override
- public int getOpcode() {
+ public int getAsmOpcode() {
return Opcodes.GETFIELD;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInstanceFieldWrite.java b/src/main/java/com/android/tools/r8/cf/code/CfInstanceFieldWrite.java
index 1f8e193..908a999 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInstanceFieldWrite.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInstanceFieldWrite.java
@@ -37,7 +37,7 @@
}
@Override
- public int getOpcode() {
+ public int getAsmOpcode() {
return Opcodes.PUTFIELD;
}
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 da879bd..aad5efb 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
@@ -55,7 +55,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.INSTANCEOF;
}
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 9ee017e..f3f4fe6 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
@@ -47,6 +47,17 @@
public abstract void print(CfPrinter printer);
/**
+ * Returns the corresponding ASM opcode, or -1 if the given CF instruction is a synthetic kind
+ * that does not have an ASM opcode.
+ */
+ public abstract int getAsmOpcode();
+
+ /** Returns false for synthetic CF instructions that do not have an ASM opcode. */
+ public boolean hasAsmOpcode() {
+ return true;
+ }
+
+ /**
* Base compare id for each instruction.
*
* <p>The id is required to be unique for each instruction class and define a order on
@@ -55,7 +66,10 @@
* instruction is not represented externally, some non-overlapping ID defined in {@code
* CfCompareHelper}.
*/
- public abstract int getCompareToId();
+ public int getCompareToId() {
+ assert hasAsmOpcode();
+ return getAsmOpcode();
+ }
/**
* Compare two instructions with the same compare id.
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 fc2e576..292983c 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
@@ -57,7 +57,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return getOpcode();
}
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 8e39bb9..a1fed4c 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
@@ -57,7 +57,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.INVOKEDYNAMIC;
}
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 d0efa3c..73f9ca1 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
@@ -21,6 +21,7 @@
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.HashingVisitor;
import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
public class CfJsrRet extends CfInstruction {
@@ -36,8 +37,8 @@
}
@Override
- public int getCompareToId() {
- throw error();
+ public int getAsmOpcode() {
+ return Opcodes.RET;
}
@Override
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 008b905..6e79310 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
@@ -34,6 +34,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.LABEL_COMPARE_ID;
}
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 0af1153..30c14b8 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
@@ -38,7 +38,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return 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 97c4dce..0cef4f5 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
@@ -48,11 +48,6 @@
}
@Override
- public int getCompareToId() {
- return getAsmOpcode();
- }
-
- @Override
public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
@@ -102,6 +97,7 @@
}
}
+ @Override
public int getAsmOpcode() {
return getAsmOpcode(opcode, type);
}
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 6821e61..5f08b41 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
@@ -37,11 +37,6 @@
}
@Override
- public int getCompareToId() {
- return getAsmOpcode();
- }
-
- @Override
public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
@@ -71,7 +66,8 @@
return 1;
}
- private int getAsmOpcode() {
+ @Override
+ public int getAsmOpcode() {
return type == MonitorType.ENTER ? Opcodes.MONITORENTER : Opcodes.MONITOREXIT;
}
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 449bdcb..c8081cf 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
@@ -67,7 +67,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.MULTIANEWARRAY;
}
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 9b047f8..c93606b 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
@@ -38,11 +38,6 @@
}
@Override
- public int getCompareToId() {
- return getAsmOpcode();
- }
-
- @Override
public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
@@ -77,6 +72,7 @@
printer.print(this);
}
+ @Override
public int getAsmOpcode() {
switch (type) {
case BYTE:
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 f574223..6105e74 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
@@ -83,7 +83,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.NEW;
}
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 f131164..e7e9d7d 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
@@ -59,7 +59,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return type.isPrimitiveArrayType() ? Opcodes.NEWARRAY : Opcodes.ANEWARRAY;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java b/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
index 11cab35..3acf922 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfNewUnboxedEnum.java
@@ -59,7 +59,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.NEW;
}
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 7706a69..bd28baa 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
@@ -25,7 +25,7 @@
public class CfNop extends CfInstruction {
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.NOP;
}
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 cadead1..fb02b64 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
@@ -40,11 +40,6 @@
}
@Override
- public int getCompareToId() {
- return getAsmOpcode();
- }
-
- @Override
public int internalAcceptCompareTo(
CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
@@ -87,6 +82,7 @@
printer.print(this);
}
+ @Override
public int getAsmOpcode() {
switch (from) {
case INT:
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfOpcodeUtils.java b/src/main/java/com/android/tools/r8/cf/code/CfOpcodeUtils.java
new file mode 100644
index 0000000..0d06079
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/cf/code/CfOpcodeUtils.java
@@ -0,0 +1,36 @@
+// Copyright (c) 2025, 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.code;
+
+import com.android.tools.r8.graph.CfCompareHelper;
+import java.util.function.IntConsumer;
+import org.objectweb.asm.Opcodes;
+
+public class CfOpcodeUtils {
+
+ public static void acceptCfFieldInstructionOpcodes(IntConsumer consumer) {
+ consumer.accept(Opcodes.GETSTATIC);
+ consumer.accept(Opcodes.PUTSTATIC);
+ consumer.accept(Opcodes.GETFIELD);
+ consumer.accept(Opcodes.PUTFIELD);
+ }
+
+ public static void acceptCfInvokeOpcodes(IntConsumer consumer) {
+ consumer.accept(Opcodes.INVOKEVIRTUAL);
+ consumer.accept(Opcodes.INVOKESPECIAL);
+ consumer.accept(Opcodes.INVOKESTATIC);
+ consumer.accept(Opcodes.INVOKEINTERFACE);
+ }
+
+ public static void acceptCfTypeInstructionOpcodes(
+ IntConsumer consumer, IntConsumer compareToIdConsumer) {
+ consumer.accept(Opcodes.CHECKCAST);
+ consumer.accept(Opcodes.INSTANCEOF);
+ consumer.accept(Opcodes.MULTIANEWARRAY);
+ consumer.accept(Opcodes.NEW);
+ consumer.accept(Opcodes.NEWARRAY);
+ consumer.accept(Opcodes.ANEWARRAY);
+ compareToIdConsumer.accept(CfCompareHelper.CONST_DYNAMIC_COMPARE_ID);
+ }
+}
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 b52cb87..efad8ac 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
@@ -33,6 +33,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.POSITION_COMPARE_ID;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java b/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
index ce358df..9a14069 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfRecordFieldValues.java
@@ -78,6 +78,16 @@
}
@Override
+ public int getAsmOpcode() {
+ return -1;
+ }
+
+ @Override
+ public boolean hasAsmOpcode() {
+ return false;
+ }
+
+ @Override
public int getCompareToId() {
return CfCompareHelper.RECORD_FIELD_VALUES_COMPARE_ID;
}
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 a99482d..1ed076a 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
@@ -40,22 +40,7 @@
}
@Override
- public int getCompareToId() {
- return getOpcode();
- }
-
- @Override
- public int internalAcceptCompareTo(
- CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
- }
-
- @Override
- public void internalAcceptHashing(HashingVisitor visitor) {
- // Nothing to add.
- }
-
- private int getOpcode() {
+ public int getAsmOpcode() {
switch (type) {
case INT:
return Opcodes.IRETURN;
@@ -73,6 +58,17 @@
}
@Override
+ public int internalAcceptCompareTo(
+ CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
+ return CfCompareHelper.compareIdUniquelyDeterminesEquality(this, other);
+ }
+
+ @Override
+ public void internalAcceptHashing(HashingVisitor visitor) {
+ // Nothing to add.
+ }
+
+ @Override
public int bytecodeSizeUpperBound() {
return 1;
}
@@ -96,7 +92,7 @@
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- visitor.visitInsn(getOpcode());
+ visitor.visitInsn(getAsmOpcode());
}
@Override
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 5b16578..d3d8f90 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,7 +35,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.RETURN;
}
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 c5c8f6e..a30bb1b 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
@@ -83,7 +83,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return opcode.opcode;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStaticFieldRead.java b/src/main/java/com/android/tools/r8/cf/code/CfStaticFieldRead.java
index 12467da..78ae24a 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStaticFieldRead.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStaticFieldRead.java
@@ -33,7 +33,7 @@
}
@Override
- public int getOpcode() {
+ public int getAsmOpcode() {
return Opcodes.GETSTATIC;
}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfStaticFieldWrite.java b/src/main/java/com/android/tools/r8/cf/code/CfStaticFieldWrite.java
index 01d9bed..df00570 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfStaticFieldWrite.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfStaticFieldWrite.java
@@ -33,7 +33,7 @@
}
@Override
- public int getOpcode() {
+ public int getAsmOpcode() {
return Opcodes.PUTSTATIC;
}
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 9e5449a..85d377d 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
@@ -36,22 +36,7 @@
}
@Override
- public int getCompareToId() {
- return getStoreType();
- }
-
- @Override
- public int internalAcceptCompareTo(
- CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
- return visitor.visitInt(var, other.asStore().var);
- }
-
- @Override
- public void internalAcceptHashing(HashingVisitor visitor) {
- visitor.visitInt(var);
- }
-
- private int getStoreType() {
+ public int getAsmOpcode() {
switch (type) {
case OBJECT:
return Opcodes.ASTORE;
@@ -69,6 +54,17 @@
}
@Override
+ public int internalAcceptCompareTo(
+ CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
+ return visitor.visitInt(var, other.asStore().var);
+ }
+
+ @Override
+ public void internalAcceptHashing(HashingVisitor visitor) {
+ visitor.visitInt(var);
+ }
+
+ @Override
public CfStore asStore() {
return this;
}
@@ -89,7 +85,7 @@
NamingLens namingLens,
LensCodeRewriterUtils rewriter,
MethodVisitor visitor) {
- visitor.visitVarInsn(getStoreType(), var);
+ visitor.visitVarInsn(getAsmOpcode(), var);
}
@Override
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 31e7ff3..585de87 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
@@ -59,7 +59,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return kind == Kind.LOOKUP ? Opcodes.LOOKUPSWITCH : Opcodes.TABLESWITCH;
}
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 4b81a79..ebf5df1 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,7 +36,7 @@
}
@Override
- public int getCompareToId() {
+ public int getAsmOpcode() {
return Opcodes.ATHROW;
}
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 063123a..5897ea6 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCompareHelper.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCompareHelper.java
@@ -17,6 +17,8 @@
public class CfCompareHelper {
+ public static final int MAX_COMPARE_ID;
+
// Integer constants to ensure that there is a well order for all CF instructions including
// virtual instructions represented in our internal encoding.
public static final int CONST_CLASS_COMPARE_ID;
@@ -46,6 +48,7 @@
LABEL_COMPARE_ID = ++lastId;
POSITION_COMPARE_ID = ++lastId;
RECORD_FIELD_VALUES_COMPARE_ID = ++lastId;
+ MAX_COMPARE_ID = lastId;
}
// Helper to signal that the concrete instruction is uniquely determined by its ID/opcode.
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
index d38b615..7362ef4 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/ClassInitializerAssertionEnablingAnalysis.java
@@ -191,7 +191,7 @@
fieldInstruction = isR8InstructionSequence(code, i + 1);
}
if (fieldInstruction != null) {
- return fieldInstruction.getOpcode() == Opcodes.PUTSTATIC
+ return fieldInstruction.getAsmOpcode() == Opcodes.PUTSTATIC
&& fieldInstruction.getField().name == dexItemFactory.assertionsDisabled;
}
}
@@ -220,7 +220,7 @@
&& invoke.getMethod() == dexItemFactory.classMethods.desiredAssertionStatus) {
if (instructions.get(i).isFieldInstruction()) {
CfFieldInstruction fieldInstruction = instructions.get(i).asFieldInstruction();
- if (fieldInstruction.getOpcode() == Opcodes.PUTSTATIC
+ if (fieldInstruction.getAsmOpcode() == Opcodes.PUTSTATIC
&& fieldInstruction.getField().name == kotlinAssertionsEnabled) {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index b52dbf0..6eb626d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.cf.code.CfLabel;
import com.android.tools.r8.cf.code.CfLoad;
import com.android.tools.r8.cf.code.CfNew;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.cf.code.CfPosition;
import com.android.tools.r8.cf.code.CfReturn;
import com.android.tools.r8.cf.code.CfReturnVoid;
@@ -85,6 +86,7 @@
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
public final class BackportedMethodRewriter implements CfInstructionDesugaring {
@@ -103,6 +105,12 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ consumer.accept(Opcodes.GETSTATIC);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
// Only invokes and static field gets are backported.
if (!instruction.isInvoke() && !instruction.isStaticFieldGet()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BufferCovariantReturnTypeRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BufferCovariantReturnTypeRewriter.java
index 67c2bf3..a3c475d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BufferCovariantReturnTypeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BufferCovariantReturnTypeRewriter.java
@@ -7,12 +7,14 @@
import com.android.tools.r8.cf.code.CfCheckCast;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.ProgramMethod;
import com.google.common.collect.ImmutableList;
+import java.util.function.IntConsumer;
/**
* BufferCovariantReturnTypeRewriter rewrites the return type of invoked methods matching
@@ -27,8 +29,13 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
- if (!isInvokeCandidate(instruction)) {
+ if (!instruction.isInvoke()) {
return DesugarDescription.nothing();
}
CfInvoke cfInvoke = instruction.asInvoke();
@@ -83,10 +90,4 @@
}
return null;
}
-
- private boolean isInvokeCandidate(CfInstruction instruction) {
- return instruction.isInvoke()
- || instruction.isInvokeStatic()
- || instruction.isInvokeInterface();
- }
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaring.java
index f5db966..c2c9731 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CfInstructionDesugaring.java
@@ -7,10 +7,17 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.ProgramMethod;
+import java.util.function.IntConsumer;
/** Interface for desugaring a single class-file instruction. */
public interface CfInstructionDesugaring {
+ CfInstructionDesugaring[] EMPTY_ARRAY = new CfInstructionDesugaring[0];
+
+ void acceptRelevantAsmOpcodes(IntConsumer consumer);
+
+ default void acceptRelevantCompareToIds(IntConsumer consumer) {}
+
// TODO(193004879): Merge the scan and prepare methods.
default void scan(ProgramMethod method, CfInstructionDesugaringEventConsumer eventConsumer) {
// Default scan is to do nothing.
@@ -43,4 +50,8 @@
default DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
throw new Unreachable();
}
+
+ default String getName() {
+ return getClass().getTypeName();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InvokeToPrivateRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/InvokeToPrivateRewriter.java
index 151eb36..799729e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InvokeToPrivateRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InvokeToPrivateRewriter.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.ProgramMethod;
import com.google.common.collect.ImmutableList;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
/**
@@ -25,6 +26,12 @@
public class InvokeToPrivateRewriter implements CfInstructionDesugaring {
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ consumer.accept(Opcodes.INVOKEINTERFACE);
+ consumer.accept(Opcodes.INVOKEVIRTUAL);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (!instruction.isInvokeVirtual() && !instruction.isInvokeInterface()) {
return DesugarDescription.nothing();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
index eda2b3d..20fbfa2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NonEmptyCfInstructionDesugaringCollection.java
@@ -12,6 +12,7 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
+import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.Position;
@@ -44,6 +45,9 @@
import com.android.tools.r8.utils.ThrowingConsumer;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@@ -64,6 +68,8 @@
private final DesugaredLibraryAPIConverter desugaredLibraryAPIConverter;
private final DesugaredLibraryDisableDesugarer disableDesugarer;
+ private final CfInstructionDesugaring[][] asmOpcodeOrCompareToIdToDesugaringsMap;
+
NonEmptyCfInstructionDesugaringCollection(
AppView<?> appView, AndroidApiLevelCompute apiLevelCompute) {
this.appView = appView;
@@ -83,6 +89,14 @@
this.interfaceMethodRewriter = null;
this.desugaredLibraryAPIConverter = null;
this.disableDesugarer = null;
+ desugarings.add(new InvokeSpecialToSelfDesugaring(appView));
+ if (appView.options().isGeneratingDex()) {
+ if (appView.options().canHaveArtArrayCloneFromInterfaceMethodBug()) {
+ desugarings.add(new OutlineArrayCloneFromInterfaceMethodDesugaring(appView));
+ }
+ yieldingDesugarings.add(new UnrepresentableInDexInstructionRemover(appView));
+ }
+ this.asmOpcodeOrCompareToIdToDesugaringsMap = createAsmOpcodeOrCompareToIdToDesugaringsMap();
return;
}
this.nestBasedAccessDesugaring = NestBasedAccessDesugaring.create(appView);
@@ -165,33 +179,55 @@
desugarings.add(varHandleDesugaring);
}
yieldingDesugarings.add(new UnrepresentableInDexInstructionRemover(appView));
+ asmOpcodeOrCompareToIdToDesugaringsMap = createAsmOpcodeOrCompareToIdToDesugaringsMap();
+ }
+
+ private CfInstructionDesugaring[][] createAsmOpcodeOrCompareToIdToDesugaringsMap() {
+ Int2ReferenceMap<List<CfInstructionDesugaring>> map = new Int2ReferenceOpenHashMap<>();
+ for (CfInstructionDesugaring desugaring : Iterables.concat(desugarings, yieldingDesugarings)) {
+ desugaring.acceptRelevantAsmOpcodes(
+ opcode -> registerRelevantAsmOpcodeOrCompareToId(map, desugaring, opcode));
+ desugaring.acceptRelevantCompareToIds(
+ id -> registerRelevantAsmOpcodeOrCompareToId(map, desugaring, id));
+ }
+ // Convert map to a dense array.
+ int maxAsmOpcodeOrCompareToId = CfCompareHelper.MAX_COMPARE_ID;
+ CfInstructionDesugaring[][] arrayMap =
+ new CfInstructionDesugaring[maxAsmOpcodeOrCompareToId + 1][];
+ for (Entry<List<CfInstructionDesugaring>> entry : map.int2ReferenceEntrySet()) {
+ arrayMap[entry.getIntKey()] = entry.getValue().toArray(CfInstructionDesugaring.EMPTY_ARRAY);
+ }
+ for (int i = 0; i < arrayMap.length; i++) {
+ if (arrayMap[i] == null) {
+ arrayMap[i] = CfInstructionDesugaring.EMPTY_ARRAY;
+ }
+ }
+ return arrayMap;
+ }
+
+ private void registerRelevantAsmOpcodeOrCompareToId(
+ Int2ReferenceMap<List<CfInstructionDesugaring>> asmOpcodeOrCompareToIdToDesugaringsMap,
+ CfInstructionDesugaring desugaring,
+ int opcodeOrCompareToId) {
+ if (asmOpcodeOrCompareToIdToDesugaringsMap.containsKey(opcodeOrCompareToId)) {
+ asmOpcodeOrCompareToIdToDesugaringsMap.get(opcodeOrCompareToId).add(desugaring);
+ } else {
+ asmOpcodeOrCompareToIdToDesugaringsMap.put(
+ opcodeOrCompareToId, ListUtils.newArrayList(desugaring));
+ }
}
static NonEmptyCfInstructionDesugaringCollection createForCfToCfNonDesugar(AppView<?> appView) {
assert appView.options().desugarState.isOff();
assert appView.options().isGeneratingClassFiles();
- NonEmptyCfInstructionDesugaringCollection desugaringCollection =
- new NonEmptyCfInstructionDesugaringCollection(appView, noAndroidApiLevelCompute());
- // TODO(b/145775365): special constructor for cf-to-cf compilations with desugaring disabled.
- // This should be removed once we can represent invoke-special instructions in the IR.
- desugaringCollection.desugarings.add(new InvokeSpecialToSelfDesugaring(appView));
- return desugaringCollection;
+ return new NonEmptyCfInstructionDesugaringCollection(appView, noAndroidApiLevelCompute());
}
static NonEmptyCfInstructionDesugaringCollection createForCfToDexNonDesugar(
AppView<?> appView, AndroidApiLevelCompute apiLevelCompute) {
assert appView.options().desugarState.isOff();
assert appView.options().isGeneratingDex();
- NonEmptyCfInstructionDesugaringCollection desugaringCollection =
- new NonEmptyCfInstructionDesugaringCollection(appView, apiLevelCompute);
- desugaringCollection.desugarings.add(new InvokeSpecialToSelfDesugaring(appView));
- if (appView.options().canHaveArtArrayCloneFromInterfaceMethodBug()) {
- desugaringCollection.desugarings.add(
- new OutlineArrayCloneFromInterfaceMethodDesugaring(appView));
- }
- desugaringCollection.yieldingDesugarings.add(
- new UnrepresentableInDexInstructionRemover(appView));
- return desugaringCollection;
+ return new NonEmptyCfInstructionDesugaringCollection(appView, apiLevelCompute);
}
private void ensureCfCode(ProgramMethod method) {
@@ -430,16 +466,29 @@
throw new Unreachable("Unexpected attempt to determine if non-CF code needs desugaring");
}
- return Iterables.any(
- code.asCfCode().getInstructions(), instruction -> needsDesugaring(instruction, method));
+ CfCode cfCode = code.asCfCode();
+ for (CfInstruction instruction : cfCode.getInstructions()) {
+ int asmOpcodeOrCompareToId =
+ instruction.hasAsmOpcode() ? instruction.getAsmOpcode() : instruction.getCompareToId();
+ CfInstructionDesugaring[] desugaringsForInstruction =
+ asmOpcodeOrCompareToIdToDesugaringsMap[asmOpcodeOrCompareToId];
+ for (CfInstructionDesugaring desugaring : desugaringsForInstruction) {
+ if (desugaring.compute(instruction, method).needsDesugaring()) {
+ return true;
+ }
+ }
+ assert verifyNoDesugaringNeeded(instruction, method);
+ }
+ return false;
}
- private boolean needsDesugaring(CfInstruction instruction, ProgramMethod context) {
- return Iterables.any(
- desugarings, desugaring -> desugaring.compute(instruction, context).needsDesugaring())
- || Iterables.any(
- yieldingDesugarings,
- desugaring -> desugaring.compute(instruction, context).needsDesugaring());
+ private boolean verifyNoDesugaringNeeded(CfInstruction instruction, ProgramMethod context) {
+ for (CfInstructionDesugaring desugaring : Iterables.concat(desugarings, yieldingDesugarings)) {
+ assert !desugaring.compute(instruction, context).needsDesugaring()
+ : "Expected instruction to be desugared, but matched by: "
+ + desugaring.getClass().getName();
+ }
+ return true;
}
private boolean verifyNoOtherDesugaringNeeded(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/OutlineArrayCloneFromInterfaceMethodDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/OutlineArrayCloneFromInterfaceMethodDesugaring.java
index ce5fde6..b1b491e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/OutlineArrayCloneFromInterfaceMethodDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/OutlineArrayCloneFromInterfaceMethodDesugaring.java
@@ -19,6 +19,7 @@
import com.google.common.collect.ImmutableList;
import java.util.Collections;
import java.util.List;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
/** This outlines calls to array clone from within interface methods. See b/342802978 */
@@ -27,11 +28,15 @@
private final AppView<?> appView;
public OutlineArrayCloneFromInterfaceMethodDesugaring(AppView<?> appView) {
-
this.appView = appView;
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ consumer.accept(Opcodes.INVOKEVIRTUAL);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
// This workaround only applies within default or static interface method.
if (!context.getHolder().isInterface()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/UnrepresentableInDexInstructionRemover.java b/src/main/java/com/android/tools/r8/ir/desugar/UnrepresentableInDexInstructionRemover.java
index f713b03..5253c0c 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/UnrepresentableInDexInstructionRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/UnrepresentableInDexInstructionRemover.java
@@ -15,6 +15,7 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfInvokeDynamic;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
@@ -25,6 +26,7 @@
import com.android.tools.r8.errors.UnsupportedInvokeCustomDiagnostic;
import com.android.tools.r8.errors.UnsupportedInvokePolymorphicMethodHandleDiagnostic;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
@@ -42,6 +44,7 @@
import com.google.common.collect.ImmutableList.Builder;
import java.util.List;
import java.util.Set;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
/**
@@ -394,6 +397,19 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ consumer.accept(Opcodes.INVOKEDYNAMIC);
+ }
+
+ @Override
+ public void acceptRelevantCompareToIds(IntConsumer consumer) {
+ consumer.accept(CfCompareHelper.CONST_DYNAMIC_COMPARE_ID);
+ consumer.accept(CfCompareHelper.CONST_METHOD_HANDLE_COMPARE_ID);
+ consumer.accept(CfCompareHelper.CONST_METHOD_TYPE_COMPARE_ID);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
for (InstructionMatcher matcher : matchers) {
DesugarDescription result = matcher.compute(instruction);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
index 259234e..e7fc2d4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
@@ -16,8 +16,10 @@
import com.android.tools.r8.cf.code.CfInstanceOf;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.contexts.CompilationContext.UniqueContext;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -47,6 +49,8 @@
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
+import java.util.function.IntConsumer;
+import org.objectweb.asm.Opcodes;
/**
* This desugaring will outline calls to library methods that are introduced after the min-api
@@ -66,6 +70,24 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfFieldInstructionOpcodes(consumer);
+ CfOpcodeUtils.acceptCfInvokeOpcodes(
+ opcode -> {
+ if (opcode != Opcodes.INVOKESPECIAL) {
+ consumer.accept(opcode);
+ }
+ });
+ consumer.accept(Opcodes.CHECKCAST);
+ consumer.accept(Opcodes.INSTANCEOF);
+ }
+
+ @Override
+ public void acceptRelevantCompareToIds(IntConsumer consumer) {
+ consumer.accept(CfCompareHelper.CONST_CLASS_COMPARE_ID);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
ComputedApiLevel computedApiLevel =
getComputedApiLevelInstructionOnHolderWithMinApi(instruction, context);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicInstructionDesugaring.java
index 4577688..be6c7a3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicInstructionDesugaring.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.errors.ConstantDynamicDesugarDiagnostic;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
@@ -25,6 +26,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.IntConsumer;
public class ConstantDynamicInstructionDesugaring implements CfInstructionDesugaring {
@@ -49,6 +51,16 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ // Intentionally empty.
+ }
+
+ @Override
+ public void acceptRelevantCompareToIds(IntConsumer consumer) {
+ consumer.accept(CfCompareHelper.CONST_DYNAMIC_COMPARE_ID);
+ }
+
+ @Override
@SuppressWarnings("ReferenceEquality")
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (!instruction.isConstDynamic()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
index 9a5056b..ecaf710 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -29,6 +30,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
@SuppressWarnings("UnusedVariable")
@@ -86,6 +88,11 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (!instruction.isInvoke()) {
return DesugarDescription.nothing();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/disabledesugarer/DesugaredLibraryDisableDesugarer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/disabledesugarer/DesugaredLibraryDisableDesugarer.java
index f3d1a6d..f4dfe72 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/disabledesugarer/DesugaredLibraryDisableDesugarer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/disabledesugarer/DesugaredLibraryDisableDesugarer.java
@@ -4,9 +4,12 @@
package com.android.tools.r8.ir.desugar.desugaredlibrary.disabledesugarer;
+import static com.android.tools.r8.utils.IntConsumerUtils.emptyIntConsumer;
+
import com.android.tools.r8.cf.code.CfFieldInstruction;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.cf.code.CfTypeInstruction;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexField;
@@ -16,6 +19,8 @@
import com.android.tools.r8.ir.desugar.CfInstructionDesugaring;
import com.android.tools.r8.ir.desugar.DesugarDescription;
import com.google.common.collect.ImmutableList;
+import java.util.function.IntConsumer;
+import org.objectweb.asm.Opcodes;
/**
* Disables the rewriting of types in specific classes declared in the desugared library
@@ -38,6 +43,25 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfFieldInstructionOpcodes(consumer);
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ CfOpcodeUtils.acceptCfTypeInstructionOpcodes(
+ opcode -> {
+ // Skip primitive array allocations.
+ if (opcode != Opcodes.NEWARRAY) {
+ consumer.accept(opcode);
+ }
+ },
+ emptyIntConsumer());
+ }
+
+ @Override
+ public void acceptRelevantCompareToIds(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfTypeInstructionOpcodes(emptyIntConsumer(), consumer);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
CfInstruction replacement = rewriteInstruction(instruction, context);
if (replacement == null) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryLibRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryLibRewriter.java
index 17c3a51..2b7ac09 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryLibRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryLibRewriter.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
@@ -24,6 +25,7 @@
import java.util.Collections;
import java.util.Map;
import java.util.function.BiFunction;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
/**
@@ -89,6 +91,11 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (appView
.getSyntheticItems()
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
index c3a58c1..45ae3da 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeter.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.cf.code.CfFieldInstruction;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -25,6 +26,7 @@
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Consumer;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
public class DesugaredLibraryRetargeter implements CfInstructionDesugaring {
@@ -58,6 +60,12 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ consumer.accept(Opcodes.GETSTATIC);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (instruction.isStaticFieldGet()) {
return computeStaticFieldGetDescription(instruction, context);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/icce/AlwaysThrowingInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/icce/AlwaysThrowingInstructionDesugaring.java
index 1204cd0..e567034 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/icce/AlwaysThrowingInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/icce/AlwaysThrowingInstructionDesugaring.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.cf.code.CfConstNumber;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
@@ -29,6 +30,7 @@
import com.android.tools.r8.ir.optimize.UtilityMethodsForCodeOptimizations.UtilityMethodForCodeOptimizations;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.function.IntConsumer;
public class AlwaysThrowingInstructionDesugaring implements CfInstructionDesugaring {
@@ -39,6 +41,11 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (instruction.isInvoke()) {
CfInvoke invoke = instruction.asInvoke();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
index b290ad9..81b9b77 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.ir.desugar.DesugarDescription;
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
import com.google.common.collect.ImmutableList;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
/** This class defines the desugaring of a single invoke-special instruction. */
@@ -31,6 +32,11 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ consumer.accept(Opcodes.INVOKESPECIAL);
+ }
+
+ @Override
@SuppressWarnings("ReferenceEquality")
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (!instruction.isInvokeSpecial()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index dd600b3..57cc90e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfInvokeDynamic;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppInfo;
@@ -54,6 +55,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.IntConsumer;
import java.util.function.Predicate;
//
@@ -215,6 +217,11 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ }
+
+ @Override
public boolean hasPreciseNeedsDesugaring() {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
index 5ba70be..dd386d5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
@@ -37,6 +37,7 @@
import java.util.Deque;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
public class LambdaInstructionDesugaring implements CfInstructionDesugaring {
@@ -55,6 +56,11 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ consumer.accept(Opcodes.INVOKEDYNAMIC);
+ }
+
+ @Override
public void scan(ProgramMethod method, CfInstructionDesugaringEventConsumer eventConsumer) {
CfCode code = method.getDefinition().getCode().asCfCode();
for (CfInstruction instruction : code.getInstructions()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
index 0550d47..6c0ee9b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfInvokeDynamic;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.Code;
@@ -43,6 +44,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
// NestBasedAccessDesugaring contains common code between the two subclasses
@@ -136,6 +138,12 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfFieldInstructionOpcodes(consumer);
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ }
+
+ @Override
public void prepare(
ProgramMethod method,
CfInstructionDesugaringEventConsumer eventConsumer,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordInstructionDesugaring.java
index 773189b..29d66a6 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordInstructionDesugaring.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfInvokeDynamic;
import com.android.tools.r8.cf.code.CfLoad;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.cf.code.CfStore;
@@ -57,6 +58,7 @@
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
public class RecordInstructionDesugaring implements CfInstructionDesugaring {
@@ -108,6 +110,12 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ consumer.accept(Opcodes.INVOKEDYNAMIC);
+ }
+
+ @Override
public void prepare(
ProgramMethod method,
CfInstructionDesugaringEventConsumer eventConsumer,
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/stringconcat/StringConcatInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/stringconcat/StringConcatInstructionDesugaring.java
index 5d5672a..05c14e9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/stringconcat/StringConcatInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/stringconcat/StringConcatInstructionDesugaring.java
@@ -41,6 +41,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
/** String concatenation desugaring rewriter. */
@@ -68,6 +69,11 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ consumer.accept(Opcodes.INVOKEDYNAMIC);
+ }
+
+ @Override
@SuppressWarnings("ReferenceEquality")
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (instruction.isInvokeDynamic()) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
index bb9ac0e..c81a156 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppView;
@@ -23,6 +24,7 @@
import com.google.common.collect.ImmutableList;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
public class TwrInstructionDesugaring implements CfInstructionDesugaring {
@@ -44,10 +46,12 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
- if (!instruction.isInvoke()) {
- return DesugarDescription.nothing();
- }
if (isTwrCloseResourceInvoke(instruction)) {
return rewriteTwrCloseResourceInvoke();
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaring.java
index 4961b64..119ad06 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/typeswitch/TypeSwitchDesugaring.java
@@ -47,6 +47,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
+import java.util.function.IntConsumer;
import org.objectweb.asm.Opcodes;
public class TypeSwitchDesugaring implements CfInstructionDesugaring {
@@ -71,6 +72,13 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ consumer.accept(Opcodes.INVOKEDYNAMIC);
+ consumer.accept(Opcodes.INVOKESPECIAL);
+ consumer.accept(Opcodes.NEW);
+ }
+
+ @Override
public DesugarDescription compute(CfInstruction instruction, ProgramMethod context) {
if (!instruction.isInvokeDynamic()) {
// We need to replace the new MatchException with RuntimeException.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
index 273ab78..766dbf4 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/varhandle/VarHandleDesugaring.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfLoad;
import com.android.tools.r8.cf.code.CfNew;
+import com.android.tools.r8.cf.code.CfOpcodeUtils;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
import com.android.tools.r8.cf.code.CfStore;
@@ -43,6 +44,7 @@
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.IntConsumer;
import java.util.function.Predicate;
import org.objectweb.asm.Opcodes;
@@ -68,6 +70,11 @@
}
@Override
+ public void acceptRelevantAsmOpcodes(IntConsumer consumer) {
+ CfOpcodeUtils.acceptCfInvokeOpcodes(consumer);
+ }
+
+ @Override
@SuppressWarnings("ReferenceEquality")
public void scan(
ProgramMethod programMethod, CfInstructionDesugaringEventConsumer eventConsumer) {
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 77f5fbc..b856ae7 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4322,29 +4322,36 @@
&& !method.getDefinition().isInitializer();
}
- private boolean addToPendingDesugaring(ProgramMethod method) {
- if (options.isInterfaceMethodDesugaringEnabled()) {
- if (mustMoveToInterfaceCompanionMethod(method)) {
- // TODO(b/199043500): Once "live moved methods" are tracked this can avoid the code check.
- if (!InvalidCode.isInvalidCode(method.getDefinition().getCode())) {
- pendingMethodMove.add(method);
+ private boolean addToPendingDesugaring(ProgramMethod method, Timing timing) {
+ try (Timing t0 = timing.begin("Analyze needs desugaring")) {
+ try (Timing t1 = timing.begin("Analyze interface method desugaring")) {
+ if (options.isInterfaceMethodDesugaringEnabled()) {
+ if (mustMoveToInterfaceCompanionMethod(method)) {
+ // TODO(b/199043500): Once "live moved methods" are tracked this can avoid the code
+ // check.
+ if (!InvalidCode.isInvalidCode(method.getDefinition().getCode())) {
+ pendingMethodMove.add(method);
+ }
+ return true;
+ }
+ ProgramMethod nonMovedMethod = pendingMethodMoveInverse.get(method);
+ if (nonMovedMethod != null) {
+ // Any non-moved code must be a proper pending item.
+ assert InvalidCode.isInvalidCode(method.getDefinition().getCode());
+ assert !InvalidCode.isInvalidCode(nonMovedMethod.getDefinition().getCode());
+ pendingMethodMove.add(nonMovedMethod);
+ return true;
}
- return true;
}
- ProgramMethod nonMovedMethod = pendingMethodMoveInverse.get(method);
- if (nonMovedMethod != null) {
- // Any non-moved code must be a proper pending item.
- assert InvalidCode.isInvalidCode(method.getDefinition().getCode());
- assert !InvalidCode.isInvalidCode(nonMovedMethod.getDefinition().getCode());
- pendingMethodMove.add(nonMovedMethod);
- return true;
}
+ try (Timing t2 = timing.begin("Analyze instruction desugaring")) {
+ if (desugaring.needsDesugaring(method)) {
+ pendingCodeDesugaring.add(method);
+ return true;
+ }
+ }
+ return false;
}
- if (desugaring.needsDesugaring(method)) {
- pendingCodeDesugaring.add(method);
- return true;
- }
- return false;
}
private void desugar(SyntheticAdditions additions) throws ExecutionException {
@@ -4924,7 +4931,7 @@
while (worklist.hasNext()) {
EnqueuerAction action = worklist.poll();
- action.run(this);
+ action.run(this, Timing.empty());
}
}
@@ -5117,18 +5124,23 @@
}
// Package protected due to entry point from worklist.
- void markMethodAsLive(ProgramMethod method, ProgramDefinition context) {
+ void markMethodAsLive(ProgramMethod method, ProgramDefinition context, Timing timing) {
assert liveMethods.contains(method);
DexEncodedMethod definition = method.getDefinition();
assert !definition.getOptimizationInfo().forceInline();
+ timing.begin("Clinit");
if (definition.isStatic()) {
markDirectAndIndirectClassInitializersAsLive(method.getHolder());
}
+ timing.end();
- traceNonDesugaredCode(method);
+ timing.begin("Trace code (non-desugared)");
+ traceNonDesugaredCode(method, timing);
+ timing.end();
+ timing.begin("Super");
ProgramMethodSet superCallTargets = superInvokeDependencies.get(method.getDefinition());
if (superCallTargets != null) {
for (ProgramMethod superCallTarget : superCallTargets) {
@@ -5136,8 +5148,11 @@
markVirtualMethodAsLive(superCallTarget, KeepReason.invokedViaSuperFrom(method));
}
}
+ timing.end();
+ timing.begin("Notify");
analyses.processNewlyLiveMethod(method, context, this, worklist);
+ timing.end();
}
private void markMethodAsTargeted(ProgramMethod method, KeepReason reason) {
@@ -5177,21 +5192,27 @@
}
}
- private void traceNonDesugaredCode(ProgramMethod method) {
+ private void traceNonDesugaredCode(ProgramMethod method, Timing timing) {
if (getMode().isInitialTreeShaking()) {
- if (addToPendingDesugaring(method)) {
+ if (addToPendingDesugaring(method, timing)) {
return;
}
}
- traceCode(method);
+ traceCode(method, timing);
}
- void traceCode(ProgramMethod method) {
+ void traceCode(ProgramMethod method, Timing timing) {
+ timing.begin("Trace code");
DefaultEnqueuerUseRegistry registry =
useRegistryFactory.create(appView, method, this, appView.apiLevelCompute());
+ timing.begin("Register code references");
method.registerCodeReferences(registry);
+ timing.end();
+ timing.begin("Notify processNewlyLiveCode");
analyses.processNewlyLiveCode(method, registry, worklist);
+ timing.end();
+ timing.end();
}
private void markReferencedTypesAsLive(ProgramMethod method) {
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
index 2b3bdf9..2303c84 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
@@ -180,8 +180,15 @@
}
@Override
+ public void run(Enqueuer enqueuer, Timing timing) {
+ timing.begin(getName());
+ enqueuer.markMethodAsLive(method, context, timing);
+ timing.end();
+ }
+
+ @Override
public void run(Enqueuer enqueuer) {
- enqueuer.markMethodAsLive(method, context);
+ throw new Unreachable();
}
}
@@ -241,8 +248,15 @@
}
@Override
+ public void run(Enqueuer enqueuer, Timing timing) {
+ timing.begin(getName());
+ enqueuer.traceCode(method, timing);
+ timing.end();
+ }
+
+ @Override
public void run(Enqueuer enqueuer) {
- enqueuer.traceCode(method);
+ throw new Unreachable();
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/Timing.java b/src/main/java/com/android/tools/r8/utils/Timing.java
index 696f1c7..7e4a8e1 100644
--- a/src/main/java/com/android/tools/r8/utils/Timing.java
+++ b/src/main/java/com/android/tools/r8/utils/Timing.java
@@ -23,6 +23,9 @@
public class Timing implements AutoCloseable {
+ private static final int MINIMUM_REPORT_MS =
+ SystemPropertyUtils.parseSystemPropertyOrDefault(
+ "com.android.tools.r8.printtimes.minvalue_ms", 10);
private static final int MINIMUM_REPORT_PERCENTAGE =
SystemPropertyUtils.parseSystemPropertyOrDefault(
"com.android.tools.r8.printtimes.minvalue", 2);
@@ -227,6 +230,9 @@
public void report(int depth, Node top) {
assert duration() >= 0;
+ if (durationInMs(duration()) < MINIMUM_REPORT_MS) {
+ return;
+ }
if (percentage(duration(), top.duration()) < MINIMUM_REPORT_PERCENTAGE) {
return;
}
@@ -245,7 +251,8 @@
}
if (childTime < duration()) {
long unaccounted = duration() - childTime;
- if (percentage(unaccounted, top.duration()) >= MINIMUM_REPORT_PERCENTAGE) {
+ if (durationInMs(unaccounted) >= MINIMUM_REPORT_MS
+ && percentage(unaccounted, top.duration()) >= MINIMUM_REPORT_PERCENTAGE) {
printPrefix(depth + 1);
System.out.println(
"("
@@ -409,6 +416,10 @@
return new TimingMerger(title, numberOfThreads, this);
}
+ private static long durationInMs(long value) {
+ return value / 1000000;
+ }
+
private static long percentage(long part, long total) {
return part * 100 / total;
}
@@ -418,7 +429,7 @@
}
private static String prettyTime(long value) {
- return (value / 1000000) + "ms";
+ return durationInMs(value) + "ms";
}
private static String prettySize(long value) {
diff --git a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
index 4c0102e..7989945 100644
--- a/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
+++ b/src/test/testbase/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
@@ -85,25 +85,25 @@
@Override
public boolean isInstancePut() {
return instruction instanceof CfFieldInstruction
- && ((CfFieldInstruction) instruction).getOpcode() == Opcodes.PUTFIELD;
+ && ((CfFieldInstruction) instruction).getAsmOpcode() == Opcodes.PUTFIELD;
}
@Override
public boolean isStaticPut() {
return instruction instanceof CfFieldInstruction
- && ((CfFieldInstruction) instruction).getOpcode() == Opcodes.PUTSTATIC;
+ && ((CfFieldInstruction) instruction).getAsmOpcode() == Opcodes.PUTSTATIC;
}
@Override
public boolean isInstanceGet() {
return instruction instanceof CfFieldInstruction
- && ((CfFieldInstruction) instruction).getOpcode() == Opcodes.GETFIELD;
+ && ((CfFieldInstruction) instruction).getAsmOpcode() == Opcodes.GETFIELD;
}
@Override
public boolean isStaticGet() {
return instruction instanceof CfFieldInstruction
- && ((CfFieldInstruction) instruction).getOpcode() == Opcodes.GETSTATIC;
+ && ((CfFieldInstruction) instruction).getAsmOpcode() == Opcodes.GETSTATIC;
}
@Override