MethodHandle.bindTo chain fails with "IllegalArgumentException: no leading reference parameter"

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Jul 25 23:46:11 UTC 2017


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.

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.

Maurizio


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