[jep-334] Asymmetric method types of MHD vs MH

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Nov 20 23:26:35 UTC 2018


I agree - there are two types: the one based on real classfile 
descriptor and the unified, curried one exposed by MethodHandle::type(). 
The former is used for lookup, the latter for invocation. Maybe 
lookupType() and invocationType() ?

Maurizio

On 20/11/2018 18:40, Brian Goetz wrote:
> There are actually two types here, and they both should be exposed.  
> One is a property of MHDesc (which is correctly called type()) which 
> describes the invocation type of the MH; the other is a propertly of 
> DirectMHDesc (which needs a new name) and which is the type that one 
> would provide to the lookup / place in the NameAndType. We're 
> currently in an inconsistent situation.
>
> On 11/20/2018 10:20 AM, Remi Forax wrote:
>> Hi Brian,
>> while i agree that the API is primarily a mirror the JVMS view and 
>> not the java.lang.invoke view,
>> one way to avoid that ambiguity is to rename methodType() to type() 
>> (as in NameAndType).
>>
>> Rémi
>>
>> ----- Mail original -----
>>> De: "Brian Goetz" <brian.goetz at oracle.com>
>>> À: "Michael van Acken" <michael.van.acken at gmail.com>, "amber-dev" 
>>> <amber-dev at openjdk.java.net>
>>> Envoyé: Mardi 20 Novembre 2018 14:28:06
>>> Objet: Re: [jep-334] Asymmetric method types of MHD vs MH
>>> Thanks for poking into these new APIs.  This is a good question.
>>>
>>> Your mental model is a good first-order approximation, but it has some
>>> risk; in the event of conflict, XxDesc's classes loyalty will be to
>>> Constant_Xxx_info (the classfile format), rather than its live-type
>>> counterpart.
>>>
>>> MethodHandle embeds the invocation mode (static, virtual, interface,
>>> special) in the MH itself, so that you can treat the receiver as just
>>> another parameter.  This is tremendously useful as the primary purpose
>>> of method handles is to be invoked; it collapse four invocation modes
>>> into one.
>>>
>>> DirectMethodHandleDesc models the classfile structure of an invocation;
>>> the MethodRef_info/NameAndType/invocation bytecode -- as shown in your
>>> example:
>>>
>>>      jshell> var mhd = (MethodHandleDesc)mh.describeConstable().get()
>>>      mhd ==> MethodHandleDesc[VIRTUAL/PrintStream::println()void]
>>>
>>> I think what you're saying is: there is enough information here to 
>>> correctly
>>> compose the type() -- for virtual/special/interface, curry the owner 
>>> type on --
>>> and that this would provide alignment with the live MethodHandle 
>>> behavior.
>>>
>>> But, it would separate from the classfile Constant_MethodHandle_info 
>>> behavior;
>>> what goes in the NameAndType here (for instance methods) is the 
>>> receiver-less
>>> version.  Hence the conflict.
>>>
>>> I think what is really going on here is that there are two types -- 
>>> the MH type,
>>> and the lookup type; the latter is a property of the DMHDesc, while 
>>> the former
>>> is a property of the MHDesc?
>>>
>>>
>>> On 11/20/2018 7:06 AM, Michael van Acken wrote:
>>>> While tracking down unexpected behavior in my compiler, I noticed that
>>>> MethodHandleDesc and MethodHandle differ in what they list in their
>>>> method type.  I was expecting that the MHD matches the MH, in that
>>>> the receiver of a virtual method is included in the parameter list.
>>>> Instead,
>>>> it is omitted.  (See below for a jshell example.)
>>>>
>>>> As a compiler writer, I find the MH's unified view on static and 
>>>> virtual
>>>> method types very helpful.  The current implementation's MHD class
>>>> does not mirror this view, which means I would have to special case 
>>>> the
>>>> method types for some operations.
>>>>
>>>> My mental model of the descriptor classes is, that they are one-to-one
>>>> symbolic representations of their handle counterparts.  I am very 
>>>> confused
>>>> by the difference in structure, with the receiver dropping out of the
>>>> method type.
>>>>
>>>>
>>>> |  Welcome to JShell -- Version 12-internal
>>>> |  For an introduction type: /help intro
>>>>
>>>> jshell> import java.lang.invoke.*
>>>>
>>>> jshell> import java.lang.constant.*
>>>>
>>>> jshell> var l = MethodHandles.lookup()
>>>> l ==>
>>>>
>>>> jshell> var mt = MethodType.methodType(Void.TYPE)
>>>> mt ==> ()void
>>>>
>>>> jshell> var mh = l.findVirtual(java.io.PrintStream.class, 
>>>> "println", mt)
>>>> mh ==> MethodHandle(PrintStream)void
>>>>
>>>> jshell> mh.type()
>>>> $6 ==> (PrintStream)void
>>>>
>>>> jshell> mh.type().parameterCount()
>>>> $7 ==> 1
>>>>
>>>> jshell> var mhd = (MethodHandleDesc)mh.describeConstable().get()
>>>> mhd ==> MethodHandleDesc[VIRTUAL/PrintStream::println()void]
>>>>
>>>> jshell> mhd.methodType()
>>>> $9 ==> MethodTypeDesc[()void]
>>>>
>>>> jshell> mhd.methodType().parameterCount()
>>>> $10 ==> 0
>>>>
>>>>
>>>> Regards,
>>>> Michael van Acken
>


More information about the amber-dev mailing list