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

Brian Goetz brian.goetz at oracle.com
Thu Nov 29 16:25:03 UTC 2018


MemberName calls them type and invocationType; unfortunately, what 
MethodHandle calls type() is the invocation type, and this seems pretty 
natural for MethodHandle (what else are you going to do with a MH, 
except invoke it?)  Which suggests either:

  - MHDesc has a method called type(), and it is also be the invocation 
type;
  - MHDesc has no method called type(), but instead has invocationType() 
and lookupType(), or some other better name.

I think the latter is probably safer.

Now, what should the lookupType() be?  There's again two ways to go:
  - Return a ClassDesc for field ops, and a MethodTypeDesc for method ops;
  - Return a MethodTypeDesc for both

The latter is nicer from an API design perspective (there's a single 
type), but less nice for those who want to use the API.

Michael has already given one example of where you'd want to use this -- 
when calling ASM.  Here, there's lots of gymanstics needed to turn the 
method type into the right thing.

Another is if you want to feed a MHDesc back into the lookup methods:

     MHDesc.of(mhd.kind(), mhd.owner(), mhd.name(), mhd.lookupType())



On 11/23/2018 5:05 PM, John Rose wrote:
> I think MemberName calls them type and invocationType. That seems like a good division of labor to me, but then I wrote it. :-)
>
>> On Nov 20, 2018, at 3:26 PM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>>
>> 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