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

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Sun Nov 25 21:34:17 UTC 2018


On 25/11/2018 21:29, Maurizio Cimadamore wrote:
>
>
> On 22/11/2018 07:21, Michael van Acken wrote:
>> Maurizio Cimadamore <maurizio.cimadamore at oracle.com 
>> <mailto:maurizio.cimadamore at oracle.com>> schrieb am Mi., 21. Nov. 
>> 2018 um 00:27 Uhr:
>>
>>     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() ?
>>
>>
>> To verify my understanding: this tentative lookupType() would return a
>> ClassDesc/TypeDescriptor.OfField for a field DMHDesc, and a
>> MethodTypeDesc/TypeDescriptor.OfMethod for a method DMHDesc.
>> Is this correct?
>
> That seems like a valid assumption to me
>
But, maybe I spoke too fast - in the MethodHandle API, calling type() 
give you a MethodType - so if we follow that, we should always return a 
MethodTypeDesc (with the right signature). Using TypeDescriptor.OfField 
is possible, but that would break symmetry with the MethodHandle API 
(its runtime equivalent would be a MethodHandle::type() method returning 
a j.l.Class<?> value).

So, maybe it's better to stick with different type accessors (for lookup 
and invocation type, however called) both returning some suitably typed 
MethodTypeDesc.

Maurizio

> Maurizio
>
>>
>> -- Michael van Acken
>>
>>
>>     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
>>     <mailto:brian.goetz at oracle.com>>
>>     >>> À: "Michael van Acken" <michael.van.acken at gmail.com
>>     <mailto:michael.van.acken at gmail.com>>, "amber-dev"
>>     >>> <amber-dev at openjdk.java.net <mailto: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
>>     <http://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