Constant descriptor resolved too soon during constant resolution?

Jorn Vernee jbvernee at xs4all.nl
Fri Aug 3 21:19:21 UTC 2018


Thanks for the response Maurizio!

> My feeling is that the BSM arg in bold above is wrong. That is a
> *live* method handle constant - e.g. of type MethodHandle, but that is
> not compatible with what the BSM expects (a ConstantDesc):

I have tested a few patches based on this observation, but I think that 
the MethodHandle type is correct after all. The reason 
`DynamicConstantDesc` needs `ConstantDesc`s as arguments is because it 
needs to know how to put them in the constant pool. In other words, you 
'expend' the descriptor when making a constant pool entry for it. You 
are left with a constant pool entry that you can turn into a live type 
(e.g. a MethodHandle), but that doesn't necessarily mean you can turn it 
_back_ into a descriptor.

There are a few other dynamic bootstraps for `Enum` and `VarHandle`. The 
`Enum` one expects `String`s, which are both descriptor and live object, 
and the `VarHandle` ones, like `j.l.i.ConstantBoostraps::fieldVarhandle` 
actually expect live types to be passed as arguments (`Class<?>` instead 
of `ClassDesc`). Also, `DynamicConstantDesc::resolveConstantDesc` 
resolves the descriptors before passing them to the bootstrap method. 
Since `DynamicConstantDesc::constantBootstrap` actually requires 
`ConstantDesc<?>`s as it's arguments, I think the real bug is in 
`DynamicConstantDesc::describeConstable`:

```
     @Override
     public Optional<? extends ConstantDesc<ConstantDesc<T>>> 
describeConstable() {
         ConstantDesc<?>[] args = new 
ConstantDesc<?>[bootstrapArgs.length + 5];
         args[0] = bootstrapMethod.owner().descriptorString();
         args[1] = bootstrapMethod.methodName();
         args[2] = bootstrapMethod.methodType().descriptorString();
         args[3] = constantName;
         args[4] = constantType.descriptorString();
         System.arraycopy(bootstrapArgs, 0, args, 5, 
bootstrapArgs.length);
         return 
Optional.of(DynamicConstantDesc.of(BSM_DYNAMICCONSTANTDESC, 
ConstantDescs.DEFAULT_NAME,
                                                   
CR_DynamicConstantDesc, args));
     }
```

Where the `args` array should still be turned into an array of 
descriptors that wrap the descriptors that are already there. This 
turn-into-descriptor already sneakily happens for the bootstrap method 
and name and type, since those are all being turned into `String`, which 
is it's own descriptor.

Brian told me in an earlier email that `ConstantDesc`s should also be 
able to describe themselves, so I think the only missing puzzle piece 
here is to add a method to `ConstantDesc` for that:

```
     ConstantDesc<? extends ConstantDesc<T>> describeSelf();
```

And then call that in the `DynamicConstantDesc::describeConstable` 
method, re-wrapping the descriptors:

```
     ConstantDesc<?>[] bootstrapArgDescs = 
Arrays.stream(bootstrapArgs).map(ConstantDesc::describeSelf).toArray(ConstantDesc[]::new); 
// describe the descriptors
     System.arraycopy(bootstrapArgDescs, 0, args, 5, 
bootstrapArgs.length); // using the descriptors instead
```

And then I think you can also drop the `implements 
Constable<ConstantDesc<...>>` from all the descriptor types.

I might look into making a patch for that later.

Jorn


More information about the amber-dev mailing list