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