Reland "Backport methods on CF code."
Bug: 147485959
Bug: 169305577
Change-Id: I10d31650a1386fbcf3ecf767234e574e4a589302
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 b695024..f475e89 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
@@ -1135,9 +1135,13 @@
return false;
}
boolean didDesugar = false;
+ Supplier<AppInfoWithClassHierarchy> lazyAppInfo =
+ Suppliers.memoize(() -> appView.appInfoForDesugaring());
if (lambdaRewriter != null) {
- AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
- didDesugar |= lambdaRewriter.desugarLambdas(method, appInfo) > 0;
+ didDesugar |= lambdaRewriter.desugarLambdas(method, lazyAppInfo.get()) > 0;
+ }
+ if (backportedMethodRewriter != null) {
+ didDesugar |= backportedMethodRewriter.desugar(method, lazyAppInfo.get());
}
return didDesugar;
}
@@ -1423,12 +1427,6 @@
timing.end();
}
- if (backportedMethodRewriter != null) {
- timing.begin("Rewrite backport methods");
- backportedMethodRewriter.desugar(code);
- timing.end();
- }
-
timing.begin("Desugar string concat");
stringConcatRewriter.desugarStringConcats(method.method, code);
timing.end();
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 99bad27..b45fe42 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
@@ -4,28 +4,25 @@
package com.android.tools.r8.ir.desugar;
-
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ProgramMethod;
-import com.android.tools.r8.ir.analysis.type.TypeAnalysis;
-import com.android.tools.r8.ir.code.IRCode;
-import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.desugar.backports.BackportedMethods;
import com.android.tools.r8.ir.desugar.backports.BooleanMethodRewrites;
@@ -41,19 +38,19 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.DesugarState;
import com.android.tools.r8.utils.Timing;
-import com.google.common.collect.Sets;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Queue;
-import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
+import org.objectweb.asm.Opcodes;
public final class BackportedMethodRewriter {
@@ -108,29 +105,34 @@
BackportedMethods.registerSynthesizedCodeReferences(options.itemFactory);
}
- public void desugar(IRCode code) {
+ public boolean desugar(ProgramMethod method, AppInfoWithClassHierarchy appInfo) {
if (!enabled) {
- return; // Nothing to do!
+ return false;
}
- Set<Value> affectedValues = Sets.newIdentityHashSet();
- InstructionListIterator iterator = code.instructionListIterator();
+ CfCode code = method.getDefinition().getCode().asCfCode();
+ ListIterator<CfInstruction> iterator = code.getInstructions().listIterator();
+ boolean replaced = false;
while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
- if (!instruction.isInvokeMethod()) {
+ CfInvoke invoke = iterator.next().asInvoke();
+ if (invoke == null) {
continue;
}
-
- InvokeMethod invoke = instruction.asInvokeMethod();
- DexMethod invokedMethod = invoke.getInvokedMethod();
+ DexMethod invokedMethod = invoke.getMethod();
MethodProvider provider = getMethodProviderOrNull(invokedMethod);
if (provider != null) {
+ if (!replaced) {
+ // Create mutable instructions on first write.
+ ArrayList<CfInstruction> mutableInstructions = new ArrayList<>(code.getInstructions());
+ code.setInstructions(mutableInstructions);
+ iterator = mutableInstructions.listIterator(iterator.previousIndex());
+ iterator.next();
+ }
provider.rewriteInvoke(
- invoke, iterator, code, appView, affectedValues, synthesizedMethods::add);
+ invoke, iterator, method.getHolder(), appInfo, synthesizedMethods::add);
+ replaced = true;
}
}
- if (!affectedValues.isEmpty()) {
- new TypeAnalysis(appView).narrowing(affectedValues);
- }
+ return replaced;
}
public void processSynthesizedClasses(IRConverter converter, ExecutorService executor)
@@ -245,7 +247,7 @@
name = factory.createString("compare");
proto = factory.createProto(factory.intType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, LongMethodRewrites::rewriteCompare));
+ addProvider(new InvokeRewriter(method, LongMethodRewrites.rewriteCompare()));
// Boolean
type = factory.boxedBooleanType;
@@ -290,7 +292,7 @@
name = factory.createString("hash");
proto = factory.createProto(factory.intType, factory.objectArrayType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, ObjectsMethodRewrites::rewriteToArraysHashCode));
+ addProvider(new InvokeRewriter(method, ObjectsMethodRewrites.rewriteToArraysHashCode()));
// int Objects.hashCode(Object o)
name = factory.createString("hashCode");
@@ -300,7 +302,7 @@
// T Objects.requireNonNull(T obj)
method = factory.objectsMethods.requireNonNull;
- addProvider(new InvokeRewriter(method, ObjectsMethodRewrites::rewriteRequireNonNull));
+ addProvider(new InvokeRewriter(method, ObjectsMethodRewrites.rewriteRequireNonNull()));
// T Objects.requireNonNull(T obj, String message)
name = factory.createString("requireNonNull");
@@ -357,7 +359,7 @@
DexString name = factory.createString("hashCode");
DexProto proto = factory.createProto(factory.intType, factory.byteType);
DexMethod method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteAsIdentity));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
// Short
type = factory.boxedShortType;
@@ -365,7 +367,7 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.shortType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteAsIdentity));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
// Integer
type = factory.boxedIntType;
@@ -374,25 +376,25 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteAsIdentity));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
// int Integer.max(int a, int b)
name = factory.createString("max");
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// int Integer.min(int a, int b)
name = factory.createString("min");
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// int Integer.sum(int a, int b)
name = factory.createString("sum");
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToAddInstruction));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToAddInstruction()));
// Double
type = factory.boxedDoubleType;
@@ -407,19 +409,19 @@
name = factory.createString("max");
proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// double Double.min(double a, double b)
name = factory.createString("min");
proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// double Double.sum(double a, double b)
name = factory.createString("sum");
proto = factory.createProto(factory.doubleType, factory.doubleType, factory.doubleType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToAddInstruction));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToAddInstruction()));
// boolean Double.isFinite(double a)
name = factory.createString("isFinite");
@@ -434,25 +436,25 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, FloatMethodRewrites::rewriteHashCode));
+ addProvider(new InvokeRewriter(method, FloatMethodRewrites.rewriteHashCode()));
// float Float.max(float a, float b)
name = factory.createString("max");
proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// float Float.min(float a, float b)
name = factory.createString("min");
proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// float Float.sum(float a, float b)
name = factory.createString("sum");
proto = factory.createProto(factory.floatType, factory.floatType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToAddInstruction));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToAddInstruction()));
// boolean Float.isFinite(float a)
name = factory.createString("isFinite");
@@ -473,19 +475,19 @@
name = factory.createString("logicalAnd");
proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, BooleanMethodRewrites::rewriteLogicalAnd));
+ addProvider(new InvokeRewriter(method, BooleanMethodRewrites.rewriteLogicalAnd()));
// boolean Boolean.logicalOr(boolean a, boolean b)
name = factory.createString("logicalOr");
proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, BooleanMethodRewrites::rewriteLogicalOr));
+ addProvider(new InvokeRewriter(method, BooleanMethodRewrites.rewriteLogicalOr()));
// boolean Boolean.logicalXor(boolean a, boolean b)
name = factory.createString("logicalXor");
proto = factory.createProto(factory.booleanType, factory.booleanType, factory.booleanType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, BooleanMethodRewrites::rewriteLogicalXor));
+ addProvider(new InvokeRewriter(method, BooleanMethodRewrites.rewriteLogicalXor()));
// Long
type = factory.boxedLongType;
@@ -500,19 +502,19 @@
name = factory.createString("max");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// long Long.min(long a, long b)
name = factory.createString("min");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToInvokeMath));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToInvokeMath()));
// long Long.sum(long a, long b)
name = factory.createString("sum");
proto = factory.createProto(factory.longType, factory.longType, factory.longType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteToAddInstruction));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteToAddInstruction()));
// Character
type = factory.boxedCharType;
@@ -521,7 +523,7 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.charType);
method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, NumericMethodRewrites::rewriteAsIdentity));
+ addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
// Objects
type = factory.objectsType;
@@ -913,7 +915,7 @@
method = factory.createMethod(type, proto, name);
addProvider(
i == 0
- ? new InvokeRewriter(method, CollectionMethodRewrites::rewriteListOfEmpty)
+ ? new InvokeRewriter(method, CollectionMethodRewrites.rewriteListOfEmpty())
: new MethodGenerator(
method,
(options, methodArg) ->
@@ -934,7 +936,7 @@
method = factory.createMethod(type, proto, name);
addProvider(
i == 0
- ? new InvokeRewriter(method, CollectionMethodRewrites::rewriteSetOfEmpty)
+ ? new InvokeRewriter(method, CollectionMethodRewrites.rewriteSetOfEmpty())
: new MethodGenerator(
method,
(options, methodArg) ->
@@ -954,7 +956,7 @@
method = factory.createMethod(type, proto, name);
addProvider(
i == 0
- ? new InvokeRewriter(method, CollectionMethodRewrites::rewriteMapOfEmpty)
+ ? new InvokeRewriter(method, CollectionMethodRewrites.rewriteMapOfEmpty())
: new MethodGenerator(
method,
(options, methodArg) ->
@@ -1221,10 +1223,10 @@
};
MethodInvokeRewriter[] rewriters =
new MethodInvokeRewriter[] {
- OptionalMethodRewrites::rewriteOrElseGet,
- OptionalMethodRewrites::rewriteDoubleOrElseGet,
- OptionalMethodRewrites::rewriteLongOrElseGet,
- OptionalMethodRewrites::rewriteIntOrElseGet,
+ OptionalMethodRewrites.rewriteOrElseGet(),
+ OptionalMethodRewrites.rewriteDoubleOrElseGet(),
+ OptionalMethodRewrites.rewriteLongOrElseGet(),
+ OptionalMethodRewrites.rewriteIntOrElseGet(),
};
DexString name = factory.createString("orElseThrow");
for (int i = 0; i < optionalTypes.length; i++) {
@@ -1291,11 +1293,10 @@
}
public abstract void rewriteInvoke(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- IRCode code,
- AppView<?> appView,
- Set<Value> affectedValues,
+ CfInvoke invoke,
+ ListIterator<CfInstruction> iterator,
+ DexProgramClass context,
+ AppInfoWithClassHierarchy appInfo,
Consumer<ProgramMethod> registerSynthesizedMethod);
}
@@ -1310,14 +1311,12 @@
@Override
public void rewriteInvoke(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- IRCode code,
- AppView<?> appView,
- Set<Value> affectedValues,
+ CfInvoke invoke,
+ ListIterator<CfInstruction> iterator,
+ DexProgramClass context,
+ AppInfoWithClassHierarchy appInfo,
Consumer<ProgramMethod> registerSynthesizedMethod) {
- rewriter.rewrite(invoke, iterator, appView.dexItemFactory(), affectedValues);
- assert code.isConsistentSSA();
+ rewriter.rewrite(invoke, iterator, appInfo.dexItemFactory());
}
}
@@ -1338,34 +1337,33 @@
@Override
public void rewriteInvoke(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- IRCode code,
- AppView<?> appView,
- Set<Value> affectedValues,
+ CfInvoke invoke,
+ ListIterator<CfInstruction> iterator,
+ DexProgramClass context,
+ AppInfoWithClassHierarchy appInfo,
Consumer<ProgramMethod> registerSynthesizedMethod) {
- ProgramMethod method =
- appView
- .getSyntheticItems()
- .createMethod(
- code.context().getHolder(),
- appView.dexItemFactory(),
- builder ->
- builder
- .setProto(getProto(appView.dexItemFactory()))
- .setAccessFlags(
- MethodAccessFlags.fromSharedAccessFlags(
- Constants.ACC_PUBLIC
- | Constants.ACC_STATIC
- | Constants.ACC_SYNTHETIC,
- false))
- .setCode(
- methodSig -> generateTemplateMethod(appView.options(), methodSig)));
-
- iterator.replaceCurrentInstruction(
- new InvokeStatic(method.getReference(), invoke.outValue(), invoke.inValues()));
-
+ ProgramMethod method = getSyntheticMethod(context, appInfo);
registerSynthesizedMethod.accept(method);
+ iterator.remove();
+ iterator.add(new CfInvoke(Opcodes.INVOKESTATIC, method.getReference(), false));
+ }
+
+ private ProgramMethod getSyntheticMethod(
+ DexProgramClass context, AppInfoWithClassHierarchy appInfo) {
+ return appInfo
+ .getSyntheticItems()
+ .createMethod(
+ context,
+ appInfo.dexItemFactory(),
+ builder ->
+ builder
+ .setProto(getProto(appInfo.dexItemFactory()))
+ .setAccessFlags(
+ MethodAccessFlags.fromSharedAccessFlags(
+ Constants.ACC_PUBLIC | Constants.ACC_STATIC | Constants.ACC_SYNTHETIC,
+ false))
+ .setCode(
+ methodSig -> generateTemplateMethod(appInfo.app().options, methodSig)));
}
public DexProto getProto(DexItemFactory itemFactory) {
@@ -1401,12 +1399,27 @@
CfCode create(InternalOptions options, DexMethod method);
}
- private interface MethodInvokeRewriter {
+ public interface MethodInvokeRewriter {
- void rewrite(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues);
+ CfInstruction rewriteSingle(CfInvoke invoke, DexItemFactory factory);
+
+ // Convenience wrapper since most rewrites are to a single instruction.
+ default void rewrite(
+ CfInvoke invoke, ListIterator<CfInstruction> iterator, DexItemFactory factory) {
+ iterator.remove();
+ iterator.add(rewriteSingle(invoke, factory));
+ }
+ }
+
+ public abstract static class FullMethodInvokeRewriter implements MethodInvokeRewriter {
+
+ @Override
+ public final CfInstruction rewriteSingle(CfInvoke invoke, DexItemFactory factory) {
+ throw new Unreachable();
+ }
+
+ @Override
+ public abstract void rewrite(
+ CfInvoke invoke, ListIterator<CfInstruction> iterator, DexItemFactory factory);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BooleanMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BooleanMethodRewrites.java
index 90654b2..ec0a554 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BooleanMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BooleanMethodRewrites.java
@@ -4,52 +4,27 @@
package com.android.tools.r8.ir.desugar.backports;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.And;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.cf.code.CfLogicalBinop;
+import com.android.tools.r8.cf.code.CfLogicalBinop.Opcode;
import com.android.tools.r8.ir.code.NumericType;
-import com.android.tools.r8.ir.code.Or;
-import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.code.Xor;
-import java.util.List;
-import java.util.Set;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
public final class BooleanMethodRewrites {
- public static void rewriteLogicalAnd(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> inValues = invoke.inValues();
- assert inValues.size() == 2;
- iterator.replaceCurrentInstruction(
- new And(NumericType.INT, invoke.outValue(), inValues.get(0), inValues.get(1)));
+ private static MethodInvokeRewriter createRewriter(CfLogicalBinop.Opcode op) {
+ return (invoke, factory) -> new CfLogicalBinop(op, NumericType.INT);
}
- public static void rewriteLogicalOr(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> inValues = invoke.inValues();
- assert inValues.size() == 2;
-
- iterator.replaceCurrentInstruction(
- new Or(NumericType.INT, invoke.outValue(), inValues.get(0), inValues.get(1)));
+ public static MethodInvokeRewriter rewriteLogicalAnd() {
+ return createRewriter(Opcode.And);
}
- public static void rewriteLogicalXor(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> inValues = invoke.inValues();
- assert inValues.size() == 2;
+ public static MethodInvokeRewriter rewriteLogicalOr() {
+ return createRewriter(Opcode.Or);
+ }
- iterator.replaceCurrentInstruction(
- new Xor(NumericType.INT, invoke.outValue(), inValues.get(0), inValues.get(1)));
+ public static MethodInvokeRewriter rewriteLogicalXor() {
+ return createRewriter(Opcode.Xor);
}
private BooleanMethodRewrites() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodRewrites.java
index 354040f..64c94c5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/CollectionMethodRewrites.java
@@ -4,54 +4,31 @@
package com.android.tools.r8.ir.desugar.backports;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.graph.DexMethod;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.Value;
-import java.util.Collections;
-import java.util.Set;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import org.objectweb.asm.Opcodes;
public final class CollectionMethodRewrites {
private CollectionMethodRewrites() {}
- public static void rewriteListOfEmpty(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- rewriteToCollectionMethod(invoke, iterator, factory, "emptyList");
+ public static MethodInvokeRewriter rewriteListOfEmpty() {
+ return rewriteToCollectionMethod("emptyList");
}
- public static void rewriteSetOfEmpty(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- rewriteToCollectionMethod(invoke, iterator, factory, "emptySet");
+ public static MethodInvokeRewriter rewriteSetOfEmpty() {
+ return rewriteToCollectionMethod("emptySet");
}
- public static void rewriteMapOfEmpty(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- rewriteToCollectionMethod(invoke, iterator, factory, "emptyMap");
+ public static MethodInvokeRewriter rewriteMapOfEmpty() {
+ return rewriteToCollectionMethod("emptyMap");
}
- private static void rewriteToCollectionMethod(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- String methodName) {
- assert invoke.inValues().isEmpty();
-
- DexMethod collectionsEmptyList =
- factory.createMethod(factory.collectionsType, invoke.getInvokedMethod().proto, methodName);
- InvokeStatic newInvoke =
- new InvokeStatic(collectionsEmptyList, invoke.outValue(), Collections.emptyList());
- iterator.replaceCurrentInstruction(newInvoke);
+ private static MethodInvokeRewriter rewriteToCollectionMethod(String methodName) {
+ return (invoke, factory) ->
+ new CfInvoke(
+ Opcodes.INVOKESTATIC,
+ factory.createMethod(factory.collectionsType, invoke.getMethod().proto, methodName),
+ false);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java
index 3601c51..8670d3b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java
@@ -4,29 +4,20 @@
package com.android.tools.r8.ir.desugar.backports;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.Value;
-import java.util.Set;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import org.objectweb.asm.Opcodes;
public final class FloatMethodRewrites {
private FloatMethodRewrites() {}
- public static void rewriteHashCode(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeStatic mathInvoke =
- new InvokeStatic(
+ public static MethodInvokeRewriter rewriteHashCode() {
+ return (invoke, factory) ->
+ new CfInvoke(
+ Opcodes.INVOKESTATIC,
factory.createMethod(
- factory.boxedFloatType, invoke.getInvokedMethod().proto, "floatToIntBits"),
- invoke.outValue(),
- invoke.inValues(),
+ factory.boxedFloatType, invoke.getMethod().proto, "floatToIntBits"),
false);
- iterator.replaceCurrentInstruction(mathInvoke);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/LongMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/LongMethodRewrites.java
index 348194b..5c29f81 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/LongMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/LongMethodRewrites.java
@@ -4,28 +4,16 @@
package com.android.tools.r8.ir.desugar.backports;
-import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.Cmp;
+import com.android.tools.r8.cf.code.CfCmp;
import com.android.tools.r8.ir.code.Cmp.Bias;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.NumericType;
-import com.android.tools.r8.ir.code.Value;
-import java.util.List;
-import java.util.Set;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
public final class LongMethodRewrites {
private LongMethodRewrites() {}
- public static void rewriteCompare(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> inValues = invoke.inValues();
- assert inValues.size() == 2;
- iterator.replaceCurrentInstruction(
- new Cmp(NumericType.LONG, Bias.NONE, invoke.outValue(), inValues.get(0), inValues.get(1)));
+ public static MethodInvokeRewriter rewriteCompare() {
+ return (invoke, factory) -> new CfCmp(Bias.NONE, NumericType.LONG);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/NumericMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/NumericMethodRewrites.java
index 4a413bc..050aefa 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/NumericMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/NumericMethodRewrites.java
@@ -1,56 +1,44 @@
package com.android.tools.r8.ir.desugar.backports;
+import com.android.tools.r8.cf.code.CfArithmeticBinop;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.Add;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.ir.code.NumericType;
-import com.android.tools.r8.ir.code.Value;
-import java.util.List;
-import java.util.Set;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.FullMethodInvokeRewriter;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import java.util.ListIterator;
+import org.objectweb.asm.Opcodes;
public final class NumericMethodRewrites {
- public static void rewriteToInvokeMath(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeStatic mathInvoke =
- new InvokeStatic(
- factory.createMethod(
- factory.mathType, invoke.getInvokedMethod().proto, invoke.getInvokedMethod().name),
- invoke.outValue(),
- invoke.inValues(),
- false);
- iterator.replaceCurrentInstruction(mathInvoke);
+
+ public static MethodInvokeRewriter rewriteToInvokeMath() {
+ return (invoke, factory) -> {
+ DexMethod method = invoke.getMethod();
+ return new CfInvoke(
+ Opcodes.INVOKESTATIC,
+ factory.createMethod(factory.mathType, method.proto, method.name),
+ false);
+ };
}
- public static void rewriteToAddInstruction(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> values = invoke.inValues();
- assert values.size() == 2;
-
- NumericType numericType = NumericType.fromDexType(invoke.getReturnType());
- Add add = new Add(numericType, invoke.outValue(), values.get(0), values.get(1));
- iterator.replaceCurrentInstruction(add);
+ public static MethodInvokeRewriter rewriteToAddInstruction() {
+ return (invoke, factory) -> {
+ NumericType numericType = NumericType.fromDexType(invoke.getMethod().getReturnType());
+ return new CfArithmeticBinop(CfArithmeticBinop.Opcode.Add, numericType);
+ };
}
- public static void rewriteAsIdentity(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- List<Value> values = invoke.inValues();
- assert values.size() == 1;
- if (invoke.hasOutValue()) {
- invoke.outValue().replaceUsers(values.get(0));
- }
- // TODO(b/152853271): Debugging information is lost here (DebugLocalWrite may be required).
- iterator.removeOrReplaceByDebugLocalRead();
+ public static MethodInvokeRewriter rewriteAsIdentity() {
+ return new FullMethodInvokeRewriter() {
+ @Override
+ public void rewrite(
+ CfInvoke invoke, ListIterator<CfInstruction> iterator, DexItemFactory factory) {
+ // The invoke consumes the stack value and pushes another assumed to be the same.
+ iterator.remove();
+ }
+ };
}
private NumericMethodRewrites() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
index de16e98..69253be 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/ObjectsMethodRewrites.java
@@ -4,43 +4,41 @@
package com.android.tools.r8.ir.desugar.backports;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfStackInstruction;
+import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
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.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.InvokeVirtual;
-import com.android.tools.r8.ir.code.Value;
-import java.util.Set;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.FullMethodInvokeRewriter;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import java.util.ListIterator;
+import org.objectweb.asm.Opcodes;
public final class ObjectsMethodRewrites {
- public static void rewriteToArraysHashCode(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- DexType arraysType = factory.createType(factory.arraysDescriptor);
- DexMethod hashCodeMethod =
- factory.createMethod(arraysType, invoke.getInvokedMethod().proto, "hashCode");
- InvokeStatic arraysHashCode =
- new InvokeStatic(hashCodeMethod, invoke.outValue(), invoke.inValues(), false);
- iterator.replaceCurrentInstruction(arraysHashCode);
+ public static MethodInvokeRewriter rewriteToArraysHashCode() {
+ return (invoke, factory) -> {
+ DexType arraysType = factory.createType(factory.arraysDescriptor);
+ return new CfInvoke(
+ Opcodes.INVOKESTATIC,
+ factory.createMethod(arraysType, invoke.getMethod().proto, "hashCode"),
+ false);
+ };
}
- public static void rewriteRequireNonNull(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getClass =
- new InvokeVirtual(factory.objectMembers.getClass, null, invoke.inValues());
- if (invoke.hasOutValue()) {
- affectedValues.addAll(invoke.outValue().affectedValues());
- invoke.outValue().replaceUsers(invoke.inValues().get(0));
- invoke.setOutValue(null);
- }
- iterator.replaceCurrentInstruction(getClass);
+ public static MethodInvokeRewriter rewriteRequireNonNull() {
+ return new FullMethodInvokeRewriter() {
+
+ @Override
+ public void rewrite(
+ CfInvoke invoke, ListIterator<CfInstruction> iterator, DexItemFactory factory) {
+ iterator.remove();
+ // requireNonNull returns the operand, so dup top-of-stack, do getClass and pop the class.
+ iterator.add(new CfStackInstruction(Opcode.Dup));
+ iterator.add(new CfInvoke(Opcodes.INVOKEVIRTUAL, factory.objectMembers.getClass, false));
+ iterator.add(new CfStackInstruction(Opcode.Pop));
+ }
+ };
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/OptionalMethodRewrites.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/OptionalMethodRewrites.java
index 1334c62..d66d7f5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/OptionalMethodRewrites.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/OptionalMethodRewrites.java
@@ -4,69 +4,40 @@
package com.android.tools.r8.ir.desugar.backports;
+import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.graph.DexItemFactory;
-import com.android.tools.r8.ir.code.InstructionListIterator;
-import com.android.tools.r8.ir.code.InvokeMethod;
-import com.android.tools.r8.ir.code.InvokeVirtual;
-import com.android.tools.r8.ir.code.Value;
-import java.util.Set;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.BackportedMethodRewriter.MethodInvokeRewriter;
+import java.util.function.Function;
+import org.objectweb.asm.Opcodes;
public final class OptionalMethodRewrites {
private OptionalMethodRewrites() {}
- public static void rewriteOrElseGet(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getInvoke =
- new InvokeVirtual(
- factory.createMethod(factory.optionalType, invoke.getInvokedMethod().proto, "get"),
- invoke.outValue(),
- invoke.inValues());
- iterator.replaceCurrentInstruction(getInvoke);
+ private static MethodInvokeRewriter createRewriter(
+ Function<DexItemFactory, DexType> holderTypeSupplier, String methodName) {
+ return (invoke, factory) ->
+ new CfInvoke(
+ Opcodes.INVOKEVIRTUAL,
+ factory.createMethod(
+ holderTypeSupplier.apply(factory), invoke.getMethod().proto, methodName),
+ false);
}
- public static void rewriteDoubleOrElseGet(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getInvoke =
- new InvokeVirtual(
- factory.createMethod(
- factory.optionalDoubleType, invoke.getInvokedMethod().proto, "getAsDouble"),
- invoke.outValue(),
- invoke.inValues());
- iterator.replaceCurrentInstruction(getInvoke);
+ public static MethodInvokeRewriter rewriteOrElseGet() {
+ return createRewriter(factory -> factory.optionalType, "get");
}
- public static void rewriteIntOrElseGet(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getInvoke =
- new InvokeVirtual(
- factory.createMethod(
- factory.optionalIntType, invoke.getInvokedMethod().proto, "getAsInt"),
- invoke.outValue(),
- invoke.inValues());
- iterator.replaceCurrentInstruction(getInvoke);
+ public static MethodInvokeRewriter rewriteDoubleOrElseGet() {
+ return createRewriter(factory -> factory.optionalDoubleType, "getAsDouble");
}
- public static void rewriteLongOrElseGet(
- InvokeMethod invoke,
- InstructionListIterator iterator,
- DexItemFactory factory,
- Set<Value> affectedValues) {
- InvokeVirtual getInvoke =
- new InvokeVirtual(
- factory.createMethod(
- factory.optionalLongType, invoke.getInvokedMethod().proto, "getAsLong"),
- invoke.outValue(),
- invoke.inValues());
- iterator.replaceCurrentInstruction(getInvoke);
+ public static MethodInvokeRewriter rewriteIntOrElseGet() {
+ return createRewriter(factory -> factory.optionalIntType, "getAsInt");
+ }
+
+ public static MethodInvokeRewriter rewriteLongOrElseGet() {
+ return createRewriter(factory -> factory.optionalLongType, "getAsLong");
}
}
diff --git a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
index f5c75aa..67721e4 100644
--- a/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunArtTestsTest.java
@@ -642,7 +642,7 @@
"530-checker-lse2",
TestCondition.match(
TestCondition.tools(DexTool.DX),
- TestCondition.compilers(CompilerUnderTest.D8),
+ TestCondition.compilers(CompilerUnderTest.R8, CompilerUnderTest.D8),
TestCondition.runtimesUpTo(DexVm.Version.V6_0_1)))
.put(
"534-checker-bce-deoptimization",