RFR: 8324433: Introduce a way to determine if an expression is evaluated as a constant by the Jit compiler [v6]
Aleksey Shipilev
shade at openjdk.org
Thu Jan 25 15:36:39 UTC 2024
On Thu, 25 Jan 2024 14:48:16 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:
> I don't 100% buy the `MethodHandleImpl` analogy. In that case the check is not simply used to save a branch, but to spare spinning of a completely new lambda form.
Doing this to save a few intructions would not likely to worth the hassle outside the _really performance critical paths_, but even then it might be useful for hot JDK code. On larger examples, you can avoid memory accesses, allocations, etc. by coding up the constant-foldable path that you know compiler would not be able to extract when propagating constants through the generic code. For example, giving quantitative substance to my previous example:
diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java
index 1c5b3c414ba..d50748c369e 100644
--- a/src/java.base/share/classes/java/lang/Integer.java
+++ b/src/java.base/share/classes/java/lang/Integer.java
@@ -28,4 +28,5 @@
import jdk.internal.misc.CDS;
import jdk.internal.misc.VM;
+import jdk.internal.vm.ConstantSupport;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.IntrinsicCandidate;
@@ -416,4 +417,7 @@ private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int l
}
+ @Stable
+ static final String[] TO_STRINGS = { "-1", "0", "1" };
+
/**
* Returns a {@code String} object representing the
@@ -428,4 +432,8 @@ private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int l
@IntrinsicCandidate
public static String toString(int i) {
+ if (ConstantSupport.isCompileConstant(i) &&
+ (i >= -1) && (i <= 1)) {
+ return TO_STRINGS[i + 1];
+ }
int size = stringSize(i);
if (COMPACT_STRINGS) {
diff --git a/test/micro/org/openjdk/bench/java/lang/Integers.java b/test/micro/org/openjdk/bench/java/lang/Integers.java
index 43ceb5d18d2..28248593a73 100644
--- a/test/micro/org/openjdk/bench/java/lang/Integers.java
+++ b/test/micro/org/openjdk/bench/java/lang/Integers.java
@@ -91,4 +91,18 @@ public void decode(Blackhole bh) {
}
+ @Benchmark
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public String toStringConstYay() {
+ return Integer.toString(0);
+ }
+
+ int v = 0;
+
+ @Benchmark
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public String toStringConstNope() {
+ return Integer.toString(v);
+ }
+
/** Performs toString on small values, just a couple of digits. */
@Benchmark
Benchmark (size) Mode Cnt Score Error Units
Integers.toStringConstNope 500 avgt 15 3,599 ? 0,034 ns/op
Integers.toStringConstNope:gc.alloc.rate.norm 500 avgt 15 48,000 ? 0,001 B/op
Integers.toStringConstNope:gc.time 500 avgt 15 223,000 ms
Integers.toStringConstYay 500 avgt 15 0,568 ? 0,046 ns/op
Integers.toStringConstYay:gc.alloc.rate.norm 500 avgt 15 ? 10?? B/op
Think about it as simplifying/avoiding the need for full compiler intrinsics. I could, in principle, do this by intrinsifying `Integer.toString` completely, check the same `isCon`, and then either construct the access to some String constant, or arrange the call to actual toString slow path. That would not be as simple as doing the similar thing in plain Java, with just a little of compiler support in form of `ConstantSupport`.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/17527#issuecomment-1910449450
More information about the hotspot-compiler-dev
mailing list