MethodHandle.bindTo chain fails with "IllegalArgumentException: no leading reference parameter"
Tobias Hartmann
tobias.hartmann at oracle.com
Wed Jul 26 08:11:45 UTC 2017
Thanks Vladimir and Maurizio for looking into this.
On 26.07.2017 01:46, Maurizio Cimadamore wrote:
> I first thought of it as a javac bug, but now I'm less sure. I mean, yes, it's buggy, but the root of the problem here is that javac doesn't know how to 'box a value'. Note that this is a true 'Valhalla value', not an MVT one, so there's no POJO to fall back to. We could have javac generate some 'vbox' before storing the value in the array, but that would not achieve much, I think - as vbox/vubox specifically rely on the duality between value-capable-class and derived-value-class that's builtin in MVT. W/o MVT there's no such duality and, as a consequence, no easy way to 'box' a value.
>
> Some approaches that have been discussed in the past were either let the VM to synthesize a box for a value, or (preferred approach) have javac to generate it - while I don't object for such experimental work to be carried out somewhere, I'm not sure that this work truly belongs to the MVT branch - where value class declaration with __ByValue is there more in order to aid test development.
Right, I agree that this is out of scope for MVT.
> So I'd reluctantly suggest that this is a test bug. The test is uncovering a well known issue with general support for value types in the language (how to do boxing?) but that has little to do with MVT itself.
Yes, I'll use a DVT for the test.
Thanks,
Tobias
> On 25/07/17 19:00, Vladimir Ivanov wrote:
>>> If you are using value types straight from source code (e.g. __Value), then yes, this appears to be a problem in javac. However, if you are just using value-capable classes, then javac shouldn't have much say in what you are trying to do, so, if that's the case it would point more in the MH direction.
>>
>> It's the former case. The exception is thrown from javac-generated code.
>>
>> MethodHandle mh2 = MethodHandles.insertArguments(mh1, 0, test_vt);
>>
>> is translated into:
>>
>> 11: anewarray #7 // class java/lang/Object
>> ...
>> 17: getfield #3 // Field test_vt:QMyValue1;
>> 20: aastore
>> 21: invokestatic #8 // Method java/lang/invoke/MethodHandles.insertArguments:(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;
>>
>> where test_vt is a Q-typed field:
>>
>> MyValue1 test_vt = MyValue1.createDefaultInline();
>>
>> __ByValue final class MyValue1 {
>> ...
>> __ValueFactory static MyValue1 createDefaultInline() {
>> return __MakeDefault MyValue1();
>> }
>> }
>>
>> aastore @ 20 tries to write a Q-typed value (loaded from test_vt) into Object[] before passing it into MethodHandles.insertArguments() which is vararg method.
>>
>> I'd expect test_vt to be boxed first.
>>
>> Best regards,
>> Vladimir Ivanov
>>
>>
>>>
>>> Maurizio
>>>
>>>
>>> On 25/07/17 18:21, Vladimir Ivanov wrote:
>>>>> Changing
>>>>> MethodHandle mh2 = mh1.bindTo(test_vt);
>>>>> to
>>>>> MethodHandle mh2 = MethodHandles.insertArguments(mh1, 0, test_vt);
>>>>> fails with:
>>>>>
>>>>> Exception in thread "main" java.lang.ArrayStoreException: MyValue1
>>>>> at Test.test(Test.java:35)
>>>>> at Test.main(Test.java:41)
>>>>>
>>>>> Why's that?
>>>>
>>>> I'd say it's a problem in javac with auto-boxing of Q-types when calling vararg methods.
>>>>
>>>> It tries to store a Q-typed value into an Object[] which generates an ArrayStoreException:
>>>>
>>>> long test() throws java.lang.Throwable;
>>>> ...
>>>> 10: iconst_1
>>>> 11: anewarray #7 // class java/lang/Object
>>>> 14: dup
>>>> 15: iconst_0
>>>> 16: aload_0
>>>> 17: getfield #3 // Field test_vt:QMyValue1;
>>>> 20: aastore
>>>> 21: invokestatic #8 // Method java/lang/invoke/MethodHandles.insertArguments:(Ljava/lang/invoke/MethodHandle;I[Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;
>>>>
>>>> Best regards,
>>>> Vladimir Ivanov
>>>
>
More information about the valhalla-dev
mailing list