Fix AbstractReturnValue and number unboxing
Bug: b/307872552
Change-Id: Ie6ef8f268122c56c888fffa0b8833851bc33ceef
diff --git a/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescriptionMethodOptimizationInfoFixer.java b/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescriptionMethodOptimizationInfoFixer.java
index 2d536b4..77fef31 100644
--- a/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescriptionMethodOptimizationInfoFixer.java
+++ b/src/main/java/com/android/tools/r8/graph/RewrittenPrototypeDescriptionMethodOptimizationInfoFixer.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraint;
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraintFactory;
import com.android.tools.r8.ir.analysis.type.DynamicType;
+import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.enums.classification.EnumUnboxerMethodClassification;
import com.android.tools.r8.ir.optimize.info.CallSiteOptimizationInfo;
@@ -172,6 +173,23 @@
return dynamicType;
}
+ @Override
+ public AbstractValue fixupAbstractReturnValue(
+ AppView<AppInfoWithLiveness> appView, AbstractValue returnValue) {
+ if (!prototypeChanges.hasRewrittenReturnInfo()) {
+ return returnValue;
+ }
+ RewrittenTypeInfo rewrittenReturnInfo = prototypeChanges.getRewrittenReturnInfo();
+ if (rewrittenReturnInfo.getNewType().isPrimitiveType()) {
+ // This covers for number unboxing, however, enum unboxing should never have a single
+ // boxed primitive as return value.
+ if (returnValue.isSingleBoxedPrimitive()) {
+ return returnValue.asSingleBoxedPrimitive().toPrimitive(appView.abstractValueFactory());
+ }
+ }
+ return returnValue;
+ }
+
private BitSet fixupArgumentInfo(BitSet bitSet) {
if (getArgumentInfoCollection().isEmpty() || bitSet == null) {
return bitSet;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfoFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfoFixer.java
index 9f75f68..c90d850 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfoFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/DefaultMethodOptimizationInfoFixer.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraint;
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraintFactory;
import com.android.tools.r8.ir.analysis.type.DynamicType;
+import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.enums.classification.EnumUnboxerMethodClassification;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
@@ -80,4 +81,10 @@
public DynamicType fixupDynamicType(DynamicType dynamicType) {
return dynamicType;
}
+
+ @Override
+ public AbstractValue fixupAbstractReturnValue(
+ AppView<AppInfoWithLiveness> appView, AbstractValue returnValue) {
+ return returnValue;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoFixer.java
index 764942d..06ef441 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoFixer.java
@@ -8,6 +8,7 @@
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraint;
import com.android.tools.r8.ir.analysis.inlining.SimpleInliningConstraintFactory;
import com.android.tools.r8.ir.analysis.type.DynamicType;
+import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.optimize.classinliner.constraint.ClassInlinerMethodConstraint;
import com.android.tools.r8.ir.optimize.enums.classification.EnumUnboxerMethodClassification;
import com.android.tools.r8.ir.optimize.info.bridge.BridgeInfo;
@@ -47,4 +48,7 @@
public abstract BitSet fixupArguments(BitSet arguments);
public abstract DynamicType fixupDynamicType(DynamicType dynamicType);
+
+ public abstract AbstractValue fixupAbstractReturnValue(
+ AppView<AppInfoWithLiveness> appView, AbstractValue returnValue);
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
index 2a33935..602b555 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableMethodOptimizationInfo.java
@@ -160,6 +160,7 @@
.fixupBridgeInfo(fixer)
.fixupClassInlinerMethodConstraint(appView, fixer)
.fixupDynamicType(fixer)
+ .fixupAbstractReturnValue(appView, fixer)
.fixupEnumUnboxerMethodClassification(fixer)
.fixupInstanceInitializerInfo(appView, fixer)
.fixupNonNullParamOnNormalExits(fixer)
@@ -210,6 +211,15 @@
}
public MutableMethodOptimizationInfo fixupAbstractReturnValue(
+ AppView<AppInfoWithLiveness> appView, MethodOptimizationInfoFixer fixer) {
+ if (abstractReturnValue.isUnknown()) {
+ return this;
+ }
+ abstractReturnValue = fixer.fixupAbstractReturnValue(appView, abstractReturnValue);
+ return this;
+ }
+
+ public MutableMethodOptimizationInfo fixupAbstractReturnValue(
AppView<AppInfoWithLiveness> appView,
DexEncodedMethod method,
GraphLens lens,
diff --git a/src/test/java/com/android/tools/r8/numberunboxing/VirtualMethodsOverrideNumberUnboxingTest.java b/src/test/java/com/android/tools/r8/numberunboxing/VirtualMethodsOverrideNumberUnboxingTest.java
index b402cb1..67c4241 100644
--- a/src/test/java/com/android/tools/r8/numberunboxing/VirtualMethodsOverrideNumberUnboxingTest.java
+++ b/src/test/java/com/android/tools/r8/numberunboxing/VirtualMethodsOverrideNumberUnboxingTest.java
@@ -6,7 +6,7 @@
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -14,7 +14,6 @@
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
-import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import org.junit.Test;
@@ -49,19 +48,14 @@
.compile()
.inspect(this::assertUnboxing)
.run(parameters.getRuntime(), Main.class)
- .assertSuccessWithOutputLines("3", "1", "5", "0");
+ .assertSuccessWithOutputLines("3", "1", "43", "5", "0", "43");
}
private void assertUnboxed(MethodSubject methodSubject) {
assertThat(methodSubject, isPresent());
- MethodSignature originalSignature = methodSubject.getOriginalSignature();
- MethodSignature finalSignature = methodSubject.getFinalSignature().asMethodSignature();
- assertEquals("java.lang.Long", originalSignature.type);
- assertEquals("long", finalSignature.type);
- assertEquals("java.lang.Double", originalSignature.parameters[0]);
- assertEquals("double", finalSignature.parameters[0]);
- assertEquals("java.lang.Integer", originalSignature.parameters[1]);
- assertEquals("int", finalSignature.parameters[1]);
+ assertTrue(methodSubject.getProgramMethod().getParameter(0).isDoubleType());
+ assertTrue(methodSubject.getProgramMethod().getParameter(1).isIntType());
+ assertTrue(methodSubject.getProgramMethod().getReturnType().isLongType());
}
private void assertUnboxing(CodeInspector codeInspector) {
@@ -73,8 +67,10 @@
public static void main(String[] args) {
System.out.println(new Add().convert(1.3, 1) + 1L);
System.out.println(new Sub().convert(1.4, 2) + 1L);
+ System.out.println(new Cst().convert(1.4, 2) + 1L);
run(new Add());
run(new Sub());
+ run(new Cst());
}
@NeverInline
@@ -95,7 +91,6 @@
@Override
@NeverInline
public Long convert(Double d, Integer i) {
- System.out.print("");
return Long.valueOf((long) (d.doubleValue() + i.intValue()));
}
}
@@ -106,8 +101,17 @@
@Override
@NeverInline
public Long convert(Double d, Integer i) {
- System.out.print("");
return Long.valueOf((long) (d.doubleValue() - i.intValue()));
}
}
+
+ @NeverClassInline
+ @NoHorizontalClassMerging
+ static class Cst implements Top {
+ @Override
+ @NeverInline
+ public Long convert(Double d, Integer i) {
+ return Long.valueOf(42L);
+ }
+ }
}