[jep-334] Asymmetric method types of MHD vs MH
Michael van Acken
michael.van.acken at gmail.com
Fri Nov 30 08:27:06 UTC 2018
Brian Goetz <brian.goetz at oracle.com> schrieb am Do., 29. Nov. 2018 um
17:27 Uhr:
> 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 believe this would match the usage of invocationType() in
DynamicCallSiteDesc as well.
Is the distinction "invocationType() is a thing of the operand stack" while
"lookupType() is a thing of the constant pool" a useful mental model here?
>
> 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
>
My first association for "lookupType()" was the table of lookup.findXXX()
methods with its clear separation MethodType / Class here:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/invoke/MethodHandles.Lookup.html
> 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())
>
Looks to me like this could be made to work with lookupType() returning
either of String, TypeDescriptor, or MethodTypeDesc.
Trying to understand the implications, I have two questions:
What should the descriptorString overload of MHDesc.of() take e.g. for an
instance getter? In MHDesc.of(GETTER, clazz, name, X) the X could be
one of "(R)T", "()T", or "T". From my experience with ASM, I assume that
the field descriptor variant "T" is closest to both constant pool
representation
and lookup.findGetter(), but there seem to be reasons for all three of them.
Related to this: What is it of benefit in looking at a *field* DMHDesc
through
the lens of a method descriptor/MethodTypeDesc, outside of the point of
view offered by invocationType()?
-- Michael van Acken
>
>
> 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