[jep-334] Asymmetric method types of MHD vs MH
Brian Goetz
brian.goetz at oracle.com
Thu Nov 29 22:05:11 UTC 2018
Here's how I propose to resolve this.
Rename existing MHD.methodType() -> invocationType()
Add method DirectMHD.lookupType(), which supports the invariant
dmhd === MHD.of(dmhd.kind(), dmhd.owner(), dmhd.name(),
dmhd.lookupType())
On 11/29/2018 11:25 AM, Brian Goetz wrote:
> 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