Rewrite Float.hashCode to Float.floatToIntBits
Test: tools/test.py --dex_vm all --no-internal -v *Backport*Test*
Test: tools/test.py --no-internal -v *GenerateBackportMethods*
Change-Id: I5c35b420c0f54a6a4d43d84fa73c422c9006b3db
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 cbc2c64..730a743 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
@@ -31,6 +31,7 @@
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;
+import com.android.tools.r8.ir.desugar.backports.FloatMethodRewrites;
import com.android.tools.r8.ir.desugar.backports.ListMethodRewrites;
import com.android.tools.r8.ir.desugar.backports.LongMethodRewrites;
import com.android.tools.r8.ir.desugar.backports.NumericMethodRewrites;
@@ -481,7 +482,7 @@
name = factory.createString("hashCode");
proto = factory.createProto(factory.intType, factory.floatType);
method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::FloatMethods_hashCode));
+ addProvider(new InvokeRewriter(method, FloatMethodRewrites::rewriteHashCode));
// float Float.max(float a, float b)
name = factory.createString("max");
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
index 5046c2f..d9beda9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/BackportedMethods.java
@@ -712,31 +712,6 @@
ImmutableList.of());
}
- public static CfCode FloatMethods_hashCode(
- InternalOptions options, DexMethod method, String name) {
- CfLabel label0 = new CfLabel();
- CfLabel label1 = new CfLabel();
- return new CfCode(
- method.holder,
- 1,
- 1,
- ImmutableList.of(
- label0,
- new CfLoad(ValueType.FLOAT, 0),
- new CfInvoke(
- 184,
- options.itemFactory.createMethod(
- options.itemFactory.createType("Ljava/lang/Float;"),
- options.itemFactory.createProto(
- options.itemFactory.createType("I"), options.itemFactory.createType("F")),
- options.itemFactory.createString("floatToIntBits")),
- false),
- new CfReturn(ValueType.INT),
- label1),
- ImmutableList.of(),
- ImmutableList.of());
- }
-
public static CfCode FloatMethods_isFinite(
InternalOptions options, DexMethod method, String name) {
CfLabel label0 = new CfLabel();
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
new file mode 100644
index 0000000..9a4ef45
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/desugar/backports/FloatMethodRewrites.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.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;
+
+public final class FloatMethodRewrites {
+
+ private FloatMethodRewrites() {}
+
+ public static void rewriteHashCode(
+ InvokeMethod invoke, InstructionListIterator iterator, DexItemFactory factory) {
+ InvokeStatic mathInvoke = new InvokeStatic(
+ factory.createMethod(factory.boxedFloatType, invoke.getInvokedMethod().proto,
+ "floatToIntBits"), invoke.outValue(), invoke.inValues(), false);
+ iterator.replaceCurrentInstruction(mathInvoke);
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
index c61433b..6cd2bdf 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
@@ -19,8 +19,10 @@
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.io.IOException;
import java.nio.file.Path;
+import java.util.HashSet;
import java.util.List;
import java.util.NavigableMap;
+import java.util.Set;
import java.util.TreeMap;
import org.junit.Assert;
import org.junit.Test;
@@ -32,6 +34,7 @@
private final Path testJar;
private final String testClassName;
private final NavigableMap<AndroidApiLevel, Integer> invokeStaticCounts = new TreeMap<>();
+ private final Set<String> ignoredInvokes = new HashSet<>();
AbstractBackportTest(TestParameters parameters, Class<?> targetClass,
Class<?> testClass) {
@@ -68,6 +71,10 @@
invokeStaticCounts.put(apiLevel, invokeStaticCount);
}
+ void ignoreInvokes(String methodName) {
+ ignoredInvokes.add(methodName);
+ }
+
private void configureProgram(TestBuilder<?, ?> builder) throws IOException {
builder.addProgramClasses(MiniAssert.class, IgnoreInvokes.class);
if (testClass != null) {
@@ -106,6 +113,8 @@
.flatMap(MethodSubject::streamInstructions)
.filter(InstructionSubject::isInvoke)
.filter(is -> is.getMethod().holder.toSourceString().equals(targetClass.getName()))
+ // Do not count invokes if explicitly ignored.
+ .filter(is -> !ignoredInvokes.contains(is.getMethod().name.toString()))
.collect(toList());
AndroidApiLevel apiLevel = parameters.getRuntime().asDex().getMinApiLevel();
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/FloatBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/FloatBackportTest.java
index d20122b..d8c1f8d 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/FloatBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/FloatBackportTest.java
@@ -20,6 +20,7 @@
public FloatBackportTest(TestParameters parameters) {
super(parameters, Float.class, Main.class);
registerTarget(AndroidApiLevel.N, 10);
+ ignoreInvokes("floatToIntBits"); // Available in API 1, used to backport hashCode.
}
static final class Main extends MiniAssert {
diff --git a/src/test/java/com/android/tools/r8/ir/desugar/backports/FloatMethods.java b/src/test/java/com/android/tools/r8/ir/desugar/backports/FloatMethods.java
index 3b4932f..a452fea 100644
--- a/src/test/java/com/android/tools/r8/ir/desugar/backports/FloatMethods.java
+++ b/src/test/java/com/android/tools/r8/ir/desugar/backports/FloatMethods.java
@@ -6,10 +6,6 @@
public final class FloatMethods {
- public static int hashCode(float f) {
- return Float.floatToIntBits(f);
- }
-
public static boolean isFinite(float f) {
return !Float.isInfinite(f) && !Float.isNaN(f);
}