constantInstruction() & DynamicConstantDesc
Brian Goetz
brian.goetz at oracle.com
Mon Jul 18 13:06:08 UTC 2022
Thanks for the experience report!
You raised three issues:
- ConstantDescs.NULL
- Preservation of signed zero
- round-tripping of DCD
The signed zero definitely looks like a bug and we should fix it as per your patch.
Handling ConstantDescs.NULL is an interesting question. Since this is a “convenience” method (the user isn’t asking for a specific opcode, they’re saying “here’s a constant, do something”), either treatment of NULL is probably valid. If we do nothing, you’ll get a condy that evaluates to null, so you get the same runtime behavior, but then again we could LDC an integer constant of zero rather than iconst_0. So this is probably reasonable behavior to special-case NULL here.
I’ll look into the third one.
Thanks,
-Brian
> On Jul 18, 2022, at 5:36 AM, Michael van Acken <michael.van.acken at gmail.com> wrote:
>
> I just started to move my most recent Clojure compiler iteration to
> the Classfile API. It is a pleasure to use. I appreciate the huge
> amount of work that is going into this.
>
> While going through my constant handling tests I found three issues.
>
> First, I expected ConstantDescs.NULL to be mapped to ACONST_NULL. I
> can just as well special case this in the compiler, of course.
>
> Second, to get a test case for the literal constant -0.0 to round-trip
> I had to patch CodeBuilder.java to go via LDC:
>
> cause: expected not equivalent to actual value
> expected: [(LDC2_W -0.0) (DRETURN)]
> actual: [(DCONST_0 ) (DRETURN)]
>
> Third, a round-trip involving the describeConstable() of a Character
> instance (via ConstantDescs.BSM_EXPLICIT_CAST) was read back as a DCD
> with a nameAndType of "_":"LC;" instead of the expected "_":"C".
> Changing the ofCanonical invocation in ConcreteEntry.java fixed this
> particular case for me, but I am only fishing around here.
>
> The patch below has more details.
>
> -- mva
>
>
> diff --git a/src/java.base/share/classes/jdk/classfile/CodeBuilder.java b/src/java.base/share/classes/jdk/classfile/CodeBuilder.java
> index 154050ae8b4..330980af725 100755
> --- a/src/java.base/share/classes/jdk/classfile/CodeBuilder.java
> +++ b/src/java.base/share/classes/jdk/classfile/CodeBuilder.java
> @@ -27,6 +27,7 @@ package jdk.classfile;
>
> import java.lang.constant.ClassDesc;
> import java.lang.constant.ConstantDesc;
> +import java.lang.constant.ConstantDescs;
> import java.lang.constant.DirectMethodHandleDesc;
> import java.lang.constant.DynamicCallSiteDesc;
> import java.lang.constant.MethodTypeDesc;
> @@ -424,7 +425,7 @@ public sealed interface CodeBuilder
>
> default CodeBuilder constantInstruction(ConstantDesc value) {
> // This method must ensure any call to constant(Opcode, ConstantDesc) has a non-null Opcode.
> - if (value == null) {
> + if (value == null || ConstantDescs.NULL.equals(value)) {
> return constantInstruction(Opcode.ACONST_NULL, null);
> }
> else if (value instanceof Integer iVal) {
> @@ -437,16 +438,16 @@ public sealed interface CodeBuilder
> else
> return constantInstruction(Opcode.LDC2_W, lVal);
> } else if (value instanceof Float fVal) {
> - if (fVal == 0.0)
> + if (fVal.compareTo(0.0f) == 0) // 0.0f but not -0.0f
> return with(ConstantInstruction.ofIntrinsic(Opcode.FCONST_0));
> - else if (fVal == 1.0)
> + else if (fVal == 1.0f)
> return with(ConstantInstruction.ofIntrinsic(Opcode.FCONST_1));
> - else if (fVal == 2.0)
> + else if (fVal == 2.0f)
> return with(ConstantInstruction.ofIntrinsic(Opcode.FCONST_2));
> else
> return constantInstruction(Opcode.LDC, fVal);
> } else if (value instanceof Double dVal) {
> - if (dVal == 0.0d)
> + if (dVal.compareTo(0.0d) == 0) // 0.0d but not -0.0d
> return with(ConstantInstruction.ofIntrinsic(Opcode.DCONST_0));
> else if (dVal == 1.0d)
> return with(ConstantInstruction.ofIntrinsic(Opcode.DCONST_1));
> diff --git a/src/java.base/share/classes/jdk/classfile/impl/ConcreteEntry.java b/src/java.base/share/classes/jdk/classfile/impl/ConcreteEntry.java
> index bead58d7618..9dcc8eeb7e1 100755
> --- a/src/java.base/share/classes/jdk/classfile/impl/ConcreteEntry.java
> +++ b/src/java.base/share/classes/jdk/classfile/impl/ConcreteEntry.java
> @@ -797,7 +797,7 @@ public abstract sealed class ConcreteEntry {
> staticArgs[i] = args.get(i).constantValue();
>
> return DynamicConstantDesc.ofCanonical(bootstrap().bootstrapMethod().asSymbol(),
> - nameAndType().name().stringValue(), ClassDesc.of(Util.toClassString(Util.descriptorToClass(nameAndType().type().stringValue()))), staticArgs);
> + nameAndType().name().stringValue(), ClassDesc.ofDescriptor(nameAndType().type().stringValue()), staticArgs);
> }
> }
>
More information about the classfile-api-dev
mailing list